'use client'; import { useEffect, useMemo, useState } from 'react'; import { AlertTriangle, ChevronLeft, ChevronRight, Trash2 } from 'lucide-react'; import DetectionLocationMap from '@/components/map/detectionLocationMap'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Skeleton } from '@/components/ui/skeleton'; import AnnotatedDetectionImage from '@/components/video/annotatedDetectionImage'; import { getDefectVisual } from '@/constants/defectVisualConfig'; import { cn } from '@/lib/utils'; import { useDiscardDetectionMutation, useTicketDetectionsQuery, } from '../../hooks/useTicketQueries'; import { DetectionDiscardDialog } from './DetectionDiscardDialog'; interface TicketDetectionPreviewProps { ticketId: string; videoId?: string | null; assignmentId: number; } function DetectionMetadataBar({ items, }: { items: { label: string; value: string | number }[]; }) { return (
{items.map((item, index) => (

{item.label}

{item.value}
))}
); } function TicketDetectionPreviewSkeleton() { return ( <>
{Array.from({ length: 3 }).map((_, index) => (
))}
); } export function TicketDetectionPreview({ ticketId, videoId, assignmentId, }: TicketDetectionPreviewProps) { const [currentIndex, setCurrentIndex] = useState(0); const [isDiscardDialogOpen, setIsDiscardDialogOpen] = useState(false); useEffect(() => { setCurrentIndex(0); }, [assignmentId, videoId]); const queryParams = useMemo( () => ({ skip: currentIndex, limit: 1, assignment_id: assignmentId, sort: 'timestamp_asc', }), [assignmentId, currentIndex], ); const detectionsQuery = useTicketDetectionsQuery( videoId ?? undefined, queryParams, ); const detectionResult = detectionsQuery.data; const activeDetection = detectionResult?.items[0]; const confirmedDetectionCount = detectionResult?.total; const detectionCount = detectionResult?.total ?? 0; const activeVisual = getDefectVisual( activeDetection?.detection.class_name ?? '', ); const ActiveIssueIcon = activeVisual.icon; const activeDisplayName = activeDetection?.detection.display_name ?? 'Detection'; const discardMutation = useDiscardDetectionMutation( ticketId, videoId ?? undefined, ); useEffect(() => { if (confirmedDetectionCount === undefined) return; if (confirmedDetectionCount === 0 && currentIndex !== 0) { setCurrentIndex(0); return; } if ( confirmedDetectionCount > 0 && currentIndex > confirmedDetectionCount - 1 ) { setCurrentIndex(confirmedDetectionCount - 1); } }, [confirmedDetectionCount, currentIndex]); const isNavigationDisabled = detectionCount === 0 || detectionsQuery.isLoading; return (

{activeDisplayName}

{detectionCount} Detections

Review all detections in ascending timestamp order.

{detectionCount === 0 ? '0 of 0' : `${currentIndex + 1} of ${detectionCount}`}
{detectionsQuery.isLoading && !detectionsQuery.data ? ( ) : detectionsQuery.isError ? (

Failed to load detection preview.

) : !activeDetection || !detectionResult ? (
No detections are available for this issue.
) : ( <>

Detection Image

{ await discardMutation.mutateAsync({ detectionId: activeDetection.detection.id, payload, }); setIsDiscardDialogOpen(false); }} /> )}
); }