mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 18:31:11 -05:00
feat: Implement skeleton loading
This commit is contained in:
@@ -23,6 +23,7 @@ import { ReassignDialog } from './ReassignDialog';
|
||||
import { smartMergeArray } from '@/lib/smartStateUpdate';
|
||||
import { useDebounce } from '@/hooks/useDebounce';
|
||||
import { QueueItem } from './QueueItem';
|
||||
import { QueueSkeleton } from './QueueSkeleton';
|
||||
|
||||
interface ModerationItem {
|
||||
id: string;
|
||||
@@ -1678,11 +1679,7 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
|
||||
const QueueContent = () => {
|
||||
if (isInitialLoad && loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center p-8">
|
||||
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-primary"></div>
|
||||
</div>
|
||||
);
|
||||
return <QueueSkeleton count={5} />;
|
||||
}
|
||||
|
||||
if (items.length === 0) {
|
||||
|
||||
42
src/components/moderation/QueueItemSkeleton.tsx
Normal file
42
src/components/moderation/QueueItemSkeleton.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Card, CardHeader, CardContent } from '@/components/ui/card';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
|
||||
export function QueueItemSkeleton() {
|
||||
return (
|
||||
<Card className="border-l-4 border-l-muted">
|
||||
<CardHeader className="pb-4">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
{/* Left side: Entity type badge + title */}
|
||||
<div className="flex-1 space-y-3">
|
||||
<Skeleton className="h-5 w-24" /> {/* Badge */}
|
||||
<Skeleton className="h-6 w-3/4" /> {/* Title */}
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="h-4 w-4 rounded-full" /> {/* Avatar */}
|
||||
<Skeleton className="h-4 w-32" /> {/* Username */}
|
||||
<Skeleton className="h-4 w-24" /> {/* Date */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right side: Status badge */}
|
||||
<Skeleton className="h-6 w-20" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-4">
|
||||
{/* Content area */}
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-full" />
|
||||
<Skeleton className="h-4 w-5/6" />
|
||||
<Skeleton className="h-4 w-4/6" />
|
||||
</div>
|
||||
|
||||
{/* Action buttons */}
|
||||
<div className="flex gap-2 pt-4">
|
||||
<Skeleton className="h-9 w-24" />
|
||||
<Skeleton className="h-9 w-24" />
|
||||
<Skeleton className="h-9 w-24" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
15
src/components/moderation/QueueSkeleton.tsx
Normal file
15
src/components/moderation/QueueSkeleton.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { QueueItemSkeleton } from './QueueItemSkeleton';
|
||||
|
||||
interface QueueSkeletonProps {
|
||||
count?: number;
|
||||
}
|
||||
|
||||
export function QueueSkeleton({ count = 5 }: QueueSkeletonProps) {
|
||||
return (
|
||||
<div className="flex flex-col gap-6">
|
||||
{Array.from({ length: count }).map((_, i) => (
|
||||
<QueueItemSkeleton key={i} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user