fix(portal): send preferredTime as HH:MM:SS and format booking slot labels (GRO-2211) #51

Merged
Flea Flicker merged 1 commits from flea/gro-2213-portal-preferredtime into dev 2026-06-08 16:41:14 +00:00
Member

FIX (web, root cause): portal booking 500 — send preferredTime as HH:MM:SS

Parent defect: GRO-2211. Root-cause fix for GRO-2213.

Why it broke

GET /api/book/availability returns canonical UTC ISO slot strings (e.g. 2026-06-09T10:00:00.000Z = the 10:00 UTC business slot). The Book New wizard held these raw, rendered them verbatim on the slot buttons / Review "Date & Time" / success screen, and POSTed preferredTime: selectedTime raw. The api inserts that into the Postgres time column → invalid input syntax for type time: "2026-06-09T10:00:00.000Z" → unhandled 500.

Changes (src/portal/sections/Appointments.tsx)

  • Add shared UTC helpers formatSlotLabel(slot) and slotToTime(slot) so display label and submit payload derive from the same canonical UTC ISO slot and never desync. Both format/extract in UTC (slots are UTC business hours — a browser-local conversion would mislabel and desync from the stored column). Guards tolerate already-formatted labels and HH:MM:SS values.
  • BookNew slot buttons, Review line, and confirmation now show formatSlotLabel(...) → e.g. 10:00 AM, never a raw ISO.
  • Submit sends preferredTime: slotToTime(selectedTime)HH:MM:SS.
  • Export BookingFlow for testing.

Tests

  • Helper unit tests for formatSlotLabel / slotToTime.
  • Book New funnel integration test: asserts the rendered slot label is 10:00 AM (never raw ISO) and the /api/portal/waitlist POST body preferredTime matches /^\d{2}:\d{2}:\d{2}$/ (10:00:00).
  • Full suite green: 155 passed; tsc --noEmit clean; lint 0 errors.

Scope note

RescheduleFlow has a sibling raw-ISO display/submit issue against startTime (different endpoint/contract). Left untouched to keep this fix tightly scoped to the preferredTime 500; can be filed as a follow-up.

AC

  • Slot buttons + Review line show formatted time, never raw ISO
  • preferredTime is HH:MM:SS
  • Unit/integration test added and green
  • Lint + typecheck + test green
## FIX (web, root cause): portal booking 500 — send `preferredTime` as `HH:MM:SS` Parent defect: [GRO-2211](/GRO/issues/GRO-2211). Root-cause fix for [GRO-2213](/GRO/issues/GRO-2213). ### Why it broke `GET /api/book/availability` returns canonical **UTC ISO** slot strings (e.g. `2026-06-09T10:00:00.000Z` = the 10:00 UTC business slot). The Book New wizard held these raw, rendered them verbatim on the slot buttons / Review "Date & Time" / success screen, and POSTed `preferredTime: selectedTime` raw. The api inserts that into the Postgres `time` column → `invalid input syntax for type time: "2026-06-09T10:00:00.000Z"` → unhandled **500**. ### Changes (`src/portal/sections/Appointments.tsx`) - Add shared UTC helpers `formatSlotLabel(slot)` and `slotToTime(slot)` so display label and submit payload derive from the same canonical UTC ISO slot and never desync. Both format/extract in **UTC** (slots are UTC business hours — a browser-local conversion would mislabel and desync from the stored column). Guards tolerate already-formatted labels and `HH:MM:SS` values. - BookNew slot buttons, Review line, and confirmation now show `formatSlotLabel(...)` → e.g. `10:00 AM`, never a raw ISO. - Submit sends `preferredTime: slotToTime(selectedTime)` → `HH:MM:SS`. - Export `BookingFlow` for testing. ### Tests - Helper unit tests for `formatSlotLabel` / `slotToTime`. - Book New funnel integration test: asserts the rendered slot label is `10:00 AM` (never raw ISO) and the `/api/portal/waitlist` POST body `preferredTime` matches `/^\d{2}:\d{2}:\d{2}$/` (`10:00:00`). - Full suite green: **155 passed**; `tsc --noEmit` clean; lint 0 errors. ### Scope note `RescheduleFlow` has a sibling raw-ISO display/submit issue against `startTime` (different endpoint/contract). Left untouched to keep this fix tightly scoped to the `preferredTime` 500; can be filed as a follow-up. ### AC - [x] Slot buttons + Review line show formatted time, never raw ISO - [x] `preferredTime` is `HH:MM:SS` - [x] Unit/integration test added and green - [x] Lint + typecheck + test green
Flea Flicker added 1 commit 2026-06-08 16:39:45 +00:00
fix(portal): send preferredTime as HH:MM:SS and format booking slot labels (GRO-2211)
CI / Test (pull_request) Successful in 20s
CI / Lint & Typecheck (pull_request) Successful in 26s
CI / Build & Push Docker Image (pull_request) Successful in 46s
7edf132bfe
The Book New wizard held raw ISO slot strings (e.g.
"2026-06-09T10:00:00.000Z") from /api/book/availability and rendered them
verbatim on the slot buttons, the Review "Date & Time" line, and the success
screen, and POSTed them straight as preferredTime. The api inserts that into
the Postgres `time` column, so a full ISO datetime is `invalid input syntax
for type time` → unhandled 500, breaking portal booking (GRO-2211).

- Add shared UTC helpers formatSlotLabel(slot) and slotToTime(slot) so the
  display label and the submitted time derive from the same canonical UTC ISO
  slot and never desync. Both format/extract in UTC (slots are UTC business
  hours); guards tolerate already-formatted labels and HH:MM:SS values.
- BookNew: render formatSlotLabel(time) on slot buttons, the Review line, and
  the confirmation; submit preferredTime: slotToTime(selectedTime) → HH:MM:SS.
- Export BookingFlow for testing.
- Tests: helper unit tests + a Book New funnel integration test asserting the
  rendered slot label is "10:00 AM" (never raw ISO) and the waitlist POST body
  preferredTime matches /^\d{2}:\d{2}:\d{2}$/.

GRO-2213

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Flea Flicker merged commit 0d52ddd9f0 into dev 2026-06-08 16:41:14 +00:00
Sign in to join this conversation.