feat: multi-pet client group booking (closes #10) (#31)

* feat: multi-pet client group booking (closes groombook/groombook#10) (GRO-27)

- Add appointment_groups table: links multiple appointments from one client visit
- Add group_id FK on appointments (nullable, backward-compatible)
- Add GET/POST/PATCH/DELETE /api/appointment-groups endpoints
  - POST creates group record + one appointment per pet atomically (with conflict checks)
  - DELETE soft-cancels all appointments in the group
- Add GroupBooking.tsx page at /group-bookings with:
  - Dynamic pet-slot form (min 2 pets, each with their own groomer/service/end time)
  - Auto-calculates end time from service duration
  - Group card list showing all pets, groomers, and statuses side-by-side
  - Client filter and cancel-all action
- Wire into nav and routing in App.tsx
- Export AppointmentGroup type; add groupId field to Appointment type

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix: remove eslint-disable for uninstalled react-hooks plugin; remove unused clientMap (GRO-27)

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: Groom Book CTO <cto@groombook.app>
Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit was merged in pull request #31.
This commit is contained in:
groombook-paperclip[bot]
2026-03-17 21:36:03 +00:00
committed by GitHub
parent e63ce83400
commit f47717dfd8
7 changed files with 901 additions and 0 deletions
+9
View File
@@ -61,6 +61,14 @@ export interface RecurringSeries {
createdAt: string;
}
export interface AppointmentGroup {
id: string;
clientId: string;
notes: string | null;
createdAt: string;
updatedAt: string;
}
export interface Appointment {
id: string;
clientId: string;
@@ -74,6 +82,7 @@ export interface Appointment {
priceCents: number | null;
seriesId: string | null;
seriesIndex: number | null;
groupId: string | null;
createdAt: string;
updatedAt: string;
}