Return to a bookable calendar after a booking is confirmed #158

Merged
thatguygriff merged 1 commits from fix/143-return-to-bookable into main 2026-07-30 02:02:51 +00:00
Owner

Closes #143.

showConfirmation() hid the slot list and put the confirmation in its place. That is a dead end: a student who wanted a second lesson had nothing to click and no way back short of reloading the page. group-classes.js did exactly the same thing to enrolments, so both are fixed here.

What it does now

The confirmation is a dismissible notice above the calendar. The calendar is reloaded first — so the slot just taken is already gone and the upcoming-lessons panel is current — and the notice is shown over it. "It worked" and "book another" are the same screen.

That ordering is why loadSlots() (and loadClasses()) now return their promise: the reload clears any standing notice, so the new one has to be shown after it resolves, not before.

The notice clears when dismissed, when another slot's booking form is opened, and on any reload of the calendar.

Two details worth noting

Built from DOM nodes, not innerHTML. The message can carry a studio's e-transfer address, so it goes in via textContent on a child node rather than being interpolated into markup.

Toggled with hidden, not an inline display. I had it on style.display = 'block' first and a browser screenshot caught the bug: an inline style outranks the stylesheet's display: flex, so the Dismiss button stacked under the text instead of sitting inline. hidden then needs the same !important guard the upcoming-lessons panel got in #151[hidden] is only a UA rule and the div { display: block } theme reset beats it.

Also removed the slotList.style.display = 'block' / list.style.display = 'block' lines. They only ever existed to undo the hiding this PR deletes; leaving them would imply something still hides those elements.

Verification

Rebased onto main after #156 (one CSS conflict, both sides pure additions at the same insertion point, kept both). composer test 814, composer lint, composer cs all pass.

None of those reach this code, though, which is why the real check was a headless browser driving booking.js against a stubbed REST API — re-run after the rebase:

notice shown with the message, calendar still visible ok
booked slot gone from the calendar, the other still bookable ok
upcoming-lessons panel updated ok
notice renders before the calendar in the DOM ok
dismiss hides the notice, calendar stays ok
second booking with no reload ok
opening the next booking form clears the standing notice ok
notice stays hidden under div { display: block } ok

16 checks in total. group-classes.js is a line-for-line mirror of the same change and is syntax-checked, but I did not build a second harness for it — worth a manual click-through of an enrolment before merging if you want belt and braces.

Closes #143. `showConfirmation()` hid the slot list and put the confirmation in its place. That is a dead end: a student who wanted a second lesson had nothing to click and no way back short of reloading the page. `group-classes.js` did exactly the same thing to enrolments, so both are fixed here. ## What it does now The confirmation is a **dismissible notice above the calendar**. The calendar is reloaded *first* — so the slot just taken is already gone and the upcoming-lessons panel is current — and the notice is shown over it. "It worked" and "book another" are the same screen. That ordering is why `loadSlots()` (and `loadClasses()`) now return their promise: the reload clears any standing notice, so the new one has to be shown after it resolves, not before. The notice clears when dismissed, when another slot's booking form is opened, and on any reload of the calendar. ## Two details worth noting **Built from DOM nodes, not innerHTML.** The message can carry a studio's e-transfer address, so it goes in via `textContent` on a child node rather than being interpolated into markup. **Toggled with `hidden`, not an inline display.** I had it on `style.display = 'block'` first and a browser screenshot caught the bug: an inline style outranks the stylesheet's `display: flex`, so the Dismiss button stacked under the text instead of sitting inline. `hidden` then needs the same `!important` guard the upcoming-lessons panel got in #151 — `[hidden]` is only a UA rule and the `div { display: block }` theme reset beats it. Also removed the `slotList.style.display = 'block'` / `list.style.display = 'block'` lines. They only ever existed to undo the hiding this PR deletes; leaving them would imply something still hides those elements. ## Verification Rebased onto `main` after #156 (one CSS conflict, both sides pure additions at the same insertion point, kept both). `composer test` 814, `composer lint`, `composer cs` all pass. None of those reach this code, though, which is why the real check was a headless browser driving `booking.js` against a stubbed REST API — re-run after the rebase: | | | |---|---| | notice shown with the message, calendar still visible | ok | | booked slot gone from the calendar, the other still bookable | ok | | upcoming-lessons panel updated | ok | | notice renders before the calendar in the DOM | ok | | dismiss hides the notice, calendar stays | ok | | **second booking with no reload** | ok | | opening the next booking form clears the standing notice | ok | | notice stays hidden under `div { display: block }` | ok | 16 checks in total. `group-classes.js` is a line-for-line mirror of the same change and is syntax-checked, but I did not build a second harness for it — worth a manual click-through of an enrolment before merging if you want belt and braces.
thatguygriff added 1 commit 2026-07-30 01:58:19 +00:00
Return to a bookable calendar after a booking is confirmed
CI / Tests (PHP 8.3) (pull_request) Successful in 2m44s
CI / Build Plugin Zip (pull_request) Skipped
CI / Coding Standards (pull_request) Successful in 3m0s
CI / Tests (PHP 8.1) (pull_request) Successful in 42s
CI / Tests (PHP 8.2) (pull_request) Successful in 44s
CI / No Debug Code (pull_request) Successful in 2s
CI / PHPStan (pull_request) Successful in 2m46s
699e479805
showConfirmation() hid the slot list and put the confirmation in its place,
which is a dead end: a student wanting a second lesson had nothing to click
and no way back short of reloading the page. Enrolling in a group class did
the same thing.

The confirmation is now a dismissible notice above the calendar. The
calendar is reloaded first — so the slot just taken is already gone and the
upcoming-lessons panel is current — and the notice is shown over it, which
is why loadSlots() had to start returning its promise. "It worked" and "book
another" are the same screen.

The notice clears when dismissed, when another slot's form is opened, and on
any reload of the calendar. group-classes.js gets the identical treatment.

It is built from DOM nodes rather than innerHTML because the message can
carry a studio's e-transfer address, and it is toggled with the `hidden`
attribute rather than an inline display — an inline style would outrank the
stylesheet's display:flex and stack the notice's parts. `hidden` needs the
!important guard for the same reason the upcoming-lessons panel does: the
div{display:block} theme reset outranks the UA sheet.

The slotList/list `display = 'block'` lines went with it. Nothing hides
those any more, so restoring them each load only implied otherwise.

Verified in a headless browser against a stubbed REST API: booking twice in
a row without a reload, the booked slot leaving the calendar, the upcoming
panel updating, dismissal, the notice clearing when the next form opens, and
the notice staying hidden under div{display:block}.

Closes #143

Co-Authored-By: Claude Opus 5 <[email protected]>
thatguygriff merged commit 28046e0fd1 into main 2026-07-30 02:02:51 +00:00
thatguygriff deleted branch fix/143-return-to-bookable 2026-07-30 02:02:51 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Unsupervised/unsupervised-scheduler#158