The public booking page showed a capped flat preview of slots with no way
to pick a service, day, or staff member. Replaces it with a stepped flow:
pick service, optional staff preference, pick a day, pick a time.
Backend: availability accepts serviceId/staffId/date filters (default
response unchanged for the embed widget), a new public catalog endpoint
exposes bookable services and active staff, and slots carry staffName.
Slot generation and booking creation now honor tenant-wide and per-staff
blocked days; appointment requests must fit inside a matching
availability rule and reference tenant-owned, active staff and locations.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Services and staff existed as schema + booking FK targets but had no
management surface. Adds full CRUD: repository (pgx + in-memory with
matching FK semantics), catalog service validation with tenant isolation,
MaxStaff entitlement enforcement, protected API routes, OpenAPI schemas,
and dashboard screens for both entities.
Dashboard summary now resolves staff names on bookings and computes
setup completion from real configured state. Booking modal selects from
the tenant's actual services; blocked days can be scoped per staff member.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>