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
+3
View File
@@ -6,6 +6,7 @@ import { StaffPage } from "./pages/Staff.js";
import { InvoicesPage } from "./pages/Invoices.js";
import { BookPage } from "./pages/Book.js";
import { ReportsPage } from "./pages/Reports.js";
import { GroupBookingPage } from "./pages/GroupBooking.js";
const NAV_LINKS = [
{ to: "/", label: "Appointments" },
@@ -13,6 +14,7 @@ const NAV_LINKS = [
{ to: "/services", label: "Services" },
{ to: "/staff", label: "Staff" },
{ to: "/invoices", label: "Invoices" },
{ to: "/group-bookings", label: "Group Bookings" },
{ to: "/reports", label: "Reports" },
];
@@ -76,6 +78,7 @@ export function App() {
<Route path="/staff" element={<StaffPage />} />
<Route path="/invoices" element={<InvoicesPage />} />
<Route path="/book" element={<BookPage />} />
<Route path="/group-bookings" element={<GroupBookingPage />} />
<Route path="/reports" element={<ReportsPage />} />
</Routes>
</main>