// js/components/calendar.js // Import time utilities import { timeToMinutes, formatDate } from '../utils/time-utils.js'; import { fetchAvailability } from '../utils/api.js'; // Global variables for calendar let currentAdminDate = new Date(); let currentAdminMonth = currentAdminDate.getMonth(); let currentAdminYear = currentAdminDate.getFullYear(); let selectedAdminDate = null; const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; // Render the admin calendar with available dates highlighted async function renderAdminCalendar(month, year) { const adminCalendarDates = document.getElementById('adminCalendarDates'); const adminMonthYear = document.getElementById('adminMonthYear'); if (!adminCalendarDates || !adminMonthYear) { console.error('Required calendar elements not found'); return; } // Clear existing calendar adminCalendarDates.innerHTML = ''; adminMonthYear.textContent = `${months[month]} ${year}`; // Get current UID and availability const selectedUid = document.getElementById('uidSelect').value; if (!selectedUid) { // If no UID selected, just show empty calendar return; } const firstDay = new Date(year, month, 1).getDay(); const daysInMonth = new Date(year, month + 1, 0).getDate(); const today = new Date(); const currentMinutes = today.getHours() * 60 + today.getMinutes(); const availability = await fetchAvailability(); // Start of today (midnight) const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // Create blank cells for days before the first day of the month for (let i = 0; i < firstDay; i++) { const blank = document.createElement('div'); blank.classList.add('date-item', 'p-2', 'rounded-pill', 'text-center', 'text-muted', 'empty-cell'); blank.style.cursor = 'default'; // Remove pointer cursor blank.style.pointerEvents = 'none'; // Disable hover and click events adminCalendarDates.appendChild(blank); } // Clear any existing selected date const existingSelected = adminCalendarDates.querySelector('.selected'); if (existingSelected) { existingSelected.classList.remove('selected'); } // Populate the calendar with days let todayElement = null; for (let i = 1; i <= daysInMonth; i++) { const day = document.createElement('div'); day.classList.add('date-item', 'p-2', 'rounded-pill', 'text-center'); day.textContent = i; const date = new Date(year, month, i); const dateStr = formatDate(date); // Check if date is in the past const isPastDate = date < startOfToday; const isToday = date.toDateString() === today.toDateString(); if (isToday) { day.classList.add('current'); todayElement = day; } // Check if the date has available time slots let hasAvailableTimes = false; if (availability[dateStr]) { let times = []; if (typeof availability[dateStr] === 'string') { times = availability[dateStr].split(',').map(t => t.trim()); } else if (Array.isArray(availability[dateStr])) { times = availability[dateStr].map(t => t.trim()); } // For today, filter out past times if (isToday) { times = times.filter(time => timeToMinutes(time) > currentMinutes); } // Only mark as available if there are valid times hasAvailableTimes = times.length > 0; } // Only add 'available' class if the date is not in the past AND has available times if (hasAvailableTimes && !isPastDate) { day.classList.add('available'); } if (isPastDate) { day.classList.add('disabled'); } else { day.addEventListener('click', () => selectAdminDate(date, firstDay)); } adminCalendarDates.appendChild(day); } // If a date was previously selected, re-select it if (selectedAdminDate && selectedAdminDate.getMonth() === month && selectedAdminDate.getFullYear() === year) { selectAdminDate(selectedAdminDate, firstDay); } } // Handle admin date selection async function selectAdminDate(date, firstDay) { // Check if the date is in the past const today = new Date(); const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate()); if (date < startOfToday) { console.warn('Attempted to select a past date'); return; } // Update selected date selectedAdminDate = date; // Get the date string for the selected date const dateStr = formatDate(date); // Trigger the updateTimeSlots function in admin.js const event = new CustomEvent('dateSelected', { detail: { dateStr: dateStr } }); document.dispatchEvent(event); // Update UI to show selected date const dateItems = document.querySelectorAll('#adminCalendarDates .date-item'); dateItems.forEach(item => item.classList.remove('selected')); // Ensure only one date is selected // Find the exact date item for the clicked date const selectedDay = Array.from(dateItems).find(item => { const dayText = item.textContent; if (!dayText || isNaN(parseInt(dayText))) return false; const itemDate = new Date(currentAdminYear, currentAdminMonth, parseInt(dayText)); return itemDate.toDateString() === date.toDateString(); }); if (selectedDay) selectedDay.classList.add('selected'); const selectedDateDisplay = document.getElementById('selectedDateDisplay'); if (selectedDateDisplay) { selectedDateDisplay.textContent = ''; } // Show the availability section const availabilitySection = document.getElementById('availabilitySection'); if (availabilitySection) { availabilitySection.classList.remove('d-none'); } } // Export functions for use in other files export { renderAdminCalendar, selectAdminDate, currentAdminMonth, currentAdminYear, selectedAdminDate, months };