'use client'; import { useEffect, useRef } from 'react'; import { CheckCircle2, Clock3, Hourglass, ListChecks, Wrench, XCircle, } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Skeleton } from '@/components/ui/skeleton'; import { Tooltip, TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip'; import { cn } from '@/lib/utils'; import type { DetectionResultItem } from '@/types'; import { formatVideoTimestamp, getIssueId, getIssueReviewStatus, type IssueReviewStatus, } from './reviewTypes'; const STATUS_CONFIG: Record< IssueReviewStatus, { label: string; icon: typeof Hourglass; className: string; } > = { not_submitted: { label: 'Awaiting Repair', icon: Wrench, className: 'bg-zinc-500/10 text-zinc-600 dark:text-zinc-300', }, pending: { label: 'Under Review', icon: Hourglass, className: 'bg-violet-500/10 text-violet-600 dark:text-violet-400', }, approved: { label: 'Approved', icon: CheckCircle2, className: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400', }, rejected: { label: 'Rejected', icon: XCircle, className: 'bg-destructive/10 text-destructive', }, }; interface IssueReviewQueueProps { detections: DetectionResultItem[]; totalCount: number; selectedIssueId?: string; hasNextPage: boolean; isFetchingNextPage: boolean; onSelect: (issueId: string) => void; onLoadMore: () => void; } export function IssueReviewQueue({ detections, totalCount, selectedIssueId, hasNextPage, isFetchingNextPage, onSelect, onLoadMore, }: IssueReviewQueueProps) { const loadMoreRef = useRef(null); useEffect(() => { const target = loadMoreRef.current; if (!target || !hasNextPage || isFetchingNextPage) return; const root = target.closest( '[data-slot="scroll-area-viewport"]', ); const observer = new IntersectionObserver( (entries) => { if (entries[0]?.isIntersecting) onLoadMore(); }, { root, rootMargin: '160px 0px' }, ); observer.observe(target); return () => observer.disconnect(); }, [hasNextPage, isFetchingNextPage, onLoadMore]); return ( Repair Issues {totalCount}
{detections.map((detection, index) => { const issueId = getIssueId(detection); const defectLabel = detection.detection.display_name; const status = getIssueReviewStatus(detection); const config = STATUS_CONFIG[status]; const StatusIcon = config.icon; const isSelected = issueId === selectedIssueId; return ( ); })}
{isFetchingNextPage ? ( <> ) : hasNextPage ? (

Scroll to load more issues

) : detections.length > 0 ? (

All {totalCount} issues loaded

) : null}
); }