Files
hermes-config/skills/self-hosting/shop-pro-quote/references/reminders.md
T
2026-07-12 10:17:17 -04:00

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.