diff --git a/client/cms/src/components/events/event-grid.container.tsx b/client/cms/src/components/events/event-grid.container.tsx index d442978..926191d 100644 --- a/client/cms/src/components/events/event-grid.container.tsx +++ b/client/cms/src/components/events/event-grid.container.tsx @@ -1,8 +1,10 @@ import type { EventInfo } from './types'; +import { FileQuestionMark } from 'lucide-react'; import PlaceholderImage from '@/assets/event-placeholder.png'; import { useGetEvents } from '@/hooks/data/useGetEvents'; import { Button } from '../ui/button'; import { DialogTrigger } from '../ui/dialog'; +import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from '../ui/empty'; import { EventGridView } from './event-grid.view'; import { KycDialogContainer } from './kyc/kyc.dialog.container'; @@ -10,31 +12,48 @@ export function EventGridContainer() { const { data, isLoading } = useGetEvents(); const allEvents: EventInfo[] = isLoading ? [] - : data.pages.flatMap(page => page.data!).map(it => ({ - type: it.type! as EventInfo['type'], - eventId: it.event_id!, - isJoined: it.is_joined!, - requireKyc: it.enable_kyc!, - coverImage: it.thumbnail! || PlaceholderImage, - eventName: it.name!, - description: it.description!, - startTime: new Date(it.start_time!), - endTime: new Date(it.end_time!), - } satisfies EventInfo)); + : data.pages.flatMap(page => page.data ?? []).map(it => ({ + type: it.type! as EventInfo['type'], + eventId: it.event_id!, + isJoined: it.is_joined!, + requireKyc: it.enable_kyc!, + coverImage: it.thumbnail! || PlaceholderImage, + eventName: it.name!, + description: it.description!, + startTime: new Date(it.start_time!), + endTime: new Date(it.end_time!), + } satisfies EventInfo)); return ( - (eventInfo.isJoined - ? - : ( - - - - - - ) + <> + {allEvents.length > 0 && ( + (eventInfo.isJoined + ? + : ( + + + + + + ) + )} + /> )} - /> + { + allEvents.length === 0 && ( + + + + + + 暂无活动 + 前面的区域 以后再来探索吧 + + + ) + } + ); } diff --git a/client/cms/src/components/ui/empty.tsx b/client/cms/src/components/ui/empty.tsx new file mode 100644 index 0000000..df91e9d --- /dev/null +++ b/client/cms/src/components/ui/empty.tsx @@ -0,0 +1,104 @@ +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +function Empty({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +const emptyMediaVariants = cva( + "flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-transparent", + icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function EmptyMedia({ + className, + variant = "default", + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) { + return ( +
a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4", + className + )} + {...props} + /> + ) +} + +function EmptyContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { + Empty, + EmptyHeader, + EmptyTitle, + EmptyDescription, + EmptyContent, + EmptyMedia, +} diff --git a/client/cms/src/routes/_workbenchLayout/events.tsx b/client/cms/src/routes/_workbenchLayout/events.tsx index 79e31d1..440bb1b 100644 --- a/client/cms/src/routes/_workbenchLayout/events.tsx +++ b/client/cms/src/routes/_workbenchLayout/events.tsx @@ -7,7 +7,7 @@ export const Route = createFileRoute('/_workbenchLayout/events')({ function RouteComponent() { return ( -
+
);