Skip to content

[booking][P1 HIGH] Pricing/duration toggle shows EMPTY or wrong-length windows for authored availability blocks (breakDownSlotsPreservingStatus sliding-window has no fallback) #1415

Description

@teetangh

User-visible symptom

A consultant authors a 2-hour availability block (e.g. 7:00 PM – 9:00 PM). On the public / explore booking surface:

  • The availability calendar shows the 7 PM – 9 PM block correctly (rendered as one merged bar).
  • The pricing / booking-length toggle shows one-hour windows (7:00–8:00, 7:30–8:30, 8:00–9:00) instead of the combined 7–9 session.
  • Selecting the "2-hour slot" pricing option renders "No available slots for the selected date" (empty), even though the 7–9 block exists and is shown on the availability calendar.

This is the same class of symptom the user reported last session and is confirmed reproducible from the code path.

Root cause (verified)

app/explore/experts/[consultantId]/components/ConsultationPricingToggle.tsx:92-129 computes availableSlots via breakDownSlotsPreservingStatus over the server's 30-minute atoms:

selectedDuration = activePlanOption?.durationInHours ?? 1;   // default 1h
availableSlots = breakDownSlotsPreservingStatus(slotsWithAllocation, selectedDuration, timezone);

utils/timeSlotsProcessing.ts:902-988 (breakDownSlotsPreservingStatus):

  1. Merges the API 30-min atoms into contiguous blocks via mergeConsecutiveSlots — exact adjacency only (:655).
  2. Segments each merged block by sliding a fixed-millisecond window of length durationInHours, but only emitting a window while windowStart + durationInMillis <= slotEnd (:931).

Two concrete failure modes fall out:

  • Empty-on-duration (2h shows nothing): the loop only emits exact durationInHours windows and has no tolerance/fallback. For durationInHours = 2 (durationInMillis = 7,200,000), a merged block must be at least 2 wall-clock-hours long in the fixed-ms sense. If the merged block is even slightly short of that (a non-30-min-boundary end, a blocked atom in the middle that prevents a full merge, or an authored window that is "2h" in some displayed sense but not in absolute ms), every windowStart + 2h <= slotEnd check fails and the function returns [] → "No available slots".
  • Wrong-length fragments (default shows 1h windows for a 2h block): with selectedDuration = 1 (default), the same function slices a 7–9 block into 7–8, 7:30–8:30, 8–9. The authored combined 2-hour session is never offered as one booking unless the user happens to toggle to exactly 2h AND the block is exactly 2h in absolute ms.

Why it matters

  • Users cannot book the session the consultant actually offers (the combined 2-hour block), or are told there are no slots at all.
  • The public availability calendar and the booking toggle disagree on the same availability data — eroding trust and causing dropped bookings at launch.
  • The durationInHours concept conflates "a pricing tier's length" with "the segment the generator must emit", with no fallback to a shorter-yet-valid window or to the authored block itself.

Suggested fix direction

  • Give breakDownSlotsPreservingStatus (and breakDownSlotsByDuration) a fallback: if no exact durationInHours window fits a merged block, emit the largest fully-contained window(s) rather than empty, or fall back to the authored block that the availability calendar shows.
  • Decide the canonical behavior: either (a) the toggle re-segments at the selected duration with a floor that always returns at least the authored contiguous window, or (b) the calendar should not over-merge what the booking layer can't satisfy — the two layers must agree on "bookable".
  • Make the merge before segmentation symmetric with the display merge (see the merge-tolerance issue), so a block shown on the calendar is always segmentable into a bookable window of the selected length.
  • Add a regression test: authored block 7–9, toggle 1h → emits 7–8/8–9; toggle 2h → emits 7–9 (never empty); toggle 2h with a 1-minute-short block → emits a valid window, not empty.

Related

Terms

pricing toggle · duration · slot window · segmentation · empty slots · booking length · sliding window

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bookingBooking, scheduling, slots, reschedule, cancellationbugSomething isn't workinglaunch: pre-mvpGates launch — money, data, or a failure we would not detect

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions