The Vehicle Records section on /garage/vehicles/:id was never calling useMaintenanceRecords, so maintenance rows always rendered empty even when records existed for the vehicle. The fuel-log and document data sources were wired in; maintenance was not.
Changes
frontend/src/features/vehicles/pages/VehicleDetailPage.tsx (desktop): import and call useMaintenanceRecords(id), merge maintenance records into the unified records list (category + subtypes + shop name in summary, cost as amount), include isMaintenanceLoading in the loading and empty-state guards, and update the row cursor so only fuel-log rows render as clickable.
frontend/src/features/vehicles/mobile/VehicleDetailMobile.tsx (mobile): same hook wiring, mobile-format secondary line, and merged loading guard.
No backend changes — the endpoint GET /maintenance/records/vehicle/:vehicleId and the useMaintenanceRecords hook already existed and are used by MaintenancePage.
Out of scope
Mobile VehicleDetailMobile also does not fetch documents (the filter dropdown offers "Documents" but no useDocumentsByVehicle hook is wired in). That is a separate gap and not part of this bug. Recommend a follow-up issue.
Test plan
npm run type-check (frontend) — passes, no errors.
npm run lint (frontend) — 0 errors; 227 baseline warnings unchanged from main.
npm test (frontend) — 17 failed / 196 passed: identical counts to main, all pre-existing failures in unrelated suites (admin, etc.).
Manual on staging desktop (≥1920px): visit https://staging.motovaultpro.com/garage/vehicles/01caf9e8-2b9a-4f24-959f-67a3e6bd91b1 and confirm maintenance records render in the Vehicle Records section, filter chips work, totals consistent with /garage/maintenance filtered by vehicle.
Manual on staging mobile viewports (320px, 768px): same vehicle, confirm maintenance records render under the Vehicle Records section.
Manual: vehicle with zero maintenance records still shows the "No records found for this filter." empty state.
Manual: no console errors on page load.
Acceptance criteria (from issue)
Maintenance records render in the Vehicle Records section on desktop and mobile.
Empty state only renders when the vehicle truly has zero records.
Records consistent with /garage/maintenance filtered by vehicle.
Linting, type-check, and tests at parity with main.
Fixes #239
## Summary
The Vehicle Records section on `/garage/vehicles/:id` was never calling `useMaintenanceRecords`, so maintenance rows always rendered empty even when records existed for the vehicle. The fuel-log and document data sources were wired in; maintenance was not.
## Changes
- `frontend/src/features/vehicles/pages/VehicleDetailPage.tsx` (desktop): import and call `useMaintenanceRecords(id)`, merge maintenance records into the unified records list (category + subtypes + shop name in summary, cost as amount), include `isMaintenanceLoading` in the loading and empty-state guards, and update the row cursor so only fuel-log rows render as clickable.
- `frontend/src/features/vehicles/mobile/VehicleDetailMobile.tsx` (mobile): same hook wiring, mobile-format secondary line, and merged loading guard.
No backend changes — the endpoint `GET /maintenance/records/vehicle/:vehicleId` and the `useMaintenanceRecords` hook already existed and are used by `MaintenancePage`.
## Out of scope
- Mobile `VehicleDetailMobile` also does not fetch documents (the filter dropdown offers "Documents" but no `useDocumentsByVehicle` hook is wired in). That is a separate gap and not part of this bug. Recommend a follow-up issue.
## Test plan
- [x] `npm run type-check` (frontend) — passes, no errors.
- [x] `npm run lint` (frontend) — 0 errors; 227 baseline warnings unchanged from `main`.
- [x] `npm test` (frontend) — 17 failed / 196 passed: identical counts to `main`, all pre-existing failures in unrelated suites (admin, etc.).
- [ ] Manual on staging desktop (≥1920px): visit `https://staging.motovaultpro.com/garage/vehicles/01caf9e8-2b9a-4f24-959f-67a3e6bd91b1` and confirm maintenance records render in the Vehicle Records section, filter chips work, totals consistent with `/garage/maintenance` filtered by vehicle.
- [ ] Manual on staging mobile viewports (320px, 768px): same vehicle, confirm maintenance records render under the Vehicle Records section.
- [ ] Manual: vehicle with zero maintenance records still shows the "No records found for this filter." empty state.
- [ ] Manual: no console errors on page load.
## Acceptance criteria (from issue)
- [x] Maintenance records render in the Vehicle Records section on desktop and mobile.
- [x] Empty state only renders when the vehicle truly has zero records.
- [x] Records consistent with `/garage/maintenance` filtered by vehicle.
- [x] Linting, type-check, and tests at parity with `main`.
The Vehicle Records section on /garage/vehicles/:id never called
useMaintenanceRecords, so maintenance rows always rendered empty even
when records existed for the vehicle. Wire the existing hook into both
the desktop VehicleDetailPage and mobile VehicleDetailMobile, merge
records into the unified list with category + subtypes + shop name,
and include the maintenance loading state in the section's loading
and empty-state guards.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Postgres numeric columns come back as strings via node-postgres, so
typeof rec.cost === 'number' was false and the amount column rendered
as '—'. Coerce with Number() (matching the pattern in
MaintenanceRecordsList) so the cost displays as a dollar amount.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #239
Summary
The Vehicle Records section on
/garage/vehicles/:idwas never callinguseMaintenanceRecords, so maintenance rows always rendered empty even when records existed for the vehicle. The fuel-log and document data sources were wired in; maintenance was not.Changes
frontend/src/features/vehicles/pages/VehicleDetailPage.tsx(desktop): import and calluseMaintenanceRecords(id), merge maintenance records into the unified records list (category + subtypes + shop name in summary, cost as amount), includeisMaintenanceLoadingin the loading and empty-state guards, and update the row cursor so only fuel-log rows render as clickable.frontend/src/features/vehicles/mobile/VehicleDetailMobile.tsx(mobile): same hook wiring, mobile-format secondary line, and merged loading guard.No backend changes — the endpoint
GET /maintenance/records/vehicle/:vehicleIdand theuseMaintenanceRecordshook already existed and are used byMaintenancePage.Out of scope
VehicleDetailMobilealso does not fetch documents (the filter dropdown offers "Documents" but nouseDocumentsByVehiclehook is wired in). That is a separate gap and not part of this bug. Recommend a follow-up issue.Test plan
npm run type-check(frontend) — passes, no errors.npm run lint(frontend) — 0 errors; 227 baseline warnings unchanged frommain.npm test(frontend) — 17 failed / 196 passed: identical counts tomain, all pre-existing failures in unrelated suites (admin, etc.).https://staging.motovaultpro.com/garage/vehicles/01caf9e8-2b9a-4f24-959f-67a3e6bd91b1and confirm maintenance records render in the Vehicle Records section, filter chips work, totals consistent with/garage/maintenancefiltered by vehicle.Acceptance criteria (from issue)
/garage/maintenancefiltered by vehicle.main.