From 98807e248588dd48658ba3fc6fd7e5cdfad46f6a Mon Sep 17 00:00:00 2001 From: Stephen Adamson Date: Fri, 17 Oct 2025 00:21:38 +0100 Subject: [PATCH] time picker closing fix --- frontend/src/routes/book/+page.svelte | 38 ++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/frontend/src/routes/book/+page.svelte b/frontend/src/routes/book/+page.svelte index 8b1a73c..7cc75e7 100644 --- a/frontend/src/routes/book/+page.svelte +++ b/frontend/src/routes/book/+page.svelte @@ -351,7 +351,6 @@ : [] ); - // NEW: Generate grouped time slots (available as individual buttons, unavailable as grouped blocks) function generateGroupedTimeSlots( duration: number, date: CalendarDate | undefined @@ -429,28 +428,50 @@ startTime: timeStr, endTime: slotEndTime }); + + // If this available slot ends at or after closing time, break out early + // to avoid generating unnecessary slots + if (timeToMinutes(slotEndTime) >= endTotalMinutes) { + break; + } } else { // Start or continue unavailable group if (currentUnavailableStart === null) { currentUnavailableStart = timeStr; } - // Continue the group - we'll close it when we hit an available slot or end } } // Close any remaining unavailable group at the end of the day + // BUT only if there are no available slots that already reach closing time if (currentUnavailableStart !== null) { - groupedSlots.push({ - type: 'unavailable', - startTime: currentUnavailableStart, - endTime: dayWorkingHours.endTime, - isGrouped: true - }); + const lastAvailableSlot = groupedSlots.filter((s) => s.type === 'available').pop(); + const lastAvailableEnd = lastAvailableSlot ? timeToMinutes(lastAvailableSlot.endTime) : 0; + + // Only add the final unavailable group if: + // 1. It actually contains some time before closing + // 2. No available slot already reaches closing time + const unavailableStartMinutes = timeToMinutes(currentUnavailableStart); + + if (unavailableStartMinutes < endTotalMinutes && lastAvailableEnd < endTotalMinutes) { + groupedSlots.push({ + type: 'unavailable', + startTime: currentUnavailableStart, + endTime: dayWorkingHours.endTime, + isGrouped: true + }); + } } return groupedSlots; } + // Helper: Convert time string to total minutes + function timeToMinutes(time: string): number { + const [hours, minutes] = time.split(':').map(Number); + return hours * 60 + minutes; + } + // Helper: Calculate the previous 15-minute time slot function calculatePreviousTime(time: string): string { const [hours, minutes] = time.split(':').map(Number); @@ -462,7 +483,6 @@ return `${String(prevHours).padStart(2, '0')}:${String(prevMinutes).padStart(2, '0')}`; } - // NEW: Generate available time slots within available segments function generateAvailableTimeSlots(duration: number, date: CalendarDate | undefined): string[] { if (!date || !workingHours || !availableHours) { return [];