80 lines
3.5 KiB
Markdown
80 lines
3.5 KiB
Markdown
# 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.
|