From a315eea0873bddbe0d16c82f2acb98c373bee3b7 Mon Sep 17 00:00:00 2001 From: Noa Virellia Date: Sun, 8 Feb 2026 17:16:18 +0800 Subject: [PATCH] feat(client): checkin Signed-off-by: Noa Virellia --- client/cms/src/client/types.gen.ts | 21 +----- client/cms/src/client/zod.gen.ts | 11 +-- .../checkin/checkin-qr.dialog.container.tsx | 28 ++++++++ .../checkin/checkin-qr.dialog.error.tsx | 18 +++++ .../checkin/checkin-qr.dialog.skeleton.tsx | 23 ++++++ .../checkin/checkin-qr.dialog.view.tsx | 23 ++++++ .../cms/src/components/checkin/qr-dialog.tsx | 70 ------------------- .../event-grid/event-grid.container.tsx | 10 +-- .../events/joined-events.containers.tsx | 19 ++++- .../events/kyc/kyc.dialog.container.tsx | 26 +++---- client/cms/src/components/events/types.ts | 2 + client/cms/src/hooks/data/useCheckinCode.ts | 9 +++ client/cms/src/hooks/data/useJoinEvent.ts | 17 ++++- client/cms/src/routeTree.gen.ts | 58 ++++----------- .../src/routes/_workbenchLayout/events.tsx | 14 ---- .../stories/events/checkin-dialog.stories.tsx | 48 +++++++++++++ 16 files changed, 211 insertions(+), 186 deletions(-) create mode 100644 client/cms/src/components/checkin/checkin-qr.dialog.container.tsx create mode 100644 client/cms/src/components/checkin/checkin-qr.dialog.error.tsx create mode 100644 client/cms/src/components/checkin/checkin-qr.dialog.skeleton.tsx create mode 100644 client/cms/src/components/checkin/checkin-qr.dialog.view.tsx delete mode 100644 client/cms/src/components/checkin/qr-dialog.tsx create mode 100644 client/cms/src/hooks/data/useCheckinCode.ts delete mode 100644 client/cms/src/routes/_workbenchLayout/events.tsx create mode 100644 client/cms/src/stories/events/checkin-dialog.stories.tsx diff --git a/client/cms/src/client/types.gen.ts b/client/cms/src/client/types.gen.ts index cb65abf..1e2729a 100644 --- a/client/cms/src/client/types.gen.ts +++ b/client/cms/src/client/types.gen.ts @@ -10,6 +10,7 @@ export type DataEventIndexDoc = { enable_kyc?: boolean; end_time?: string; event_id?: string; + is_checked_in?: boolean; is_joined?: boolean; join_count?: number; name?: string; @@ -501,16 +502,6 @@ export type GetEventAttendanceResponse = GetEventAttendanceResponses[keyof GetEv export type GetEventCheckinData = { body?: never; - headers: { - /** - * latest - */ - 'X-Api-Version': string; - /** - * Bearer token - */ - Authorization: string; - }; path?: never; query: { /** @@ -610,16 +601,6 @@ export type PostEventCheckinSubmitData = { * Checkin Code Data */ body: ServiceEventCheckinSubmitData; - headers: { - /** - * latest - */ - 'X-Api-Version': string; - /** - * Bearer token - */ - Authorization: string; - }; path?: never; query?: never; url: '/event/checkin/submit'; diff --git a/client/cms/src/client/zod.gen.ts b/client/cms/src/client/zod.gen.ts index 0dcffaa..6e13fae 100644 --- a/client/cms/src/client/zod.gen.ts +++ b/client/cms/src/client/zod.gen.ts @@ -8,6 +8,7 @@ export const zDataEventIndexDoc = z.object({ enable_kyc: z.boolean().optional(), end_time: z.string().optional(), event_id: z.string().optional(), + is_checked_in: z.boolean().optional(), is_joined: z.boolean().optional(), join_count: z.number().int().optional(), name: z.string().optional(), @@ -234,10 +235,6 @@ export const zGetEventCheckinData = z.object({ path: z.never().optional(), query: z.object({ event_id: z.string() - }), - headers: z.object({ - 'X-Api-Version': z.string(), - Authorization: z.string() }) }); @@ -266,11 +263,7 @@ export const zGetEventCheckinQueryResponse = zUtilsRespStatus.and(z.object({ export const zPostEventCheckinSubmitData = z.object({ body: zServiceEventCheckinSubmitData, path: z.never().optional(), - query: z.never().optional(), - headers: z.object({ - 'X-Api-Version': z.string(), - Authorization: z.string() - }) + query: z.never().optional() }); /** diff --git a/client/cms/src/components/checkin/checkin-qr.dialog.container.tsx b/client/cms/src/components/checkin/checkin-qr.dialog.container.tsx new file mode 100644 index 0000000..c59b01a --- /dev/null +++ b/client/cms/src/components/checkin/checkin-qr.dialog.container.tsx @@ -0,0 +1,28 @@ +import type { EventInfo } from '../events/types'; +import { isNil } from 'lodash-es'; +import { useState } from 'react'; +import { useCheckinCode } from '@/hooks/data/useCheckinCode'; +import { Dialog } from '../ui/dialog'; +import { CheckinQrDialogError } from './checkin-qr.dialog.error'; +import { CheckinQrDialogSkeleton } from './checkin-qr.dialog.skeleton'; +import { CheckinQrDialogView } from './checkin-qr.dialog.view'; + +export function CheckinQrDialogContainer({ event, children }: { event: EventInfo; children: React.ReactNode }) { + const [isDialogOpen, setIsDialogOpen] = useState(false); + const { data, isLoading, isError } = useCheckinCode(event.eventId, isDialogOpen); + + return ( + + {children} + {isLoading && ( + + )} + {isError && ( + + )} + {!isLoading && !isError && !isNil(data) && ( + + )} + + ); +} diff --git a/client/cms/src/components/checkin/checkin-qr.dialog.error.tsx b/client/cms/src/components/checkin/checkin-qr.dialog.error.tsx new file mode 100644 index 0000000..5fcc7f5 --- /dev/null +++ b/client/cms/src/components/checkin/checkin-qr.dialog.error.tsx @@ -0,0 +1,18 @@ +import { TicketX } from 'lucide-react'; +import { DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/dialog'; + +export function CheckinQrDialogError() { + return ( + + + 签到码 + + 签到码获取出错。请稍后重试。 +
+ +
+
+
+
+ ); +} diff --git a/client/cms/src/components/checkin/checkin-qr.dialog.skeleton.tsx b/client/cms/src/components/checkin/checkin-qr.dialog.skeleton.tsx new file mode 100644 index 0000000..64d4c84 --- /dev/null +++ b/client/cms/src/components/checkin/checkin-qr.dialog.skeleton.tsx @@ -0,0 +1,23 @@ +import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '../ui/dialog'; +import { QRCode } from '../ui/shadcn-io/qr-code'; + +export function CheckinQrDialogSkeleton() { + return ( + + + 签到码 + + 请工作人员扫描下面的二维码为你签到。 + + +
+ +
+ +
+ 加载中... +
+
+
+ ); +} diff --git a/client/cms/src/components/checkin/checkin-qr.dialog.view.tsx b/client/cms/src/components/checkin/checkin-qr.dialog.view.tsx new file mode 100644 index 0000000..3453d45 --- /dev/null +++ b/client/cms/src/components/checkin/checkin-qr.dialog.view.tsx @@ -0,0 +1,23 @@ +import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '../ui/dialog'; +import { QRCode } from '../ui/shadcn-io/qr-code'; + +export function CheckinQrDialogView({ checkinCode }: { checkinCode: string }) { + return ( + + + 签到码 + + 请工作人员扫描下面的二维码为你签到。 + + +
+ +
+ +
+ {checkinCode} +
+
+
+ ); +} diff --git a/client/cms/src/components/checkin/qr-dialog.tsx b/client/cms/src/components/checkin/qr-dialog.tsx deleted file mode 100644 index df2a81c..0000000 --- a/client/cms/src/components/checkin/qr-dialog.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { useState } from 'react'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, -} from '@/components/ui/dialog'; -import { QRCode } from '@/components/ui/shadcn-io/qr-code'; -import { Button } from '../ui/button'; - -export function QrDialog( - { eventId }: { eventId: string }, -) { - const [open, setOpen] = useState(false); - return ( - - - - - - - QR Code - - 请工作人员扫描下面的二维码为你签到。 - - - - - - ); -} - -function QrSection({ eventId, enabled }: { eventId: string; enabled: boolean }) { - // const { data } = useCheckinCode(eventId, enabled); - const data = { data: { checkin_code: `dummy${eventId}${enabled}` } }; - return data - ? ( - <> -
- -
- -
- {data.data.checkin_code} -
-
- - ) - : ( - - ); -} - -function QrSectionSkeleton() { - return ( - <> -
- -
- -
- Loading... -
-
- - ); -} diff --git a/client/cms/src/components/events/event-grid/event-grid.container.tsx b/client/cms/src/components/events/event-grid/event-grid.container.tsx index f2d258e..13e7da5 100644 --- a/client/cms/src/components/events/event-grid/event-grid.container.tsx +++ b/client/cms/src/components/events/event-grid/event-grid.container.tsx @@ -7,12 +7,6 @@ import { toEventInfo } from '../types'; import { EventGridSkeleton } from './event-grid.skeleton'; import { EventGridView } from './event-grid.view'; -function JoinButton() { - return ( - - ); -} - export function EventGridContainer() { const { data, isLoading } = useEvents(); @@ -29,14 +23,14 @@ export function EventGridContainer() { ? ( - + ) : ( - + ) diff --git a/client/cms/src/components/events/joined-events.containers.tsx b/client/cms/src/components/events/joined-events.containers.tsx index 4ebdc54..05585a0 100644 --- a/client/cms/src/components/events/joined-events.containers.tsx +++ b/client/cms/src/components/events/joined-events.containers.tsx @@ -1,16 +1,31 @@ import type { EventInfo } from './types'; +import { useNavigate } from '@tanstack/react-router'; import { useJoinedEvents } from '@/hooks/data/useJoinedEvents'; import { isInDateRange } from '@/lib/utils'; +import { CheckinQrDialogContainer } from '../checkin/checkin-qr.dialog.container'; import { Button } from '../ui/button'; +import { DialogTrigger } from '../ui/dialog'; import { EventGridSkeleton } from './event-grid/event-grid.skeleton'; import { EventGridView } from './event-grid/event-grid.view'; import { toEventInfo } from './types'; export function JoinedEventGridFooter({ event }: { event: EventInfo }) { + const isOutOfDateRange = !isInDateRange(event.startTime, event.endTime); + const isCheckedIn = event.isCheckedIn; + const canCheckIn = !isOutOfDateRange && !isCheckedIn; + const navigate = useNavigate(); return (
- - + + + + + +
); } diff --git a/client/cms/src/components/events/kyc/kyc.dialog.container.tsx b/client/cms/src/components/events/kyc/kyc.dialog.container.tsx index 1e043ee..198805c 100644 --- a/client/cms/src/components/events/kyc/kyc.dialog.container.tsx +++ b/client/cms/src/components/events/kyc/kyc.dialog.container.tsx @@ -1,12 +1,11 @@ import type { EventInfo } from '../types'; import type { KycSubmission } from './kyc.types'; import { Dialog } from '@radix-ui/react-dialog'; -import { useQueryClient } from '@tanstack/react-query'; import { useCallback, useEffect, useState } from 'react'; import { useStore } from 'zustand'; -import { postEventJoin, postKycQuery } from '@/client'; -import { getEventListInfiniteQueryKey } from '@/client/@tanstack/react-query.gen'; +import { postKycQuery } from '@/client'; import { useCreateKycSession } from '@/hooks/data/useCreateKycSession'; +import { useJoinEvent } from '@/hooks/data/useJoinEvent'; import { KycFailedDialogView } from './kyc-failed.dialog.view'; import { KycMethodSelectionDialogView } from './kyc-method-selection.dialog.view'; import { KycPendingDialogView } from './kyc-pending.dialog.view'; @@ -22,12 +21,12 @@ export function KycDialogContainer({ event, children }: { event: EventInfo; chil const setStage = useStore(store, s => s.setStage); const setKycId = useStore(store, s => s.setKycId); - const { mutateAsync } = useCreateKycSession(); - const queryClient = useQueryClient(); + const { mutateAsync: createKycSessionAsync } = useCreateKycSession(); + const { mutateAsync: joinEventAsync } = useJoinEvent(); const joinEvent = useCallback(async (eventId: string, kycId: string, abortSignal?: AbortSignal) => { try { - await postEventJoin({ + await joinEventAsync({ signal: abortSignal, body: { event_id: eventId, kyc_id: kycId }, }); @@ -37,11 +36,11 @@ export function KycDialogContainer({ event, children }: { event: EventInfo; chil console.error('Error joining event:', e); setStage('failed'); } - }, [setStage]); + }, [joinEventAsync, setStage]); const onKycSessionCreate = useCallback(async (submission: KycSubmission) => { try { - const { data } = await mutateAsync(submission); + const { data } = await createKycSessionAsync(submission); setKycId(data!.kyc_id!); if (data!.status === 'success') { await joinEvent(event.eventId, data!.kyc_id!, undefined); @@ -55,7 +54,7 @@ export function KycDialogContainer({ event, children }: { event: EventInfo; chil console.error(e); setStage('failed'); } - }, [event.eventId, joinEvent, mutateAsync, setKycId, setStage]); + }, [event.eventId, joinEvent, createKycSessionAsync, setKycId, setStage]); useEffect(() => { if (stage !== 'pending' || !isDialogOpen) { @@ -107,14 +106,7 @@ export function KycDialogContainer({ event, children }: { event: EventInfo; chil return ( { - if (!open) { - void queryClient.invalidateQueries({ - queryKey: getEventListInfiniteQueryKey({ query: {} }), - }); - } - setIsDialogOpen(open); - }} + onOpenChange={setIsDialogOpen} > {children} {stage === 'prompt' && setStage('methodSelection')} />} diff --git a/client/cms/src/components/events/types.ts b/client/cms/src/components/events/types.ts index 930e3fc..1d51c81 100644 --- a/client/cms/src/components/events/types.ts +++ b/client/cms/src/components/events/types.ts @@ -5,6 +5,7 @@ export interface EventInfo { type: 'official' | 'party'; eventId: string; isJoined: boolean; + isCheckedIn: boolean; requireKyc: boolean; coverImage: string; eventName: string; @@ -19,6 +20,7 @@ export function toEventInfo(raw: DataEventIndexDoc): EventInfo { eventId: raw.event_id!, isJoined: raw.is_joined!, requireKyc: raw.enable_kyc!, + isCheckedIn: raw.is_checked_in ?? false, coverImage: raw.thumbnail! || PlaceholderImage, eventName: raw.name!, description: raw.description!, diff --git a/client/cms/src/hooks/data/useCheckinCode.ts b/client/cms/src/hooks/data/useCheckinCode.ts new file mode 100644 index 0000000..cf64d9e --- /dev/null +++ b/client/cms/src/hooks/data/useCheckinCode.ts @@ -0,0 +1,9 @@ +import { useQuery } from '@tanstack/react-query'; +import { getEventCheckinOptions } from '@/client/@tanstack/react-query.gen'; + +export function useCheckinCode(eventId: string, enabled: boolean) { + return useQuery({ + ...getEventCheckinOptions({ query: { event_id: eventId } }), + enabled, + }); +} diff --git a/client/cms/src/hooks/data/useJoinEvent.ts b/client/cms/src/hooks/data/useJoinEvent.ts index ae273ac..838f424 100644 --- a/client/cms/src/hooks/data/useJoinEvent.ts +++ b/client/cms/src/hooks/data/useJoinEvent.ts @@ -1,8 +1,21 @@ -import { useMutation } from '@tanstack/react-query'; -import { postEventJoinMutation } from '@/client/@tanstack/react-query.gen'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { + getEventJoinedInfiniteQueryKey, + getEventListInfiniteQueryKey, + postEventJoinMutation, +} from '@/client/@tanstack/react-query.gen'; export function useJoinEvent() { + const queryClient = useQueryClient(); return useMutation({ ...postEventJoinMutation(), + onSuccess: () => { + void queryClient.invalidateQueries({ + queryKey: getEventListInfiniteQueryKey(), + }); + void queryClient.invalidateQueries({ + queryKey: getEventJoinedInfiniteQueryKey(), + }); + }, }); } diff --git a/client/cms/src/routeTree.gen.ts b/client/cms/src/routeTree.gen.ts index 723a86c..c9e5b23 100644 --- a/client/cms/src/routeTree.gen.ts +++ b/client/cms/src/routeTree.gen.ts @@ -15,7 +15,6 @@ import { Route as AuthorizeRouteImport } from './routes/authorize' import { Route as WorkbenchLayoutRouteImport } from './routes/_workbenchLayout' import { Route as WorkbenchLayoutIndexRouteImport } from './routes/_workbenchLayout/index' import { Route as WorkbenchLayoutJoinedEventsRouteImport } from './routes/_workbenchLayout/joined-events' -import { Route as WorkbenchLayoutEventsRouteImport } from './routes/_workbenchLayout/events' import { Route as WorkbenchLayoutProfileIndexRouteImport } from './routes/_workbenchLayout/profile/index' import { Route as WorkbenchLayoutEventsIndexRouteImport } from './routes/_workbenchLayout/events/index' import { Route as WorkbenchLayoutProfileUserIdRouteImport } from './routes/_workbenchLayout/profile/$userId' @@ -51,11 +50,6 @@ const WorkbenchLayoutJoinedEventsRoute = path: '/joined-events', getParentRoute: () => WorkbenchLayoutRoute, } as any) -const WorkbenchLayoutEventsRoute = WorkbenchLayoutEventsRouteImport.update({ - id: '/events', - path: '/events', - getParentRoute: () => WorkbenchLayoutRoute, -} as any) const WorkbenchLayoutProfileIndexRoute = WorkbenchLayoutProfileIndexRouteImport.update({ id: '/profile/', @@ -64,9 +58,9 @@ const WorkbenchLayoutProfileIndexRoute = } as any) const WorkbenchLayoutEventsIndexRoute = WorkbenchLayoutEventsIndexRouteImport.update({ - id: '/', - path: '/', - getParentRoute: () => WorkbenchLayoutEventsRoute, + id: '/events/', + path: '/events/', + getParentRoute: () => WorkbenchLayoutRoute, } as any) const WorkbenchLayoutProfileUserIdRoute = WorkbenchLayoutProfileUserIdRouteImport.update({ @@ -76,9 +70,9 @@ const WorkbenchLayoutProfileUserIdRoute = } as any) const WorkbenchLayoutEventsEventIdRoute = WorkbenchLayoutEventsEventIdRouteImport.update({ - id: '/$eventId', - path: '/$eventId', - getParentRoute: () => WorkbenchLayoutEventsRoute, + id: '/events/$eventId', + path: '/events/$eventId', + getParentRoute: () => WorkbenchLayoutRoute, } as any) export interface FileRoutesByFullPath { @@ -86,7 +80,6 @@ export interface FileRoutesByFullPath { '/authorize': typeof AuthorizeRoute '/magicLinkSent': typeof MagicLinkSentRoute '/token': typeof TokenRoute - '/events': typeof WorkbenchLayoutEventsRouteWithChildren '/joined-events': typeof WorkbenchLayoutJoinedEventsRoute '/events/$eventId': typeof WorkbenchLayoutEventsEventIdRoute '/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute @@ -110,7 +103,6 @@ export interface FileRoutesById { '/authorize': typeof AuthorizeRoute '/magicLinkSent': typeof MagicLinkSentRoute '/token': typeof TokenRoute - '/_workbenchLayout/events': typeof WorkbenchLayoutEventsRouteWithChildren '/_workbenchLayout/joined-events': typeof WorkbenchLayoutJoinedEventsRoute '/_workbenchLayout/': typeof WorkbenchLayoutIndexRoute '/_workbenchLayout/events/$eventId': typeof WorkbenchLayoutEventsEventIdRoute @@ -125,7 +117,6 @@ export interface FileRouteTypes { | '/authorize' | '/magicLinkSent' | '/token' - | '/events' | '/joined-events' | '/events/$eventId' | '/profile/$userId' @@ -148,7 +139,6 @@ export interface FileRouteTypes { | '/authorize' | '/magicLinkSent' | '/token' - | '/_workbenchLayout/events' | '/_workbenchLayout/joined-events' | '/_workbenchLayout/' | '/_workbenchLayout/events/$eventId' @@ -208,13 +198,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof WorkbenchLayoutJoinedEventsRouteImport parentRoute: typeof WorkbenchLayoutRoute } - '/_workbenchLayout/events': { - id: '/_workbenchLayout/events' - path: '/events' - fullPath: '/events' - preLoaderRoute: typeof WorkbenchLayoutEventsRouteImport - parentRoute: typeof WorkbenchLayoutRoute - } '/_workbenchLayout/profile/': { id: '/_workbenchLayout/profile/' path: '/profile' @@ -224,10 +207,10 @@ declare module '@tanstack/react-router' { } '/_workbenchLayout/events/': { id: '/_workbenchLayout/events/' - path: '/' + path: '/events' fullPath: '/events/' preLoaderRoute: typeof WorkbenchLayoutEventsIndexRouteImport - parentRoute: typeof WorkbenchLayoutEventsRoute + parentRoute: typeof WorkbenchLayoutRoute } '/_workbenchLayout/profile/$userId': { id: '/_workbenchLayout/profile/$userId' @@ -238,42 +221,29 @@ declare module '@tanstack/react-router' { } '/_workbenchLayout/events/$eventId': { id: '/_workbenchLayout/events/$eventId' - path: '/$eventId' + path: '/events/$eventId' fullPath: '/events/$eventId' preLoaderRoute: typeof WorkbenchLayoutEventsEventIdRouteImport - parentRoute: typeof WorkbenchLayoutEventsRoute + parentRoute: typeof WorkbenchLayoutRoute } } } -interface WorkbenchLayoutEventsRouteChildren { - WorkbenchLayoutEventsEventIdRoute: typeof WorkbenchLayoutEventsEventIdRoute - WorkbenchLayoutEventsIndexRoute: typeof WorkbenchLayoutEventsIndexRoute -} - -const WorkbenchLayoutEventsRouteChildren: WorkbenchLayoutEventsRouteChildren = { - WorkbenchLayoutEventsEventIdRoute: WorkbenchLayoutEventsEventIdRoute, - WorkbenchLayoutEventsIndexRoute: WorkbenchLayoutEventsIndexRoute, -} - -const WorkbenchLayoutEventsRouteWithChildren = - WorkbenchLayoutEventsRoute._addFileChildren( - WorkbenchLayoutEventsRouteChildren, - ) - interface WorkbenchLayoutRouteChildren { - WorkbenchLayoutEventsRoute: typeof WorkbenchLayoutEventsRouteWithChildren WorkbenchLayoutJoinedEventsRoute: typeof WorkbenchLayoutJoinedEventsRoute WorkbenchLayoutIndexRoute: typeof WorkbenchLayoutIndexRoute + WorkbenchLayoutEventsEventIdRoute: typeof WorkbenchLayoutEventsEventIdRoute WorkbenchLayoutProfileUserIdRoute: typeof WorkbenchLayoutProfileUserIdRoute + WorkbenchLayoutEventsIndexRoute: typeof WorkbenchLayoutEventsIndexRoute WorkbenchLayoutProfileIndexRoute: typeof WorkbenchLayoutProfileIndexRoute } const WorkbenchLayoutRouteChildren: WorkbenchLayoutRouteChildren = { - WorkbenchLayoutEventsRoute: WorkbenchLayoutEventsRouteWithChildren, WorkbenchLayoutJoinedEventsRoute: WorkbenchLayoutJoinedEventsRoute, WorkbenchLayoutIndexRoute: WorkbenchLayoutIndexRoute, + WorkbenchLayoutEventsEventIdRoute: WorkbenchLayoutEventsEventIdRoute, WorkbenchLayoutProfileUserIdRoute: WorkbenchLayoutProfileUserIdRoute, + WorkbenchLayoutEventsIndexRoute: WorkbenchLayoutEventsIndexRoute, WorkbenchLayoutProfileIndexRoute: WorkbenchLayoutProfileIndexRoute, } diff --git a/client/cms/src/routes/_workbenchLayout/events.tsx b/client/cms/src/routes/_workbenchLayout/events.tsx deleted file mode 100644 index 4c774f2..0000000 --- a/client/cms/src/routes/_workbenchLayout/events.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { createFileRoute } from '@tanstack/react-router'; -import { EventGridContainer } from '@/components/events/event-grid/event-grid.container'; - -export const Route = createFileRoute('/_workbenchLayout/events')({ - component: RouteComponent, -}); - -function RouteComponent() { - return ( -
- -
- ); -} diff --git a/client/cms/src/stories/events/checkin-dialog.stories.tsx b/client/cms/src/stories/events/checkin-dialog.stories.tsx new file mode 100644 index 0000000..eaa2790 --- /dev/null +++ b/client/cms/src/stories/events/checkin-dialog.stories.tsx @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { CheckinQrDialogError } from '@/components/checkin/checkin-qr.dialog.error'; +import { CheckinQrDialogSkeleton } from '@/components/checkin/checkin-qr.dialog.skeleton'; +import { CheckinQrDialogView } from '@/components/checkin/checkin-qr.dialog.view'; +import { Dialog } from '@/components/ui/dialog'; + +const meta = { + title: 'Events/CheckinQRDialog', + component: CheckinQrDialogView, + decorators: [ + Story => ( + + + + ), + ], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Prompt: Story = { + args: { + checkinCode: '114514', + }, +}; + +export const Skeleton: Story = { + render: () => ( + + + + ), + args: { + checkinCode: '', + }, +}; + +export const Error: Story = { + render: () => ( + + + + ), + args: { + checkinCode: '', + }, +};