refactor(booking): cache guest page formatters and reuse the slots query key - #3046
Merged
Conversation
Three cleanups left by the booking work packages, all behavior-preserving. public-booking.format.ts kept one cached formatter for date keys, with a comment noting that constructing Intl is the expensive part, while six other formatters rebuilt theirs on every call. The guest page calls them per open slot and per day cell, so a month render constructed dozens. Generalize the existing cache into perTimeZoneFormatter and route all seven through it, which also drops six near-identical option literals. PublicBookingMonthGrid built the aria-label for every cell before the unavailable-day early return discarded it, so most of the month's labels were formatted and thrown away. Build it where it is used. The reservation mutation invalidated slots with a hand-written key array instead of publicBookingQueryKeys, so a change to the key factory would have silently stopped matching. Add a slotsAll prefix, build slots from it, and invalidate through it. The page and reservation queries also carried the same not-found retry predicate twice; name it once. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FXNUAfQd2mEg5u1Q3oFzn9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three behavior-preserving cleanups left by the booking work packages (#3022-#3045). No user-visible change; no new exports beyond one query-key prefix.
1.
public-booking.format.tscached one formatter and rebuilt six. The file already kept a per-timezone cache for the date-key formatter, with a comment stating that constructingIntl.DateTimeFormatis the expensive part. The other six formatters ignored that and constructed a fresh one on every call, and they are the hot ones:formatBookingSlotTimeruns once per open slot,formatBookingMonthDayLabelonce per day cell, andlistBookingWeekdayHeadingsbuilds 14 formatters per call. Generalized the existing cache into aperTimeZoneFormatterhelper and routed all seven through it, which also removes six near-identical option literals. Cache keys are IANA zones already validated byvalidatePublicBookingSearch, so it stays bounded.2.
PublicBookingMonthGridformatted labels it threw away.aria-labelwas computed for every cell before the!day.availableearly return discarded it, so most of a month's ~35-42 labels were built and dropped. Moved it to where it is used.3.
public-booking.query.tshand-wrote a query key. The reservation mutation invalidated slots with a literal["public-booking", "slots", slug]instead ofpublicBookingQueryKeys-- the only such call site in the web package, and one that would silently stop matching if the key factory changed shape. Added aslotsAllprefix, builtslotsfrom it, and invalidated through it. The page and reservation queries also carried the same not-found retry predicate verbatim twice; named itretryUnlessNotFoundonce.Simplicity
Net reduction. The formatter change removes six duplicated option literals and the bespoke
dateKeyFormattersmap in favor of one 15-line helper; the query change removes a duplicated 6-line predicate and a magic key array. Nothing new is abstracted that did not already exist in the file:perTimeZoneFormatteris the existingdateKeyFormattercache with the option set lifted out.Automated validation
bun run verifyselected thewebpackage and passedtest:web,type-check,lint, andknip. Because the change touches rendered guest-page output, the Playwright suitesverifyskipped for a missing browser were run explicitly after installing Chromium: all 30e2e/bookingspecs pass, and the booking a11y specs pass.bun test:a11yalso surfaces 6 failures inapp-a11y.spec.tsanddatepicker-a11y.spec.ts(week view, event forms, sidebar datepicker). These are pre-existing and unrelated: re-running those two spec files on a cleanmain(00f3e00) with this branch stashed reproduces the same 6 failures. They are calendar-app color-contrast checks that touch no booking code.Independent review
No
/reviewhandoff for this change. Self-review notes on the risky edge:formatGuestTimeZoneLabeldepends onIntlthrowing for an invalid timezone, and the construction still happens inside itstry(nothing is cached on throw), so the fallback-to-raw-zone behavior is preserved.Intloption property order is not significant, so spreading...optionsbeforetimeZoneis equivalent to the previous literals.Test plan
Generated by Claude Code