diff --git a/apps/admin/src/app/(authed)/mentors/page.tsx b/apps/admin/src/app/(authed)/mentors/page.tsx index 426478e..4fa49e3 100644 --- a/apps/admin/src/app/(authed)/mentors/page.tsx +++ b/apps/admin/src/app/(authed)/mentors/page.tsx @@ -78,7 +78,7 @@ export default function MentorsPage() { - + reload({ background: true })} /> {/* データ領域。Reveal を常時マウントして入場は一度だけ(再フェッチで再生されない)。 @@ -110,7 +110,12 @@ export default function MentorsPage() { 保存すれば再取得で両者が同期するため許容するトレードオフ。 */}
{state.data.mentors.map((m) => ( - + reload({ background: true })} + variant="card" + /> ))}
@@ -130,7 +135,12 @@ export default function MentorsPage() { {state.data.mentors.map((m) => ( - + reload({ background: true })} + variant="row" + /> ))} diff --git a/apps/admin/src/app/(authed)/page.tsx b/apps/admin/src/app/(authed)/page.tsx index f80880a..602cf01 100644 --- a/apps/admin/src/app/(authed)/page.tsx +++ b/apps/admin/src/app/(authed)/page.tsx @@ -96,7 +96,7 @@ export default function DashboardPage() { type="button" variant="outline" size="sm" - onClick={() => sessions.reload()} + onClick={() => sessions.reload({ background: true })} disabled={sessions.state.kind === 'loading'} > diff --git a/apps/admin/src/app/(authed)/pre-registrations/page.tsx b/apps/admin/src/app/(authed)/pre-registrations/page.tsx index 6c5a995..c552c0a 100644 --- a/apps/admin/src/app/(authed)/pre-registrations/page.tsx +++ b/apps/admin/src/app/(authed)/pre-registrations/page.tsx @@ -101,7 +101,7 @@ export default function PreRegistrationsPage() { - + reload({ background: true })} /> {/* データ領域。Reveal を常時マウントして入場は一度だけ(再フェッチで再生されない)。 @@ -133,7 +133,7 @@ export default function PreRegistrationsPage() { reload({ background: true })} variant="card" /> ))} @@ -157,7 +157,7 @@ export default function PreRegistrationsPage() { reload({ background: true })} variant="row" /> ))} diff --git a/apps/checkin/src/app/first-time/page.tsx b/apps/checkin/src/app/first-time/page.tsx index 6354c30..d195fb3 100644 --- a/apps/checkin/src/app/first-time/page.tsx +++ b/apps/checkin/src/app/first-time/page.tsx @@ -28,22 +28,18 @@ import { Card, CardContent, CardDescription, CardHeader } from '@tecnova/ui/comp import { Input } from '@tecnova/ui/components/input'; import { Skeleton } from '@tecnova/ui/components/skeleton'; import { Table, TableBody, TableCell, TableRow } from '@tecnova/ui/components/table'; -import { apiFetch, readErrorMessage } from '@tecnova/ui/lib/api-client'; +import { useApiResource } from '@tecnova/ui/hooks/use-api-resource'; import { motion, useReducedMotion } from 'motion/react'; import Link from 'next/link'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useMemo, useState } from 'react'; import { AnimatedNumber } from '@/components/animated-number'; import { PageShell } from '@/components/page-shell'; import { PanelHeader } from '@/components/panel-header'; import { Reveal } from '@/components/reveal'; +import { CheckinErrorScreen } from '@/components/screen-error'; import { formatJapaneseDate } from '@/lib/format'; import { listItemTransition } from '@/lib/motion'; -type State = - | { kind: 'loading' } - | { kind: 'list'; items: PreRegisteredListResponse['participants'] } - | { kind: 'error'; message: string }; - type PreRegisteredParticipant = PreRegisteredListResponse['participants'][number]; function ParticipantDetails({ item }: { item: PreRegisteredParticipant }) { @@ -124,33 +120,14 @@ function RegistrationSteps() { export default function FirstTimePage() { const prefersReduced = useReducedMotion(); - const [state, setState] = useState({ kind: 'loading' }); + const { state, reload } = useApiResource('/checkin/pre-registered'); const [query, setQuery] = useState(''); - const loadParticipants = useCallback(async () => { - setState({ kind: 'loading' }); - try { - const r = await apiFetch('/checkin/pre-registered'); - if (!r.ok) throw new Error(await readErrorMessage(r)); - const data = (await r.json()) as PreRegisteredListResponse; - setState({ kind: 'list', items: data.participants }); - } catch (e) { - setState({ - kind: 'error', - message: e instanceof Error ? e.message : String(e), - }); - } - }, []); - - useEffect(() => { - void loadParticipants(); - }, [loadParticipants]); - const filteredItems = useMemo(() => { - if (state.kind !== 'list') return []; + if (state.kind !== 'ok') return []; const normalizedQuery = query.trim().toLowerCase(); - if (!normalizedQuery) return state.items; - return state.items.filter((item) => { + if (!normalizedQuery) return state.data.participants; + return state.data.participants.filter((item) => { const values = [ item.fullName, item.nickname, @@ -162,7 +139,7 @@ export default function FirstTimePage() { }); }, [query, state]); - if (state.kind === 'loading') { + if (state.kind === 'idle' || state.kind === 'loading') { return (
@@ -189,27 +166,21 @@ export default function FirstTimePage() { if (state.kind === 'error') { return ( -
- - -
- - -
-
+ + + + + } + /> ); } @@ -233,14 +204,18 @@ export default function FirstTimePage() { style={{ height: 'auto' }} className="w-fit px-4 py-2 text-base" > - 未登録 + 未登録{' '} +
- {state.items.length === 0 ? ( + {state.data.participants.length === 0 ? (