enhance booking window logic to support overnight desk configurations and update related UI components

This commit is contained in:
Marshal
2026-07-05 21:29:09 +00:00
parent 3485a7d63d
commit caa8397563
5 changed files with 83 additions and 36 deletions

View File

@@ -165,9 +165,9 @@ export function isRoundTheClock(hours: OfficeHours): boolean {
* Returns `null` when the next open would fall on/after `departure` — the train
* leaves before another cycle could run, so the window is done.
*
* Precondition: `windowCloseHour >= windowOpenHour` — the desk runs within a
* single EAT day and never wraps past midnight (enforced when global rules are
* saved). openHour === closeHour is the 24-hour desk, handled first.
* The desk may run within one EAT day (`closeHour > openHour`), round the clock
* (`openHour === closeHour`), or overnight across midnight (`openHour >
* closeHour`, e.g. 08:00 → 07:00). `officeHoursOpen` handles all three.
*/
/**
* The EAT instant a booking cycle would open if it became ready at `readyAt`,
@@ -189,6 +189,19 @@ export function officeHoursOpen(readyAt: Date, hours: OfficeHours): Date {
const readyMinutes = hour * 60 + minute;
const openMinutes = hours.windowOpenHour * 60;
const closeMinutes = hours.windowCloseHour * 60;
if (hours.windowOpenHour > hours.windowCloseHour) {
// Overnight desk, e.g. open 08:00 → close 07:00 next morning. The desk is
// open across midnight: [openHour, 24:00) on this EAT day and [00:00,
// closeHour) on the next. Only the daytime gap [closeHour, openHour) is shut.
if (readyMinutes >= openMinutes || readyMinutes < closeMinutes) {
// Inside the overnight window (either side of midnight) → open when ready.
return readyAt;
}
// In the daytime gap → the desk opens again at openHour this EAT morning.
return eatDayToUtc(eatDay(readyAt), hours.windowOpenHour);
}
if (readyMinutes < openMinutes) {
// Ready before the desk opens on its own EAT calendar day → open this morning.
return eatDayToUtc(eatDay(readyAt), hours.windowOpenHour);