diff --git a/packages/admin/src/components/repairs/ticket-photos.tsx b/packages/admin/src/components/repairs/ticket-photos.tsx index 2470938..1e2757c 100644 --- a/packages/admin/src/components/repairs/ticket-photos.tsx +++ b/packages/admin/src/components/repairs/ticket-photos.tsx @@ -26,6 +26,7 @@ const PHOTO_CATEGORIES = [ { key: 'intake', label: 'Intake Photos', description: 'Condition at intake' }, { key: 'in_progress', label: 'Work in Progress', description: 'During repair' }, { key: 'completed', label: 'Completed', description: 'Final result' }, + { key: 'document', label: 'Documents', description: 'Signed approvals, quotes, receipts' }, ] as const interface TicketPhotosProps { @@ -161,7 +162,7 @@ function PhotoSection({ = { const STATUS_FLOW = ['in_transit', 'intake', 'diagnosing', 'pending_approval', 'approved', 'in_progress', 'ready', 'picked_up'] +const TABS = [ + { key: 'details', label: 'Details' }, + { key: 'line-items', label: 'Line Items' }, + { key: 'notes', label: 'Notes' }, + { key: 'files', label: 'Photos & Docs' }, +] as const + +type TabKey = typeof TABS[number]['key'] + function RepairTicketDetailPage() { const { ticketId } = useParams({ from: '/_authenticated/repairs/$ticketId' }) const navigate = useNavigate() const queryClient = useQueryClient() const hasPermission = useAuthStore((s) => s.hasPermission) + const [activeTab, setActiveTab] = useState('details') const [addItemOpen, setAddItemOpen] = useState(false) const [editing, setEditing] = useState(false) const { params, setPage, setSort } = usePagination() @@ -64,7 +74,6 @@ function RepairTicketDetailPage() { const { data: ticket, isLoading } = useQuery(repairTicketDetailOptions(ticketId)) const { data: lineItemsData, isLoading: itemsLoading } = useQuery(repairLineItemListOptions(ticketId, params)) - // Edit form state const [editFields, setEditFields] = useState>({}) const statusMutation = useMutation({ @@ -131,11 +140,7 @@ function RepairTicketDetailPage() { if (editFields.technicianNotes !== (ticket!.technicianNotes ?? '')) data.technicianNotes = editFields.technicianNotes || undefined if (editFields.estimatedCost !== (ticket!.estimatedCost ?? '')) data.estimatedCost = editFields.estimatedCost ? parseFloat(editFields.estimatedCost) : undefined if (editFields.actualCost !== (ticket!.actualCost ?? '')) data.actualCost = editFields.actualCost ? parseFloat(editFields.actualCost) : undefined - - if (Object.keys(data).length === 0) { - setEditing(false) - return - } + if (Object.keys(data).length === 0) { setEditing(false); return } updateMutation.mutate(data) } @@ -165,7 +170,7 @@ function RepairTicketDetailPage() { ] return ( -
+
{/* Header */}

Ticket #{ticket.ticketNumber}

-

{ticket.customerName}

+

{ticket.customerName} — {ticket.instrumentDescription ?? 'No instrument'}

+
{/* Status Progress Bar */} - + {/* Status Actions */} - {hasPermission('repairs.edit') && !isTerminal && ( -
- {nextStatus && ( - - )} - {ticket.status === 'in_progress' && ( - - )} - {ticket.status === 'pending_parts' && ( - - )} - {hasPermission('repairs.admin') && ( - - )} -
- )} - - {/* Reopen for cancelled tickets */} - {ticket.status === 'cancelled' && hasPermission('repairs.admin') && ( - - )} - - {/* Ticket Details — View or Edit */} - - - Details - {hasPermission('repairs.edit') && !editing && ( - - )} - {editing && ( -
- - -
- )} -
- - {editing ? ( -
-
-
- - setEditFields((p) => ({ ...p, customerName: e.target.value }))} /> -
-
- - setEditFields((p) => ({ ...p, customerPhone: e.target.value }))} /> -
+ )} + {ticket.status === 'in_progress' && ( + + )} + {ticket.status === 'pending_parts' && ( + + )} + {hasPermission('repairs.admin') && ( + + )} + + )} + {ticket.status === 'cancelled' && hasPermission('repairs.admin') && ( + + )} +
+ + {/* Tabs */} +
+
+ {TABS.map((tab) => ( + + ))} +
+
+ + {/* Tab Content */} + {activeTab === 'details' && ( + + + Ticket Details + {hasPermission('repairs.edit') && !editing && ( + + )} + {editing && ( +
+ +
-
-
- - setEditFields((p) => ({ ...p, instrumentDescription: e.target.value }))} /> + )} + + + {editing ? ( +
+
+
setEditFields((p) => ({ ...p, customerName: e.target.value }))} />
+
setEditFields((p) => ({ ...p, customerPhone: e.target.value }))} />
-
- - setEditFields((p) => ({ ...p, serialNumber: e.target.value }))} /> +
+
setEditFields((p) => ({ ...p, instrumentDescription: e.target.value }))} />
+
setEditFields((p) => ({ ...p, serialNumber: e.target.value }))} />
-
-
-
- - -
-
- - setEditFields((p) => ({ ...p, estimatedCost: e.target.value }))} /> -
-
- - setEditFields((p) => ({ ...p, actualCost: e.target.value }))} /> +
+
+ + +
+
setEditFields((p) => ({ ...p, estimatedCost: e.target.value }))} />
+
setEditFields((p) => ({ ...p, actualCost: e.target.value }))} />
+