break calendar

This commit is contained in:
2025-10-15 21:25:26 +01:00
parent 5e9bad058f
commit 827b5d9b3d
+63 -20
View File
@@ -94,17 +94,24 @@
// Initialize date boundaries
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
const maxDate = new Date();
maxDate.setMonth(today.getMonth() + 6);
// Create CalendarDate objects directly without toCalendar conversion
const minDate = new CalendarDate(today.getFullYear(), today.getMonth() + 1, today.getDate());
const tomorrowDate = new CalendarDate(
tomorrow.getFullYear(),
tomorrow.getMonth() + 1,
tomorrow.getDate()
);
const maxCalendarDate = new CalendarDate(
maxDate.getFullYear(),
maxDate.getMonth() + 1,
maxDate.getDate()
);
let placeholder = $state<CalendarDate>(minDate);
let placeholder = $state<CalendarDate>(tomorrowDate);
$effect(() => {
const monthKey = `${placeholder.year}-${String(placeholder.month).padStart(2, '0')}`;
if (!workingHoursCache.has(monthKey)) {
@@ -116,7 +123,10 @@
async function fetchWorkingHoursForMonth(date: CalendarDate) {
const monthKey = `${date.year}-${String(date.month).padStart(2, '0')}`;
if (workingHoursCache.has(monthKey)) {
workingHours = workingHoursCache.get(monthKey)!;
// Use a timeout to ensure state updates properly
setTimeout(() => {
workingHours = workingHoursCache.get(monthKey)!;
}, 0);
return;
}
@@ -176,15 +186,16 @@
}
}
// Set default selected date to next available working day
// Set default selected date to next available working day (starting from tomorrow)
function setDefaultSelectedDate(
hoursMap: Record<string, { isOpen: boolean; startTime: string; endTime: string }>
) {
const currentDate = new Date();
let nextDate = new Date(currentDate);
// Check next 30 days for available working day
for (let i = 0; i < 30; i++) {
// Check next 30 days for available working day (starting from tomorrow, i=1)
for (let i = 1; i < 30; i++) {
nextDate = new Date(currentDate);
nextDate.setDate(currentDate.getDate() + i);
const dateStr = nextDate.toISOString().split('T')[0];
@@ -198,9 +209,15 @@
}
}
// Fallback to today if no working day found
// Fallback to tomorrow if no working day found
if (!selectedDate) {
selectedDate = minDate;
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
selectedDate = new CalendarDate(
tomorrow.getFullYear(),
tomorrow.getMonth() + 1,
tomorrow.getDate()
);
}
}
@@ -248,7 +265,7 @@
}
// Initialize with current month
fetchWorkingHoursForMonth(minDate);
fetchWorkingHoursForMonth(tomorrowDate);
// Handle calendar month change
function handleMonthChange(newMonth: CalendarDate) {
@@ -279,37 +296,63 @@
// If no data for this date, assume unavailable
if (!dayHours) return true;
return !dayHours.isOpen;
// If closed, mark as unavailable
if (!dayHours.isOpen) return true;
// Check if there are any available time slots for the selected services
if (selectedServices.length > 0) {
const duration = getTotalDuration();
const slots = generateTimeSlots(duration, date);
// If no slots available for the required duration, mark as unavailable
if (slots.length === 0) return true;
}
return false;
}
function generateTimeSlots(duration: number, date: CalendarDate | undefined) {
if (!date || !workingHours) return [];
function generateTimeSlots(duration: number, date: CalendarDate | undefined): string[] {
if (!date || !workingHours) {
return [];
}
const dateStr = date.toString();
const dayHours = workingHours[dateStr];
// If no working hours data or closed, return empty
if (!dayHours || !dayHours.isOpen) return [];
if (!dayHours || !dayHours.isOpen) {
return [];
}
const slots: string[] = [];
const slots = [];
const [startHour, startMinute] = dayHours.startTime.split(':').map(Number);
const [endHour, endMinute] = dayHours.endTime.split(':').map(Number);
// Convert to minutes for easier calculation
const startTotalMinutes = startHour * 60 + startMinute;
let startTotalMinutes = startHour * 60 + startMinute;
const endTotalMinutes = endHour * 60 + endMinute;
// Generate 15-minute intervals
const now = new Date();
const today = new CalendarDate(now.getFullYear(), now.getMonth() + 1, now.getDate());
const isToday = date.compare(today) === 0;
if (isToday) {
const currentMinutes = now.getHours() * 60 + now.getMinutes();
const minimumStartMinutes = currentMinutes + 120; // Current time + 2 hours
startTotalMinutes = Math.max(startTotalMinutes, minimumStartMinutes);
}
for (let minutes = startTotalMinutes; minutes < endTotalMinutes; minutes += 15) {
const slotEndMinutes = minutes + duration;
// Skip if slot would end after closing time
if (slotEndMinutes > endTotalMinutes) continue;
if (slotEndMinutes > endTotalMinutes) {
continue;
}
const hour = Math.floor(minutes / 60);
const minute = minutes % 60;
const timeStr = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
const timeStr = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
slots.push(timeStr);
}