// Calendar view: month grid with task indicators + day detail panel function CalendarView({ items, openForm, onStatusChange, onEdit }) { const [cursor, setCursor] = React.useState(new Date(TODAY.getFullYear(), TODAY.getMonth(), 1)); const [selected, setSelected] = React.useState(TODAY); const month = cursor.getMonth(); const year = cursor.getFullYear(); const first = new Date(year, month, 1); const last = new Date(year, month + 1, 0); // Start grid on Monday const startWeekday = (first.getDay() + 6) % 7; // 0 = Mon const totalDays = last.getDate(); const cells = []; for (let i = 0; i < startWeekday; i++) cells.push({ outside: true, date: addDays(first, i - startWeekday) }); for (let d = 1; d <= totalDays; d++) cells.push({ outside: false, date: new Date(year, month, d) }); while (cells.length % 7 !== 0) cells.push({ outside: true, date: addDays(last, cells.length - startWeekday - totalDays + 1) }); const dayItems = itemsOnDate(items, selected); return (
{MONTHS[month].charAt(0).toUpperCase() + MONTHS[month].slice(1)}{" "} {year} } action={
setCursor(new Date(year, month - 1, 1))} /> setCursor(new Date(year, month + 1, 1))} />
} />
{["lun.","mar.","mer.","jeu.","ven.","sam.","dim."].map(d => (
{d}
))}
{cells.map((cell, i) => { const its = itemsOnDate(items, cell.date); const isToday = sameDay(cell.date, TODAY); const isSelected = sameDay(cell.date, selected); return ( ); })}
{/* Day detail */}
{sameDay(selected, TODAY) ? "Aujourd'hui" : fmtRel(selected)}
{DAYS_LONG[selected.getDay()].charAt(0).toUpperCase() + DAYS_LONG[selected.getDay()].slice(1)} {selected.getDate()} {MONTHS[selected.getMonth()]}
{dayItems.length === 0 ? (
Aucune tâche ni événement
) : ( dayItems.map(it => ) )}
{/* Legend */}
Légende
{Object.entries(STATES).map(([k, s]) => ( {s.label} ))}
{Object.entries(KINDS).filter(([k]) => k !== "task").map(([k, kk]) => ( {kk.label} ))}
); } Object.assign(window, { CalendarView });