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

3.5 KiB

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:

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.