fix(timeslots): respect minimum notice period across timezones#102
Merged
Conversation
The minimum notice period for booking a pickup timeslot was not enforced correctly because slot start times were parsed in the server's local timezone. In production the server runs in UTC while slots are wall-clock times in the shop's timezone (NZ), so the notice-period comparison was off by the shop's UTC offset (~12-13h, DST-dependent). - Add timezone-safe slotInstant() helper (DST-aware via Intl) and a SHOP_TIMEZONE constant (defaults to Pacific/Auckland) in lib/scheduleGenerator.ts. - pickup-slots route: use slotInstant for the notice comparison and compute 'today' in the shop timezone. - select-timeslot route: enforce the notice period on booking (previously only active + capacity were checked), so it can't be bypassed via a direct/stale POST. - Sync new SHOP_TIMEZONE server-only env var across env.d.ts, container-worker.js, and .env.local.
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.
Problem
The minimum notice period for booking a pickup timeslot wasn't respected. Slot start times were parsed as timezone-naive datetimes (
new Date("YYYY-MM-DDT09:00:00")), which JS interprets in the server's local timezone. In production the server runs in UTC, but slots are wall-clock times in the shop's timezone (NZ), so the notice-period comparison was shifted by the shop's UTC offset (~12–13h, DST-dependent) — letting too-soon slots through.Fix
lib/scheduleGenerator.ts: add DST-awareslotInstant()helper (usesIntl.DateTimeFormatto resolve the correct UTC offset for the slot's date) and aSHOP_TIMEZONEconstant (defaults toPacific/Auckland).app/api/pickup-slots/route.ts: useslotInstantfor the notice comparison; compute "today" in the shop timezone so the date filter doesn't drop/add a day around UTC midnight.app/api/shop/[orderId]/select-timeslot/route.ts: enforce the notice period on booking (previously only active + capacity were checked), so it can't be bypassed via a direct/stale POST. Uses the same schedule-override → global-default → 24h resolution.SHOP_TIMEZONEadded toenv.d.ts,container-worker.js, and.env.localwith consistentPacific/Aucklanddefaults. No Docker placeholder needed (not client-inlined).Verification
slotInstantacross DST: NZDT +13 (summer) and NZST +12 (winter) resolve to the correct UTC instants, and the notice-window include/exclude logic is correct.biome checkclean;tsc --noEmitpasses.