42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
|
|
import { Skeleton } from '@/components/ui/skeleton';
|
||
|
|
import { CardSkeleton } from '@/components/shared/loading-skeleton';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Route-level loading UI for the client detail page. Renders while the
|
||
|
|
* server component resolves the session and the client component bootstraps
|
||
|
|
* its initial query — replaces the previous empty-header flash on direct
|
||
|
|
* URL visits.
|
||
|
|
*/
|
||
|
|
export default function Loading() {
|
||
|
|
return (
|
||
|
|
<div className="space-y-6">
|
||
|
|
{/* Header strip — title, badges, action buttons */}
|
||
|
|
<div className="rounded-xl border border-border bg-card px-5 py-4 shadow-sm space-y-3">
|
||
|
|
<div className="flex items-center gap-3">
|
||
|
|
<Skeleton className="h-7 w-56" />
|
||
|
|
<Skeleton className="h-5 w-16 rounded-full" />
|
||
|
|
</div>
|
||
|
|
<div className="flex flex-wrap gap-2">
|
||
|
|
<Skeleton className="h-9 w-20 rounded-md" />
|
||
|
|
<Skeleton className="h-9 w-20 rounded-md" />
|
||
|
|
<Skeleton className="h-9 w-24 rounded-md" />
|
||
|
|
<Skeleton className="h-9 w-32 rounded-md" />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Tab strip */}
|
||
|
|
<div className="flex gap-2 border-b border-border pb-1">
|
||
|
|
{Array.from({ length: 8 }).map((_, i) => (
|
||
|
|
<Skeleton key={i} className="h-8 w-20 rounded-md" />
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Two-column overview */}
|
||
|
|
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||
|
|
<CardSkeleton />
|
||
|
|
<CardSkeleton />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|