fix(chatelet): let a min-stay range extend forward (reka span guard) #158

Merged
padreug merged 1 commit from fix/chatelet-min-nights-range-spanning into dev 2026-09-21 12:32:09 +00:00
Showing only changes of commit 6f56e999d6 - Show all commits

fix(chatelet): let a min-stay range extend forward (reka span guard)

The stay picker enforced min_nights by disabling the days between check-in
and check-in + min_nights. reka-ui refuses to *complete* a range that spans
a disabled day, so on a 2-night-minimum room every forward check-out was
unreachable: the guest picked a check-in and could then only click an
earlier day, which reka swapped into the range (the 'calendar jumps
backwards' report). One-night-minimum rooms were unaffected, which is why
the Orangery Suite worked and the Tour Room didn't.

Stop disabling the in-window days. Enforce the minimum in onModel instead:
a too-short range keeps the check-in and clears the check-out, resetting
reka's controlled model directly (checkOut is already '' so the props watch
won't fire, and reka's highlighted end would otherwise linger). Occupied
nights past the next booking still cap the range, and #157's check-in
validity guard is unchanged.

Verified headlessly on min-1 and min-2 rooms, empty and with a blocked
night: forward selection completes, exact-minimum completes, below-minimum
is rejected, the boundary check-out is reachable, and the quote is correct.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Padreug 2026-09-21 13:28:35 +02:00

View file

@ -122,7 +122,13 @@ function isDateDisabled(d: DateValue): boolean {
} }
if (y === start) return false if (y === start) return false
if (y > start) { if (y > start) {
if (y < addDays(start, props.minNights)) return true // Do NOT disable the days inside the minimum-stay window here: reka-ui
// refuses to complete a range that *spans* a disabled day, so disabling
// start+1 (for a 2-night minimum, etc.) makes every forward check-out
// unreachable — the guest can only click an earlier day, which reka
// swaps in. The minimum stay is enforced in onModel instead (a too-short
// range keeps the check-in and clears the check-out). Occupied nights
// past the next booking still cap the range.
if (boundary.value && y > boundary.value) return true if (boundary.value && y > boundary.value) return true
return false return false
} }
@ -143,8 +149,12 @@ function onModel(v: RekaDateRange | null) {
const ok = const ok =
stayIsFree(props.nightSet, ci, co) && nightsBetween(ci, co) >= props.minNights stayIsFree(props.nightSet, ci, co) && nightsBetween(ci, co) >= props.minNights
if (!ok) { if (!ok) {
// Defensive: reka let a bad range through — keep the check-in, redo the end. // A range too short for the minimum stay (or spanning an occupied
// night). Keep the check-in and redo the end. checkOut is already ''
// here, so the props watch won't fire — reset reka's controlled model
// directly, otherwise its highlighted end lingers on the rejected day.
pendingStart.value = ci pendingStart.value = ci
model.value = { start: fromYmd(ci), end: undefined }
emit('update:checkIn', ci) emit('update:checkIn', ci)
emit('update:checkOut', '') emit('update:checkOut', '')
return return