diff --git a/CLAUDE.md b/CLAUDE.md index 550b00c..69e8e78 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -109,6 +109,39 @@ All public pages wrap content in `` from `components/layout - `data/state.json` — province/state data, joined to city via `province_id` - `data/specialties.json` — medical specialties; items with `parent` field are sub-specialties shown in FrequentSearches +### Booking Modes (slot vs service) + +The backend decides how a doctor is booked, **per location**: a doctor can be +slot-based in their own office and service-based in a clinic. The mode arrives as +`booking_mode` on each entry of `getBookingLocations`, so `components/appointment/index.js` +reads it off the *selected* location, never off the doctor. + +| Mode | Flow | Slot source | +|---|---|---| +| `slot` | date → time | `getAppointmentSlots` → `adaptSlots` | +| `service` | **service → date → time** | `getServiceSlots` → `adaptServiceSlots` | + +- `lib/appointmentSlots.js` is the split point. Both adapters return the same shape — + an array of sessions `{ start_time, end_time, label, slots }` — which + `app/component/date/dateTime/index.js` turns into tabs (`sessions.length > 1`). +- **Duration is server data.** `total_duration_minutes` comes from + `appointment-service-slots`; never sum `duration_minutes` in the front. The backend + formula is going to change to solo/additional minutes, and any parallel client + calculation will silently start showing a wrong number. `components/appointment/service/index.js` + keeps a client sum only as a labelled fallback with a `console.warn`. +- The service step runs *before* the date step, yet `total_duration_minutes` does not + depend on the date — the backend computes it before touching that day's shifts — so + the picker may ask for it using today's date even if today is closed. +- Shift boundaries are **not** derived in the front for service mode: a flat + `start_times` list cannot distinguish a break between shifts from a gap left by a + booked appointment. One session with the real range is returned instead. See the note + in `clinicpro/docs/api/appointment.md`. +- User panel: `service_items` and `service_total_minutes` come from + `GET /api/v1/appointments/user`. Slot-mode appointments have neither, so every read + is guarded — an unguarded `.map` crashes the card for all slot-mode appointments. + +Backend reference: `clinicpro/docs/architecture/booking-modes.md`. + ### Doctor & Clinic Slugs Both use `uuid` as the URL slug: `/doctor/${doctor.uuid}` and `/clinic/${clinic.uuid}`.