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

Merged
ghost merged 2 commits from feat/multi-pet-group-booking into main 2026-03-17 21:36:04 +00:00
ghost commented 2026-03-17 21:28:35 +00:00 (Migrated from github.com)

Summary

Implements multi-pet client group booking from issue #10. When a client brings multiple pets in the same visit (possibly with different groomers working simultaneously), staff can now create a group booking that links all pets in one atomic operation.

Schema (0005_appointment_groups.sql):

  • New appointment_groups table with client_id and optional notes
  • New group_id FK column on appointments (nullable — fully backward-compatible)

API (/api/appointment-groups):

  • POST / — creates group + one appointment per pet atomically inside a transaction; checks groomer conflicts for each pet independently
  • GET / — list groups with their appointments (filterable by clientId, date range)
  • GET /:id — single group with enriched appointment rows (pet/service/staff names)
  • PATCH /:id — update group notes
  • DELETE /:id — soft-cancel all appointments in the group

Frontend (/group-bookings):

  • Dynamic form: select client, date, start time; add 2+ pet slots each with pet, service, groomer (optional), and end time
  • End time auto-fills from service duration when a service is selected
  • Group cards display all pets side-by-side with status badges
  • Client filter dropdown and Cancel All button per group

Test plan

  • Navigate to /group-bookings — empty state shown
  • Create group booking: select client with 2+ pets, different groomers, submit → group appears in list
  • Verify DB: appointment_groups row created; appointments rows have matching group_id
  • Try booking a groomer who has a conflict → 409 error shown
  • Single-pet slots: form enforces minimum 2 pets
  • Cancel All → all appointments in group move to cancelled
  • Existing single appointments unaffected (group_id is NULL)
  • TypeScript: tsc --noEmit passes in api, web, and db packages

Closes #10

🤖 Generated with Claude Code

## Summary Implements multi-pet client group booking from issue #10. When a client brings multiple pets in the same visit (possibly with different groomers working simultaneously), staff can now create a **group booking** that links all pets in one atomic operation. **Schema** (`0005_appointment_groups.sql`): - New `appointment_groups` table with `client_id` and optional `notes` - New `group_id` FK column on `appointments` (nullable — fully backward-compatible) **API** (`/api/appointment-groups`): - `POST /` — creates group + one appointment per pet atomically inside a transaction; checks groomer conflicts for each pet independently - `GET /` — list groups with their appointments (filterable by `clientId`, date range) - `GET /:id` — single group with enriched appointment rows (pet/service/staff names) - `PATCH /:id` — update group notes - `DELETE /:id` — soft-cancel all appointments in the group **Frontend** (`/group-bookings`): - Dynamic form: select client, date, start time; add 2+ pet slots each with pet, service, groomer (optional), and end time - End time auto-fills from service duration when a service is selected - Group cards display all pets side-by-side with status badges - Client filter dropdown and Cancel All button per group ## Test plan - [ ] Navigate to `/group-bookings` — empty state shown - [ ] Create group booking: select client with 2+ pets, different groomers, submit → group appears in list - [ ] Verify DB: `appointment_groups` row created; `appointments` rows have matching `group_id` - [ ] Try booking a groomer who has a conflict → 409 error shown - [ ] Single-pet slots: form enforces minimum 2 pets - [ ] Cancel All → all appointments in group move to `cancelled` - [ ] Existing single appointments unaffected (`group_id` is NULL) - [ ] TypeScript: `tsc --noEmit` passes in api, web, and db packages Closes #10 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This repo is archived. You cannot comment on pull requests.