Implements GitHub issue #9 — recurring appointment scheduling with
configurable frequency and cascade edit/cancel options.
Changes:
- DB: add `recurring_series` table (frequency_weeks) and series_id /
series_index columns on appointments (migration 0003)
- API POST /appointments: accepts optional `recurrence` object
(frequencyWeeks + count) that creates a full series in one transaction
- API PATCH /appointments/🆔 new `cascadeMode` field
(this_only | this_and_future | all) applies time-delta shifts and
field updates across the series
- API DELETE /appointments/🆔 new `?cascade=` query param cancels
this_only / this_and_future / all series members
- Frontend: booking form gains a "Recurring appointment" checkbox with
frequency and count pickers; calendar chips show a ↻ recurring label;
detail modal shows "Recurring series" badge and a cascade-delete radio
picker for series appointments
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add invoice_status and payment_method enums to schema
- Add invoices table: appointmentId, clientId, subtotal/tax/tip/total cents,
status (draft/pending/paid/void), paymentMethod, paidAt, notes
- Add invoice_line_items table: invoiceId, description, qty, unitPrice, total
- Migration 0002_invoices.sql with FK constraints and journal entry
- POST /api/invoices — create invoice with line items
- POST /api/invoices/from-appointment/:id — one-click invoice from appointment,
pre-populated with service name and price; returns 409 if already invoiced
- GET /api/invoices — list with optional ?status/clientId/appointmentId filters
- GET /api/invoices/:id — invoice with line items
- PATCH /api/invoices/:id — update status, payment method, tip, notes; auto-sets
paidAt when marking paid; blocks edits on voided invoices
- Add Invoice/InvoiceLineItem types to @groombook/types
- InvoicesPage: list view with status filter, create from appointment modal,
detail modal with tip input, payment method selector, Mark as Paid/Void actions
- Add Invoices nav link in App.tsx
Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
- Add health_alerts column to pets table (migration 0001)
- Update DB schema, shared types, and API Zod validation
- Show health alerts prominently (red badge) in pet cards
- Add health alerts field to pet form with allergy/condition placeholder
- Add delete button per pet with confirmation dialog
- Add delete client button with cascade warning
Closesgroombook/groombook#2
Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
- Fix Dockerfiles to copy pnpm-lock.yaml (frozen-lockfile compliance)
- Add migrate target to API Dockerfile using builder stage
- Add migrate service to docker-compose that runs before API starts
- Add AUTH_DISABLED env var bypass to auth middleware for dev/Docker
- Proxy /api/ from nginx to API container (no CORS needed)
- Include initial Drizzle migration (0000_colossal_colossus.sql)
- Add .env.example with all configurable variables
- Update README with Docker self-hosting instructions
Closes#7
Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>