import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { repairTicketDetailOptions, repairTicketKeys, repairTicketMutations, repairLineItemListOptions, repairLineItemMutations, repairServiceTemplateListOptions, repairNoteListOptions, repairNoteMutations, } from '@/api/repairs' import { StatusProgress } from '@/components/repairs/status-progress' import { TicketPhotos } from '@/components/repairs/ticket-photos' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Separator } from '@/components/ui/separator' import { ChevronRight, Plus, Camera, MessageSquare, Wrench, Trash2 } from 'lucide-react' import { toast } from 'sonner' const STATUS_FLOW = ['new', 'intake', 'diagnosing', 'pending_approval', 'approved', 'in_progress', 'ready', 'picked_up'] interface RepairWorkbenchProps { ticketId: string } export function RepairWorkbench({ ticketId }: RepairWorkbenchProps) { const queryClient = useQueryClient() const [activeSection, setActiveSection] = useState<'work' | 'parts' | 'photos' | 'notes'>('work') const [newNote, setNewNote] = useState('') // Add line item state const [addingItem, setAddingItem] = useState(false) const [newItemType, setNewItemType] = useState('part') const [newItemDesc, setNewItemDesc] = useState('') const [newItemQty, setNewItemQty] = useState('1') const [newItemPrice, setNewItemPrice] = useState('') const { data: ticket } = useQuery({ ...repairTicketDetailOptions(ticketId), staleTime: 15_000, }) const { data: lineItemsData } = useQuery({ ...repairLineItemListOptions(ticketId, { page: 1, limit: 100, q: undefined, sort: undefined, order: 'asc' }), }) const { data: notesData } = useQuery(repairNoteListOptions(ticketId)) const { data: templatesData } = useQuery({ ...repairServiceTemplateListOptions({ page: 1, limit: 50, q: undefined, sort: 'sort_order', order: 'asc' }), }) const statusMutation = useMutation({ mutationFn: (status: string) => repairTicketMutations.updateStatus(ticketId, status), onSuccess: () => { queryClient.invalidateQueries({ queryKey: repairTicketKeys.detail(ticketId) }) toast.success('Status updated') }, onError: (err) => toast.error(err.message), }) const addNoteMutation = useMutation({ mutationFn: () => repairNoteMutations.create(ticketId, { content: newNote, visibility: 'internal' }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['repair-tickets', ticketId, 'notes'] }) setNewNote('') toast.success('Note added') }, onError: (err) => toast.error(err.message), }) const addLineItemMutation = useMutation({ mutationFn: () => repairLineItemMutations.create(ticketId, { itemType: newItemType, description: newItemDesc, qty: parseInt(newItemQty) || 1, unitPrice: parseFloat(newItemPrice) || 0, }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['repair-tickets', ticketId, 'line-items'] }) setAddingItem(false) setNewItemDesc('') setNewItemPrice('') toast.success('Item added') }, onError: (err) => toast.error(err.message), }) const deleteLineItemMutation = useMutation({ mutationFn: (id: string) => repairLineItemMutations.delete(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['repair-tickets', ticketId, 'line-items'] }) toast.success('Item removed') }, onError: (err) => toast.error(err.message), }) if (!ticket) { return (
) } const lineItems = lineItemsData?.data ?? [] const notes = notesData?.data ?? [] const templates = templatesData?.data ?? [] const currentIdx = STATUS_FLOW.indexOf(ticket.status) const nextStatus = currentIdx >= 0 && currentIdx < STATUS_FLOW.length - 1 ? STATUS_FLOW[currentIdx + 1] : null const isTerminal = ['picked_up', 'delivered', 'cancelled'].includes(ticket.status) return (
{/* Header */}

#{ticket.ticketNumber}

{ticket.customerName} — {ticket.itemDescription ?? 'No item'}

{nextStatus && !isTerminal && ( )}
!isTerminal && statusMutation.mutate(s)} />
{/* Section toggle */}
{[ { key: 'work' as const, icon: Wrench, label: 'Work' }, { key: 'parts' as const, icon: Plus, label: 'Parts' }, { key: 'photos' as const, icon: Camera, label: 'Photos' }, { key: 'notes' as const, icon: MessageSquare, label: `Notes (${notes.length})` }, ].map((s) => ( ))}
{/* Content */}
{activeSection === 'work' && (

Problem Description

{ticket.problemDescription}

{ticket.conditionIn && (

Condition at Intake

{ticket.conditionIn} {ticket.conditionInNotes &&

{ticket.conditionInNotes}

}
)} {ticket.technicianNotes && (

Technician Notes

{ticket.technicianNotes}

)}
{ticket.estimatedCost &&

Estimate

${ticket.estimatedCost}

} {ticket.actualCost &&

Actual

${ticket.actualCost}

} {ticket.promisedDate &&

Promised

{new Date(ticket.promisedDate).toLocaleDateString()}

}
)} {activeSection === 'parts' && (

Line Items

{/* Template quick-add */} {templates.length > 0 && (
{templates.slice(0, 8).map(t => ( ))}
)} {addingItem && (
setNewItemDesc(e.target.value)} />
setNewItemQty(e.target.value)} />
setNewItemPrice(e.target.value)} />
)}
{lineItems.map((item) => (
{item.itemType} {item.description} x{item.qty}
${item.totalPrice}
))} {lineItems.length > 0 && ( <>
Total ${lineItems.reduce((s, i) => s + parseFloat(i.totalPrice), 0).toFixed(2)}
)} {lineItems.length === 0 && !addingItem && (

No line items yet

)}
)} {activeSection === 'photos' && ( )} {activeSection === 'notes' && (