@@ -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';
|
||||
|
||||
@@ -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()
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 (
|
||||
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
||||
{children}
|
||||
{isLoading && (
|
||||
<CheckinQrDialogSkeleton />
|
||||
)}
|
||||
{isError && (
|
||||
<CheckinQrDialogError />
|
||||
)}
|
||||
{!isLoading && !isError && !isNil(data) && (
|
||||
<CheckinQrDialogView checkinCode={String(data.data!.checkin_code)} />
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { TicketX } from 'lucide-react';
|
||||
import { DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/dialog';
|
||||
|
||||
export function CheckinQrDialogError() {
|
||||
return (
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>签到码</DialogTitle>
|
||||
<DialogDescription>
|
||||
签到码获取出错。请稍后重试。
|
||||
<div className="flex justify-center my-12">
|
||||
<TicketX size={100} className="stroke-[1.5]" />
|
||||
</div>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
</DialogContent>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>签到码</DialogTitle>
|
||||
<DialogDescription>
|
||||
请工作人员扫描下面的二维码为你签到。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="border-2 px-4 py-8 border-muted rounded-xl flex flex-col items-center justify-center p-4">
|
||||
<QRCode data="welcome to join the conference" className="size-60 blur-sm" />
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<div className="flex flex-1 items-center ml-2 text-2xl text-primary/80 justify-center">
|
||||
加载中...
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
);
|
||||
}
|
||||
23
client/cms/src/components/checkin/checkin-qr.dialog.view.tsx
Normal file
23
client/cms/src/components/checkin/checkin-qr.dialog.view.tsx
Normal file
@@ -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 (
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>签到码</DialogTitle>
|
||||
<DialogDescription>
|
||||
请工作人员扫描下面的二维码为你签到。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="border-2 px-4 py-8 border-muted rounded-xl flex flex-col items-center justify-center p-4">
|
||||
<QRCode data={checkinCode} className="size-60" />
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<div className="flex flex-1 items-center ml-2 font-mono text-2xl tracking-widest text-primary/80 justify-center">
|
||||
{checkinCode}
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button className="w-20">签到</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>QR Code</DialogTitle>
|
||||
<DialogDescription>
|
||||
请工作人员扫描下面的二维码为你签到。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<QrSection eventId={eventId} enabled={open} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
function QrSection({ eventId, enabled }: { eventId: string; enabled: boolean }) {
|
||||
// const { data } = useCheckinCode(eventId, enabled);
|
||||
const data = { data: { checkin_code: `dummy${eventId}${enabled}` } };
|
||||
return data
|
||||
? (
|
||||
<>
|
||||
<div className="border-2 px-4 py-8 border-muted rounded-xl flex flex-col items-center justify-center p-4">
|
||||
<QRCode data={data.data.checkin_code} className="size-60" />
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<div className="flex flex-1 items-center ml-2 font-mono text-3xl tracking-widest text-primary/80 justify-center">
|
||||
{data.data.checkin_code}
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<QrSectionSkeleton />
|
||||
);
|
||||
}
|
||||
|
||||
function QrSectionSkeleton() {
|
||||
return (
|
||||
<>
|
||||
<div className="border-2 px-4 py-8 border-muted rounded-xl flex flex-col items-center justify-center p-4">
|
||||
<QRCode data="114514" className="size-60 blur-xs" />
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<div className="flex flex-1 items-center ml-2 font-mono text-3xl tracking-widest text-primary/80 justify-center">
|
||||
Loading...
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -7,12 +7,6 @@ import { toEventInfo } from '../types';
|
||||
import { EventGridSkeleton } from './event-grid.skeleton';
|
||||
import { EventGridView } from './event-grid.view';
|
||||
|
||||
function JoinButton() {
|
||||
return (
|
||||
<Button className="w-full">加入活动</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export function EventGridContainer() {
|
||||
const { data, isLoading } = useEvents();
|
||||
|
||||
@@ -29,14 +23,14 @@ export function EventGridContainer() {
|
||||
? (
|
||||
<KycDialogContainer event={eventInfo}>
|
||||
<DialogTrigger asChild>
|
||||
<JoinButton />
|
||||
<Button className="w-full">加入活动</Button>
|
||||
</DialogTrigger>
|
||||
</KycDialogContainer>
|
||||
)
|
||||
: (
|
||||
<EventJoinDialogContainer event={eventInfo}>
|
||||
<DialogTrigger asChild>
|
||||
<JoinButton />
|
||||
<Button className="w-full">加入活动</Button>
|
||||
</DialogTrigger>
|
||||
</EventJoinDialogContainer>
|
||||
)
|
||||
|
||||
@@ -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 (
|
||||
<div className="flex flex-row justify-between w-full gap-4">
|
||||
<Button className="flex-1" disabled={!isInDateRange(event.startTime, event.endTime)}>签到</Button>
|
||||
<Button className="flex-1">查看详情</Button>
|
||||
<CheckinQrDialogContainer event={event}>
|
||||
<DialogTrigger asChild>
|
||||
<Button className="flex-1" disabled={isOutOfDateRange}>
|
||||
{isOutOfDateRange && '未到签到时间'}
|
||||
{isCheckedIn && '已签到'}
|
||||
{canCheckIn && '签到'}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
</CheckinQrDialogContainer>
|
||||
<Button className="flex-1" onClick={() => void navigate({ to: `/events/$eventId`, params: { eventId: event.eventId } })}>查看详情</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<Dialog
|
||||
open={isDialogOpen}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: getEventListInfiniteQueryKey({ query: {} }),
|
||||
});
|
||||
}
|
||||
setIsDialogOpen(open);
|
||||
}}
|
||||
onOpenChange={setIsDialogOpen}
|
||||
>
|
||||
{children}
|
||||
{stage === 'prompt' && <KycPromptDialogView next={() => setStage('methodSelection')} />}
|
||||
|
||||
@@ -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!,
|
||||
|
||||
9
client/cms/src/hooks/data/useCheckinCode.ts
Normal file
9
client/cms/src/hooks/data/useCheckinCode.ts
Normal file
@@ -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,
|
||||
});
|
||||
}
|
||||
@@ -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(),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<div className="py-4 px-6 md:gap-6 md:py-6 h-full">
|
||||
<EventGridContainer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
48
client/cms/src/stories/events/checkin-dialog.stories.tsx
Normal file
48
client/cms/src/stories/events/checkin-dialog.stories.tsx
Normal file
@@ -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 => (
|
||||
<Dialog open={true}>
|
||||
<Story />
|
||||
</Dialog>
|
||||
),
|
||||
],
|
||||
} satisfies Meta<typeof CheckinQrDialogView>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Prompt: Story = {
|
||||
args: {
|
||||
checkinCode: '114514',
|
||||
},
|
||||
};
|
||||
|
||||
export const Skeleton: Story = {
|
||||
render: () => (
|
||||
<Dialog open={true}>
|
||||
<CheckinQrDialogSkeleton />
|
||||
</Dialog>
|
||||
),
|
||||
args: {
|
||||
checkinCode: '',
|
||||
},
|
||||
};
|
||||
|
||||
export const Error: Story = {
|
||||
render: () => (
|
||||
<Dialog open={true}>
|
||||
<CheckinQrDialogError />
|
||||
</Dialog>
|
||||
),
|
||||
args: {
|
||||
checkinCode: '',
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user