Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | 9x 12x 12x 12x 1x 11x 5x 6x 2x 4x 1x 3x 2x 1x 12x 12x | import { Stack } from "@mui/material";
import {
MagnifyingGlassIcon,
PencilSimpleIcon,
StarIcon,
WarningCircleIcon,
XCircleIcon,
} from "@phosphor-icons/react";
import GiveText from "@shared/Text/GiveText";
import { styled, useAppTheme } from "@theme/v2/Provider";
import { ReviewRatingFilter } from "./review.types";
type Props = {
ratings: ReviewRatingFilter[];
awaitingReplyOnly: boolean;
/** True when the event has no reviews at all, filters and search aside. */
isUnfiltered: boolean;
/** The active search term, already trimmed; echoed back when it matched nothing. */
searchTerm?: string;
/** The side panel's card draws the same states in a 144px box. */
compact?: boolean;
/**
* The list read failed. Outranks every branch below: with no rows and no
* reason given, "No reviews yet" would report an outage as the merchant's
* customers having written nothing.
*/
isError?: boolean;
};
/**
* What fills the list column when nothing matches.
*
* The frames draw four different messages rather than one, because "nobody has
* reviewed this event" and "your 2-star filter matched nothing" are different
* facts and only one of them is worth acting on:
*
* - no reviews at all (frame 7878-60582's copy) — pencil
* - a search that matched nothing — magnifier, echoing the term
* - awaiting-reply only (frame 7508-75519) — pencil, "No reviews to reply to"
* - exactly one star filter (frame 7508-75946) — star, naming the rating
* - anything else (frame 7508-77120) — x-circle, "Please try removing the filters"
*
* ...and a read failure ahead of all of them, for callers with no room for the
* full error state — the panel's card. Every one of these messages lives here
* and only here, which is what keeps the tab and the card saying the same thing.
*
* The search branch comes before the filter ones on purpose: with a term typed
* and no chips on, "Please try removing the filters" names something that is
* not there and never mentions what was searched for.
*/
const EventReviewsEmptyState = ({
ratings,
awaitingReplyOnly,
isUnfiltered,
searchTerm,
compact,
isError,
}: Props) => {
const { palette } = useAppTheme();
const { Icon, title, description } = (() => {
if (isError) {
return {
Icon: WarningCircleIcon,
title: "Reviews couldn't be loaded",
description:
"Something went wrong on our side. Please try again in a moment.",
};
}
if (isUnfiltered) {
return {
Icon: PencilSimpleIcon,
title: "No reviews yet",
description:
"Your customers haven't left any reviews yet. Once they do, they'll appear here.",
};
}
if (searchTerm) {
return {
Icon: MagnifyingGlassIcon,
title: `No results for "${searchTerm}"`,
description:
ratings.length > 0 || awaitingReplyOnly
? "Please try a different search term or filter criteria"
: "Please try a different search term",
};
}
if (awaitingReplyOnly && ratings.length === 0) {
return {
Icon: PencilSimpleIcon,
title: "No reviews to reply to",
description: "When customers leave new reviews, they'll appear here.",
};
}
if (!awaitingReplyOnly && ratings.length === 1) {
return {
Icon: StarIcon,
title: `No ${ratings[0]}-star reviews found`,
description: `There are no customer reviews with a ${ratings[0]}-star rating`,
};
}
return {
Icon: XCircleIcon,
title: "No results",
description: "Please try removing the filters",
};
})();
return (
<Stack
alignItems="center"
justifyContent="center"
gap="20px"
paddingY={compact ? "20px" : "64px"}
height={compact ? "144px" : undefined}
data-testid={
isError ? "event-reviews-error-state" : "event-reviews-empty-state"
}
>
<IconCircle>
<Icon size={24} color={palette.icon?.["icon-primary"] as string} />
</IconCircle>
<Stack alignItems="center" gap="4px">
<GiveText variant="bodyM" color="primary">
{title}
</GiveText>
<GiveText variant="bodyS" color="secondary" textAlign="center">
{description}
</GiveText>
</Stack>
</Stack>
);
};
export default EventReviewsEmptyState;
const IconCircle = styled(Stack)(({ theme }) => ({
alignItems: "center",
justifyContent: "center",
width: "56px",
height: "56px",
borderRadius: "50%",
backgroundColor: theme.palette.primitive?.transparent["darken-5"],
}));
|