diff --git a/frontend/src/features/vehicles/mobile/VehicleDetailMobile.tsx b/frontend/src/features/vehicles/mobile/VehicleDetailMobile.tsx index 7f9d16f..bef18a7 100644 --- a/frontend/src/features/vehicles/mobile/VehicleDetailMobile.tsx +++ b/frontend/src/features/vehicles/mobile/VehicleDetailMobile.tsx @@ -12,6 +12,9 @@ import { FuelLogResponse, UpdateFuelLogRequest } from '../../fuel-logs/types/fue import { FuelLogEditDialog } from '../../fuel-logs/components/FuelLogEditDialog'; import { fuelLogsApi } from '../../fuel-logs/api/fuel-logs.api'; import { MaintenanceRecordForm } from '../../maintenance/components/MaintenanceRecordForm'; +import { useMaintenanceRecords } from '../../maintenance/hooks/useMaintenanceRecords'; +import { getCategoryDisplayName } from '../../maintenance/types/maintenance.types'; +import type { MaintenanceRecordResponse } from '../../maintenance/types/maintenance.types'; import { VehicleImage } from '../components/VehicleImage'; import { OwnershipCostsList } from '../../ownership-costs'; import { getVehicleLabel } from '@/core/utils/vehicleDisplay'; @@ -46,6 +49,7 @@ export const VehicleDetailMobile: React.FC = ({ const [recordFilter, setRecordFilter] = useState<'All' | 'Fuel Logs' | 'Maintenance' | 'Documents'>('All'); const { fuelLogs, isLoading: isFuelLoading } = useFuelLogs(vehicle.id); + const { records: maintenanceRecords, isRecordsLoading: isMaintenanceLoading } = useMaintenanceRecords(vehicle.id); const queryClient = useQueryClient(); const [editingLog, setEditingLog] = useState(null); const [showMaintenanceDialog, setShowMaintenanceDialog] = useState(false); @@ -124,8 +128,34 @@ export const VehicleDetailMobile: React.FC = ({ }); } } + + if (maintenanceRecords && Array.isArray(maintenanceRecords)) { + for (const rec of maintenanceRecords as MaintenanceRecordResponse[]) { + const catLabel = getCategoryDisplayName(rec.category); + const subtypes = Array.isArray(rec.subtypes) ? rec.subtypes : []; + const subtypeText = subtypes.length + ? `${subtypes.slice(0, 3).join(', ')}${subtypes.length > 3 ? ` +${subtypes.length - 3}` : ''}` + : ''; + const summary = subtypeText ? `${catLabel} — ${subtypeText}` : catLabel; + const secondaryParts: string[] = []; + if (rec.shopName) secondaryParts.push(rec.shopName); + secondaryParts.push(new Date(rec.date).toLocaleDateString()); + secondaryParts.push('Maintenance'); + const secondary = secondaryParts.join(' • '); + const amount = typeof rec.cost === 'number' ? `$${rec.cost.toFixed(2)}` : undefined; + list.push({ + id: rec.id, + type: 'Maintenance', + date: rec.date, + summary, + amount, + secondary + }); + } + } + return list.sort((a, b) => b.date.localeCompare(a.date)); - }, [fuelLogs]); + }, [fuelLogs, maintenanceRecords]); const filteredRecords = useMemo(() => { if (recordFilter === 'All') return records; @@ -243,7 +273,7 @@ export const VehicleDetailMobile: React.FC = ({
- {isFuelLoading ? 'Loading…' : `${filteredRecords.length} record${filteredRecords.length === 1 ? '' : 's'}`} + {(isFuelLoading || isMaintenanceLoading) ? 'Loading…' : `${filteredRecords.length} record${filteredRecords.length === 1 ? '' : 's'}`} Filter @@ -262,7 +292,7 @@ export const VehicleDetailMobile: React.FC = ({ - {isFuelLoading ? ( + {(isFuelLoading || isMaintenanceLoading) ? ( Loading records… diff --git a/frontend/src/features/vehicles/pages/VehicleDetailPage.tsx b/frontend/src/features/vehicles/pages/VehicleDetailPage.tsx index 179aef4..65e7e0f 100644 --- a/frontend/src/features/vehicles/pages/VehicleDetailPage.tsx +++ b/frontend/src/features/vehicles/pages/VehicleDetailPage.tsx @@ -23,6 +23,9 @@ import { FuelLogResponse, UpdateFuelLogRequest } from '../../fuel-logs/types/fue import { FuelLogEditDialog } from '../../fuel-logs/components/FuelLogEditDialog'; import { FuelLogForm } from '../../fuel-logs/components/FuelLogForm'; import { MaintenanceRecordForm } from '../../maintenance/components/MaintenanceRecordForm'; +import { useMaintenanceRecords } from '../../maintenance/hooks/useMaintenanceRecords'; +import { getCategoryDisplayName } from '../../maintenance/types/maintenance.types'; +import type { MaintenanceRecordResponse } from '../../maintenance/types/maintenance.types'; // Unit conversions now handled by backend import { fuelLogsApi } from '../../fuel-logs/api/fuel-logs.api'; import { OwnershipCostsList } from '../../ownership-costs'; @@ -60,6 +63,7 @@ export const VehicleDetailPage: React.FC = () => { const { fuelLogs, isLoading: isFuelLoading } = useFuelLogs(id); const { data: documents, isLoading: isDocumentsLoading } = useDocumentsByVehicle(id); + const { records: maintenanceRecords, isRecordsLoading: isMaintenanceLoading } = useMaintenanceRecords(id); const { mutateAsync: deleteDocument } = useDeleteDocument(); const { mutateAsync: removeVehicleFromDocument } = useRemoveVehicleFromDocument(); const queryClient = useQueryClient(); @@ -133,8 +137,24 @@ export const VehicleDetailPage: React.FC = () => { } } + if (maintenanceRecords && Array.isArray(maintenanceRecords)) { + for (const rec of maintenanceRecords as MaintenanceRecordResponse[]) { + const catLabel = getCategoryDisplayName(rec.category); + const subtypes = Array.isArray(rec.subtypes) ? rec.subtypes : []; + const subtypeText = subtypes.length + ? `${subtypes.slice(0, 3).join(', ')}${subtypes.length > 3 ? ` +${subtypes.length - 3}` : ''}` + : ''; + const parts: string[] = [catLabel]; + if (subtypeText) parts.push(subtypeText); + if (rec.shopName) parts.push(rec.shopName); + const summary = parts.join(' • '); + const amount = typeof rec.cost === 'number' ? `$${rec.cost.toFixed(2)}` : undefined; + list.push({ id: rec.id, type: 'Maintenance', date: rec.date, summary, amount }); + } + } + return list.sort((a, b) => b.date.localeCompare(a.date)); - }, [fuelLogs, documents]); + }, [fuelLogs, documents, maintenanceRecords]); const filteredRecords = useMemo(() => { if (recordFilter === 'All') return records; @@ -475,22 +495,22 @@ export const VehicleDetailPage: React.FC = () => { - {(isFuelLoading || isDocumentsLoading) && ( + {(isFuelLoading || isDocumentsLoading || isMaintenanceLoading) && ( Loading records… )} - {!isFuelLoading && !isDocumentsLoading && filteredRecords.length === 0 && ( + {!isFuelLoading && !isDocumentsLoading && !isMaintenanceLoading && filteredRecords.length === 0 && ( No records found for this filter. )} - {!isFuelLoading && !isDocumentsLoading && filteredRecords.map((rec) => ( - handleRowClick(rec.id, rec.type)}> + {!isFuelLoading && !isDocumentsLoading && !isMaintenanceLoading && filteredRecords.map((rec) => ( + handleRowClick(rec.id, rec.type)}> {dayjs(rec.date).format('M/D/YYYY')} {rec.type} {rec.summary}