- Eliminate N+1 on resolveCollaborator: add batchResolveCollaborators() in auth.ts (2 DB queries max regardless of session count), update all 4 workshop services to use post-batch mapping - Debounce router.refresh() in useLive.ts (300ms) to group simultaneous SSE events and avoid cascade re-renders - Call cleanupOldEvents fire-and-forget in createEvent to purge old SSE events inline without blocking the response - Add loading.tsx skeletons on /sessions and /users matching actual page layout (PageHeader + content structure) - Lazy-load ShareModal via next/dynamic in BaseSessionLiveWrapper to reduce initial JS bundle Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
33 lines
1.2 KiB
TypeScript
33 lines
1.2 KiB
TypeScript
export default function SessionsLoading() {
|
|
return (
|
|
<main className="mx-auto max-w-7xl px-4">
|
|
{/* PageHeader skeleton */}
|
|
<div className="py-6 flex items-start justify-between gap-4">
|
|
<div className="flex items-center gap-3">
|
|
<div className="h-10 w-10 bg-card rounded-xl animate-pulse" />
|
|
<div className="space-y-2">
|
|
<div className="h-7 w-40 bg-card rounded animate-pulse" />
|
|
<div className="h-4 w-64 bg-card rounded animate-pulse" />
|
|
</div>
|
|
</div>
|
|
<div className="h-9 w-36 bg-card rounded-lg animate-pulse" />
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
{/* Tabs skeleton */}
|
|
<div className="flex gap-2 pb-2">
|
|
{[120, 100, 110, 90, 105].map((w, i) => (
|
|
<div key={i} className="h-9 bg-card animate-pulse rounded-full" style={{ width: w }} />
|
|
))}
|
|
</div>
|
|
{/* Cards grid skeleton */}
|
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
{Array.from({ length: 6 }).map((_, i) => (
|
|
<div key={i} className="h-44 bg-card animate-pulse rounded-xl border border-border" />
|
|
))}
|
|
</div>
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|