feat(client): qrcode checkin dialog

Signed-off-by: Noa Virellia <noa@requiem.garden>
This commit is contained in:
2025-12-28 01:20:13 +08:00
parent f89a483380
commit a48f5ad2fa
16 changed files with 524 additions and 119 deletions

View File

@@ -1,44 +1,30 @@
import { useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardAction, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
import { useCheckin } from '@/hooks/data/useCheckin';
import { useUserInfo } from '@/hooks/data/useUserInfo';
import { QrDialog } from '../checkin/qr-dialog';
export function CheckinCard() {
const { mutateAsync, isPending } = useCheckin();
const { data } = useUserInfo();
const queryClient = useQueryClient();
return (
<Card className="@container/card">
<CardHeader>
<CardDescription></CardDescription>
<CardTitle className="text-2xl font-semibold tabular-nums @[250px]/card:text-3xl">
{data.checkin !== null ? '已签到' : '未签到'}
{data.checkin !== null && <span className="text-sm font-medium ml-2">{`${new Date(data.checkin).toLocaleString()}`}</span>}
</CardTitle>
<CardAction>
<Badge variant="outline">Day 1</Badge>
</CardAction>
</CardHeader>
<CardFooter className="flex-col items-start gap-1.5 text-sm">
<Button
className="w-20"
onClick={() => {
mutateAsync().then(() => {
toast('签到成功');
void queryClient.invalidateQueries({ queryKey: ['userInfo'] });
}).catch((error) => {
console.error(error);
toast('签到失败');
});
}}
disabled={isPending || data.checkin !== null}
>
</Button>
</CardFooter>
</Card>
<>
<Card className="@container/card">
<CardHeader>
<CardDescription></CardDescription>
<CardTitle className="text-2xl font-semibold tabular-nums @[250px]/card:text-3xl">
{data.checkin !== null ? '已签到' : '未签到'}
{data.checkin !== null && <span className="text-sm font-medium ml-2">{`${new Date(data.checkin).toLocaleString()}`}</span>}
</CardTitle>
<CardAction>
<Badge variant="outline">Day 1</Badge>
</CardAction>
</CardHeader>
<CardFooter className="flex-col items-start gap-1.5 text-sm">
<QrDialog
eventId="019b5bf2-90ce-75f5-93a4-a66914c2ef11"
>
</QrDialog>
</CardFooter>
</Card>
</>
);
}