fix: Scheduled maintenance list not displaying schedules (#129) #148

Closed
opened 2026-02-13 01:45:41 +00:00 by egullickson · 2 comments
Owner

Relates to #129

Summary

The Schedules tab on the Maintenance page is always empty despite schedules existing in the database (e.g., 30 schedules created from manual OCR extraction). The UI components are fully implemented but the data query never executes.

Root Cause

MaintenancePage.tsx (line 20) calls useMaintenanceRecords() without a vehicleId parameter:

// BUG: No vehicleId passed
const { records, schedules, isRecordsLoading, isSchedulesLoading, ... } = useMaintenanceRecords();

The schedules query in useMaintenanceRecords.ts has enabled: !!vehicleId -- when vehicleId is undefined, the query never runs. The list stays empty.

Additionally, the creation hook (useCreateSchedulesFromExtraction) invalidates ['maintenanceSchedules', vehicleId] with the actual vehicleId, but the page-level query uses ['maintenanceSchedules', undefined] -- the keys don't match, so invalidation has no effect.

Requirements

  • Wire vehicleId from vehicle selection/context into useMaintenanceRecords(vehicleId)
  • Ensure query invalidation keys match between creation and list fetching
  • Both Records and Schedules tabs need vehicle context to display data
  • Follow existing patterns (e.g., FuelLogsPage uses useFuelLogs(vehicleId))
  • Mobile + desktop must work

Acceptance Criteria

  • Schedules tab displays all schedules for the selected vehicle
  • Records tab displays all records for the selected vehicle
  • Due soon and overdue indicators display correctly
  • After OCR creates schedules, navigating to Schedules tab shows them
  • Edit and delete actions work on displayed schedules
  • Works on mobile (320px, 768px) and desktop (1920px) viewports
Relates to #129 ## Summary The Schedules tab on the Maintenance page is always empty despite schedules existing in the database (e.g., 30 schedules created from manual OCR extraction). The UI components are fully implemented but the data query never executes. ## Root Cause `MaintenancePage.tsx` (line 20) calls `useMaintenanceRecords()` **without a vehicleId parameter**: ```typescript // BUG: No vehicleId passed const { records, schedules, isRecordsLoading, isSchedulesLoading, ... } = useMaintenanceRecords(); ``` The schedules query in `useMaintenanceRecords.ts` has `enabled: !!vehicleId` -- when vehicleId is undefined, the query never runs. The list stays empty. Additionally, the creation hook (`useCreateSchedulesFromExtraction`) invalidates `['maintenanceSchedules', vehicleId]` with the actual vehicleId, but the page-level query uses `['maintenanceSchedules', undefined]` -- the keys don't match, so invalidation has no effect. ## Requirements - Wire vehicleId from vehicle selection/context into `useMaintenanceRecords(vehicleId)` - Ensure query invalidation keys match between creation and list fetching - Both Records and Schedules tabs need vehicle context to display data - Follow existing patterns (e.g., FuelLogsPage uses `useFuelLogs(vehicleId)`) - Mobile + desktop must work ## Acceptance Criteria - [ ] Schedules tab displays all schedules for the selected vehicle - [ ] Records tab displays all records for the selected vehicle - [ ] Due soon and overdue indicators display correctly - [ ] After OCR creates schedules, navigating to Schedules tab shows them - [ ] Edit and delete actions work on displayed schedules - [ ] Works on mobile (320px, 768px) and desktop (1920px) viewports
egullickson added the
status
in-progress
type
feature
labels 2026-02-13 01:45:46 +00:00
egullickson changed title from feat: Scheduled maintenance list UI with CRUD and due status (#129) to fix: Scheduled maintenance list not displaying schedules (#129) 2026-02-13 01:52:18 +00:00
egullickson added
type
bug
and removed
type
feature
labels 2026-02-13 01:52:19 +00:00
Author
Owner

Plan: Fix scheduled maintenance list not displaying schedules

Phase: Planning | Agent: Planner | Status: AWAITING_REVIEW

Root Cause Analysis

MaintenancePage.tsx and MaintenanceMobileScreen.tsx both call useMaintenanceRecords() without a vehicleId. The hook's schedules query has enabled: !!vehicleId, so it never executes. Records work because the hook falls back to getRecords() (all records), but schedules require vehicleId because the backend only has GET /maintenance/schedules/vehicle/:vehicleId (no "get all schedules" endpoint).

Fix Strategy

Add a vehicle selector to the Maintenance page (matching the FuelLogs pattern) and pass the selected vehicleId to the hook. This is a frontend-only fix -- no backend changes needed.

Milestone 1: Wire vehicleId into MaintenancePage and MaintenanceMobileScreen

Files to modify (3):

  1. frontend/src/features/maintenance/pages/MaintenancePage.tsx

    • Add selectedVehicleId state (useState)
    • Add a vehicle selector at the top of the page (use useVehicles() hook + MUI Select, matching the inline pattern already used in MaintenanceRecordForm)
    • Pass selectedVehicleId to useMaintenanceRecords(selectedVehicleId)
    • Auto-select first vehicle if user has vehicles and none selected
    • Pass selectedVehicleId to forms as default vehicle (optional UX improvement)
  2. frontend/src/features/maintenance/mobile/MaintenanceMobileScreen.tsx

    • Same changes as MaintenancePage: add vehicle selector state, add selector UI, pass to hook
    • Ensure vehicle selector is mobile-friendly (44px touch targets, full-width)
  3. frontend/src/features/maintenance/hooks/useMaintenanceRecords.ts (verification only)

    • Verify the hook already accepts vehicleId?: string and passes it correctly
    • No changes expected -- the hook is already correctly designed, just not being called with a vehicleId

Expected Behavior After Fix

  1. User navigates to Maintenance page
  2. Vehicle selector shows at top, auto-selects first vehicle
  3. Records tab shows records for selected vehicle (was already partially working for "all")
  4. Schedules tab shows all schedules for selected vehicle (currently broken)
  5. Due soon / overdue indicators display correctly
  6. Changing vehicle selector updates both tabs
  7. After OCR creates schedules, returning to Maintenance page with that vehicle selected shows the new schedules

Out of Scope

  • No backend changes (API already supports this)
  • No changes to schedule CRUD components (already working)
  • No changes to OCR extraction flow
  • No new VehicleSelector shared component (use inline Select matching existing form pattern)

Risk Assessment

  • Low risk: Small, targeted change to 2 page files
  • No API changes: Backend already supports vehicleId-scoped queries
  • Pattern proven: FuelLogs uses the same approach successfully

Verdict: AWAITING_REVIEW | Next: User approval, then execution

## Plan: Fix scheduled maintenance list not displaying schedules **Phase**: Planning | **Agent**: Planner | **Status**: AWAITING_REVIEW ### Root Cause Analysis `MaintenancePage.tsx` and `MaintenanceMobileScreen.tsx` both call `useMaintenanceRecords()` without a `vehicleId`. The hook's schedules query has `enabled: !!vehicleId`, so it never executes. Records work because the hook falls back to `getRecords()` (all records), but schedules require `vehicleId` because the backend only has `GET /maintenance/schedules/vehicle/:vehicleId` (no "get all schedules" endpoint). ### Fix Strategy Add a vehicle selector to the Maintenance page (matching the FuelLogs pattern) and pass the selected vehicleId to the hook. This is a frontend-only fix -- no backend changes needed. ### Milestone 1: Wire vehicleId into MaintenancePage and MaintenanceMobileScreen **Files to modify (3):** 1. **`frontend/src/features/maintenance/pages/MaintenancePage.tsx`** - Add `selectedVehicleId` state (useState) - Add a vehicle selector at the top of the page (use `useVehicles()` hook + MUI Select, matching the inline pattern already used in MaintenanceRecordForm) - Pass `selectedVehicleId` to `useMaintenanceRecords(selectedVehicleId)` - Auto-select first vehicle if user has vehicles and none selected - Pass `selectedVehicleId` to forms as default vehicle (optional UX improvement) 2. **`frontend/src/features/maintenance/mobile/MaintenanceMobileScreen.tsx`** - Same changes as MaintenancePage: add vehicle selector state, add selector UI, pass to hook - Ensure vehicle selector is mobile-friendly (44px touch targets, full-width) 3. **`frontend/src/features/maintenance/hooks/useMaintenanceRecords.ts`** (verification only) - Verify the hook already accepts `vehicleId?: string` and passes it correctly - No changes expected -- the hook is already correctly designed, just not being called with a vehicleId ### Expected Behavior After Fix 1. User navigates to Maintenance page 2. Vehicle selector shows at top, auto-selects first vehicle 3. Records tab shows records for selected vehicle (was already partially working for "all") 4. Schedules tab shows all schedules for selected vehicle (currently broken) 5. Due soon / overdue indicators display correctly 6. Changing vehicle selector updates both tabs 7. After OCR creates schedules, returning to Maintenance page with that vehicle selected shows the new schedules ### Out of Scope - No backend changes (API already supports this) - No changes to schedule CRUD components (already working) - No changes to OCR extraction flow - No new VehicleSelector shared component (use inline Select matching existing form pattern) ### Risk Assessment - **Low risk**: Small, targeted change to 2 page files - **No API changes**: Backend already supports vehicleId-scoped queries - **Pattern proven**: FuelLogs uses the same approach successfully *Verdict*: AWAITING_REVIEW | *Next*: User approval, then execution
Author
Owner

Milestone 1: Wire vehicleId into MaintenancePage and MaintenanceMobileScreen

Phase: Execution | Agent: Developer | Status: PASS

Changes Made

frontend/src/features/maintenance/pages/MaintenancePage.tsx

  • Added useVehicles() hook and selectedVehicleId state
  • Added vehicle selector dropdown (MUI Select) above tabs
  • Auto-selects first vehicle on load via useEffect
  • Passes selectedVehicleId to useMaintenanceRecords(selectedVehicleId || undefined)
  • Fixed stale ['maintenanceRecords', 'all'] refetch key in delete handler to use broad ['maintenanceRecords'] prefix

frontend/src/features/maintenance/mobile/MaintenanceMobileScreen.tsx

  • Same vehicle selector logic as desktop
  • Mobile-optimized: 44px minHeight on Select and MenuItems for touch targets
  • Full-width selector inside GlassCard header section

frontend/src/features/maintenance/hooks/useMaintenanceRecords.ts (verified, no changes needed)

  • Hook already correctly accepts vehicleId?: string and gates schedules query on enabled: !!vehicleId
  • Query keys properly use vehicleId for cache scoping

Query Invalidation Alignment Verified

Source Key Pattern Matches Page Query
useMaintenanceRecords mutations ['maintenanceSchedules'] (broad) Yes
useCreateSchedulesFromExtraction ['maintenanceSchedules', vehicleId] Yes (exact match)
Page delete handlers ['maintenanceRecords'] (broad, fixed) Yes

Quality Checks

  • Lint: 0 errors (223 pre-existing warnings, none in modified files)
  • Type-check: Pass (tsc --noEmit clean)
  • Tests: 147 passed, 8 failed (all pre-existing failures in unrelated features: stations, admin, documents)

Commit

6bb2c57 - fix: Wire vehicleId into maintenance page to display schedules (refs #148)

Verdict: PASS | Next: PR creation and final review

## Milestone 1: Wire vehicleId into MaintenancePage and MaintenanceMobileScreen **Phase**: Execution | **Agent**: Developer | **Status**: PASS ### Changes Made **`frontend/src/features/maintenance/pages/MaintenancePage.tsx`** - Added `useVehicles()` hook and `selectedVehicleId` state - Added vehicle selector dropdown (MUI Select) above tabs - Auto-selects first vehicle on load via useEffect - Passes `selectedVehicleId` to `useMaintenanceRecords(selectedVehicleId || undefined)` - Fixed stale `['maintenanceRecords', 'all']` refetch key in delete handler to use broad `['maintenanceRecords']` prefix **`frontend/src/features/maintenance/mobile/MaintenanceMobileScreen.tsx`** - Same vehicle selector logic as desktop - Mobile-optimized: 44px minHeight on Select and MenuItems for touch targets - Full-width selector inside GlassCard header section **`frontend/src/features/maintenance/hooks/useMaintenanceRecords.ts`** (verified, no changes needed) - Hook already correctly accepts `vehicleId?: string` and gates schedules query on `enabled: !!vehicleId` - Query keys properly use vehicleId for cache scoping ### Query Invalidation Alignment Verified | Source | Key Pattern | Matches Page Query | |--------|------------|-------------------| | `useMaintenanceRecords` mutations | `['maintenanceSchedules']` (broad) | Yes | | `useCreateSchedulesFromExtraction` | `['maintenanceSchedules', vehicleId]` | Yes (exact match) | | Page delete handlers | `['maintenanceRecords']` (broad, fixed) | Yes | ### Quality Checks - Lint: 0 errors (223 pre-existing warnings, none in modified files) - Type-check: Pass (tsc --noEmit clean) - Tests: 147 passed, 8 failed (all pre-existing failures in unrelated features: stations, admin, documents) ### Commit `6bb2c57` - `fix: Wire vehicleId into maintenance page to display schedules (refs #148)` *Verdict*: PASS | *Next*: PR creation and final review
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: egullickson/motovaultpro#148