break calendar
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user