import { format, eachDayOfInterval, endOfMonth, startOfMonth, startOfYear, endOfYear, eachMonthOfInterval, getDay } from 'date-fns'; import { es } from 'date-fns/locale'; import type { Reservation } from '../types'; interface Props { reservations: Reservation[]; year: number; } export function YearlyCalendar({ reservations = [], year }: Props) { const months = eachMonthOfInterval({ start: startOfYear(new Date(year, 0, 1)), end: endOfYear(new Date(year, 0, 1)) }); const isDayOccupied = (date: Date) => { if (!reservations || !Array.isArray(reservations)) return false; return reservations.some(res => { if (!res.start_date || !res.end_date) return false; const start = new Date(res.start_date); const end = new Date(res.end_date); if (isNaN(start.getTime()) || isNaN(end.getTime())) return false; // Ajuste de zona horaria simple const checkDate = new Date(date); checkDate.setHours(12, 0, 0, 0); start.setHours(0, 0, 0, 0); end.setHours(23, 59, 59, 999); return checkDate >= start && checkDate <= end; }); }; return (

Vista Anual {year}

Panorama global de ocupación.

Libre
Ocupado
{months.map((month) => { const monthStart = startOfMonth(month); const monthEnd = endOfMonth(month); const days = eachDayOfInterval({ start: monthStart, end: monthEnd }); const startDayOfWeek = getDay(monthStart); // 0 = Sunday // Create empty slots for days before the 1st of the month const emptySlots = Array(startDayOfWeek).fill(null); return (

{format(month, 'MMMM', { locale: es })}

{['D', 'L', 'M', 'X', 'J', 'V', 'S'].map(d => (
{d}
))}
{emptySlots.map((_, i) => (
))} {days.map((day) => { const occupied = isDayOccupied(day); return (
{format(day, 'd')} {/* Tooltip on hover if occupied (simplified) */} {occupied && (
Ocupado
)}
); })}
); })}
); }