Files
AgendaPro Dev d796538fd9 feat: rebrand AgendaPro -> AgendaMax + calendar fixes + current-week demo seed
- Rebrand all user-facing text to AgendaMax
- Fix sidebar scrolling: card container no longer overflows html (flex h-full min-h-0)
- Fix calendar toolbar hover: active buttons keep readable contrast
- Sticky calendar toolbar (month/week/day always visible on scroll)
- Seed guarantees 2-4 appointments per day for current week (Mon-Sat)
2026-07-27 10:11:16 -06:00

5.8 KiB
Raw Permalink Blame History

Task 12 — Wizard 3/4 pasos + Confirmation con reasons + anclar main ancho

File changed

  • src/pages/public/BookingPage.tsx (only file touched)

Steps applied (19)

  1. Replaced static STEPS with FULL_STEPS const + stepsFor(autoAssign) helper that drops the "Especialista" step when auto-assign is on (returns {n, label, original} items).
  2. Added maxBookableDate() helper next to todayStr (today + 3 months, ISO YYYY-MM-DD).
  3. In BookingPage, computed autoAssign, steps (useMemo on autoAssign), stepCount, and currentOriginal (find by n === step, read .original) before slotsQuery so the closure can see it.
  4. slotsQuery.enabled now uses currentOriginal === 3 (was step >= 3).
  5. goNext / goBack / pickSlot use stepCount (no hard-coded 4).
  6. canContinue, primaryLabel, onPrimary switch on currentOriginal. handleBook sends employee_id: autoAssign ? undefined : selectedSlot.employee_id.
  7. Rewrote the main return (...) to render sections by currentOriginal; main widens to max-w-5xl only when currentOriginal === 3, otherwise max-w-2xl; DateTimePicker gets max={maxBookableDate()}; the Especialista row in Datos is hidden when autoAssign.
  8. Updated TopBar + ActionBar signatures to accept stepCount + steps; both widened from max-w-3xl/max-w-2xlmax-w-5xl. TopBar now reads "Paso X de {stepCount}" and iterates the dynamic steps array (including the mobile X / {stepCount} chip).
  9. Confirmation renders appointment.reasons as brand badges (with Sparkles icon) guarded by reasons && reasons.length > 0, placed under the Especialista row.

Also updated the two secondary TopBar call sites (disabled-booking screen and Confirmation) to pass stepCount={4} steps={[]}step={0} hides the indicator block, so an empty array is safe there.

Verification

typecheck

> tsc -b --noEmit
(no output — 0 errors)

First pass surfaced one error: ActionBar's stepCount param was unused (TS6133). Fixed by surfacing it in the empty-state label: Paso {step} de {stepCount} · Continúa para reservar.

build

> tsc -b && vite build
✓ 2461 modules transformed.
✓ built in 5.16s

lint

> eslint . --ext ts,tsx
ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

Pre-existing env issue (ESLint 9 with no flat config in the repo). Not introduced by this task; no react-hooks/exhaustive-deps warnings would be reachable until the config is repaired. The useMemo(() => stepsFor(autoAssign), [autoAssign]) dep array is correct.

Runtime smoke (server already running on :5173)

  • Slug: lumiere-estetica-spa. Default auto_assign_specialist=0.
  • OFF flow: GET /api/public/<slug>auto_assign_specialist=0. Slots for service 6 tomorrow returned 10 slots. POST /book without employee_id → 201, emp_id=2 Mateo Herrera, reasons=["Disponible"], client_created=true. (Server still auto-ranked because the client didn't pick one — that's the unchanged 4-step path.)
  • ON flow: PATCH /api/settings {auto_assign_specialist:1}. GET public → auto_assign_specialist=1 (correctly exposed). POST /book without employee_id at a free slot → 201, emp_id=2 Mateo Herrera, reasons=["Disponible"].
  • Double-booking guard: re-POSTing the first booked slot → 409 Esa hora acaba de ocuparse, elige otra.
  • Restored auto_assign_specialist=0 afterwards.

Visual confirmation of step count / layout width was done by code inspection (no headless browser available in this subagent): stepsFor(false) yields 4 items; stepsFor(true) yields 3 items (Especialista filtered). The TopBar "Paso X de {stepCount}" and the mobile "X / {stepCount}" both read from the dynamic count, so 4 vs 3 follows automatically. main's width is selected by currentOriginal === 3 ? "max-w-5xl" : "max-w-2xl", which is true only on the Horario section regardless of the 3- or 4-step mapping.

Deviations

  • ActionBar's previously-unused stepCount prop (the spec required ActionBar to accept it, but the plan's literal snippet didn't read it) is now surfaced in the empty-state copy. This both satisfies TS6133 and improves UX consistency.
  • No commit performed (per task constraints).

Self-review

  • OFF = 4 steps? Yes — stepsFor(false) maps all 4 FULL_STEPS to {1:Servicio, 2:Especialista, 3:Horario, 4:Datos} with original matching n. currentOriginal drives section rendering, so the 4-step Servicio→Especialista→Horario→Datos flow is preserved exactly. The "Cualquiera" path still hits the server ranking (server-side, unchanged here).
  • ON = 3 steps? Yes — stepsFor(true) filters out Especialista, renumbering to {1:Servicio (orig 1), 2:Horario (orig 3), 3:Datos (orig 4)}. The currentOriginal === 2 branch (Especialista) never matches because no step maps to original 2.
  • currentOriginal before slotsQuery? Yes — declared at line 83, slotsQuery at line 90 references it in enabled at line 93.
  • handleBook sends undefined employee_id when autoAssign? Yes — line 198 employee_id: autoAssign ? undefined : selectedSlot.employee_id. BookPayload.employee_id is optional, so this typechecks.
  • Confirmation shows reasons badges? Yes — guarded by appointment.reasons && appointment.reasons.length > 0, renders <span> chips with Sparkles icon under the Especialista row.
  • main widened only on Horario? Yes — cn("…", currentOriginal === 3 ? "max-w-5xl" : "max-w-2xl"). Horario is always original 3 in both flows.
  • Disabled-booking screen, loading/error states, reset() preserved? Yes — only the TopBar call in the disabled screen was updated to pass the new required props; the rest of that branch is untouched. Loading/error branches and reset() are unchanged.
  • No git commit. Confirmed — only file edits + npm runs.