# Maintenance Reminders (Phase 4.6) ## Overview Maintenance reminders allow shops to set mileage-based follow-up reminders for customers after service. Reminders are created from the RO Detail Modal and displayed on the Dashboard. ## PocketBase Collection: `reminders` | Field | Type | Notes | |-------|------|-------| | `customerId` | text | From RO's `customerId` | | `customerName` | text | Pre-filled from RO | | `vehicleInfo` | text | Pre-filled from RO | | `shopUserId` | text | The shop's PB user ID | | `mileageAtService` | number | User-entered, pre-filled from `ro.mileage` | | `intervalMileage` | number | User-entered, defaults to 5000 | | `dueMileage` | number | Computed: `mileageAtService + intervalMileage` | | `notes` | text | Optional notes field | | `active` | bool | Set `true` on creation | ## Integration Points ### 1. RODetailModal.tsx — Set Reminder **Location**: Header area, in the button group next to Print/PDF/Generate Quote buttons. **Button**: `BellRing` icon, toggles the inline form. Pre-fills `reminderMileage` from `ro.mileage` when opened. Active state uses blue styling to indicate the form is open. **Inline Form** (appears below header, above info bar): - Blue-themed card (`border-blue-200 bg-blue-50`) - Shows customer name and vehicle info from RO (read-only) - Three fields in a grid: 1. Mileage at Service (pre-filled from `ro.mileage`) 2. Interval in miles (defaults to 5000) 3. Due Mileage (computed live: `(parseInt(mileage)||0) + (parseInt(interval)||0)`) - Notes textarea (optional) - Cancel / Save Reminder buttons with loading spinner **State variables** (in main `RODetailModal` component): ``` showReminderForm, reminderMileage, reminderInterval, reminderNotes, savingReminder ``` **Handler**: `handleSaveReminder()` — validates non-zero mileage + interval, creates record in `reminders` collection, shows success/error toast. **Imports used**: `BellRing` from lucide-react (added to existing icon import line). ### 2. Dashboard.tsx — Reminders Widget **Location**: Between the header row and the loading state section. Only renders when `reminders.length > 0`. **Widget**: White card with ring shadow, contains: - Header: `BellRing` icon + "Maintenance Reminders" title + count badge ("N active" in blue pill) - Each reminder row shows: - Customer name + vehicle info - Optional notes (italic) - Due mileage (right-aligned) - "Active"/"Paused" badge (amber if `dueMileage > 0`, green otherwise) **Data fetching**: `fetchReminders()` callback queries `reminders` collection filtered by `shopUserId` and `active = true`, sorted `-created`. Called via `useEffect` on mount. **Interface**: `ReminderRecord` interface defined locally in Dashboard.tsx. **Imports used**: `BellRing` from lucide-react (added to existing icon import). ## Verification After changes to either file, run: ```bash npm run build # tsc + vite build npm run lint # oxlint npm run test # vitest ``` ## Pitfalls - **Unused import errors**: TypeScript `tsc -b` is strict about unused variables/imports. If you import `useToast` but don't call `showToast`, the build fails. Remove the unused import and destructuring. - **Collection must exist in PocketBase**: The `reminders` collection needs to be created via a PB migration or admin UI before the code will work at runtime. - **Pre-fill mileage**: The "Set Reminder" button click handler pre-fills from `ro.mileage` — make sure the button's `onClick` includes `setReminderMileage(ro.mileage || '')` so the form opens with the current mileage.