'use client'; import { useEffect } from 'react'; import { BriefcaseBusiness, CalendarClock, ChevronDown, Images, ListChecks, } from 'lucide-react'; import { PersonInfo } from '@/components/person-avatar'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from '@/components/ui/collapsible'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Progress } from '@/components/ui/progress'; import { getDefectVisual } from '@/constants/defectVisualConfig'; import { cn } from '@/lib/utils'; import type { TicketActor, TicketAssignmentSummary } from '@/types'; import { formatDate } from '@/utils/date'; import { useTicketAssignmentsQuery } from '../../hooks/useTicketQueries'; import { TicketDetectionPreview } from './TicketDetectionPreview'; interface TicketAssignmentsCardProps { ticketId: string; videoId?: string | null; initialAssignments?: TicketAssignmentSummary[]; selectedAssignmentId?: number; onAssignmentChange: (assignmentId: number) => void; } function formatLabel(value: string) { return value .replaceAll('_', ' ') .replace(/\b\w/g, (character) => character.toUpperCase()); } function AssignmentClassBadge({ className }: { className: string }) { const visual = getDefectVisual(className); const IssueIcon = visual.icon; return ( {formatLabel(className)} ); } function AssignmentProgress({ assignment, }: { assignment: TicketAssignmentSummary; }) { const total = Math.max(assignment.item_count, 0); const approved = Math.max(assignment.approved_detections, 0); const progress = total > 0 ? Math.min((approved / total) * 100, 100) : 0; return (
Repair progress {approved} of {total} approved
{assignment.approved_detections} approved {assignment.pending_detections} pending {assignment.not_submitted_detections} not submitted
); } function AssignmentOverview({ assignment, }: { assignment: TicketAssignmentSummary; }) { const criteria = assignment.criteria; const classNames = criteria?.class_names?.length ? criteria.class_names : assignment.defect_class ? [assignment.defect_class] : []; const worker: TicketActor = { user_id: assignment.assigned_to_user_id, name: assignment.assigned_to_name, email: assignment.assigned_to_email ?? null, avatar_url: assignment.assigned_to_avatar_url ?? null, }; return (

Assignment {assignment.id}

{classNames.map((className) => ( ))} {assignment.item_count}{' '} {assignment.item_count === 1 ? 'issue' : 'issues'} {assignment.due_at ? ( Due {formatDate(assignment.due_at)} ) : null}
); } export function TicketAssignmentsCard({ ticketId, videoId, initialAssignments, selectedAssignmentId, onAssignmentChange, }: TicketAssignmentsCardProps) { const assignmentsQuery = useTicketAssignmentsQuery( ticketId, initialAssignments, ); const assignments = (assignmentsQuery.data?.items ?? []).filter( (assignment) => assignment.item_count > 0, ); const selectedAssignment = assignments.find((assignment) => assignment.id === selectedAssignmentId) ?? assignments[0]; const activeAssignmentId = selectedAssignment ? String(selectedAssignment.id) : ''; const resolvedAssignmentId = selectedAssignment?.id; useEffect(() => { if ( resolvedAssignmentId !== undefined && resolvedAssignmentId !== selectedAssignmentId ) { onAssignmentChange(resolvedAssignmentId); } }, [onAssignmentChange, resolvedAssignmentId, selectedAssignmentId]); return (
Work Assignments Issues grouped by assignee, scope, and repair progress.
{assignmentsQuery.data ? ( {assignments.length}{' '} {assignments.length === 1 ? 'Assignment' : 'Assignments'} ) : null}
{assignmentsQuery.isLoading ? ( Array.from({ length: 2 }).map((_, index) => (
)) ) : assignmentsQuery.isError ? (

Unable to load work assignments.

) : selectedAssignment ? (
{videoId ? (
) : null}
) : (

No work assignments yet

Work assignments will appear here after issues are allocated.

)} ); }