import React, { useEffect, useMemo, useState } from 'react'; import { ChevronLeft, ChevronRight } from 'lucide-react'; import { MONTHS, monthGrid, parseISODate, todayISO } from '../../lib/journal'; interface JournalCalendarProps { /** Day currently in view; the calendar follows its month */ activeDate: string; /** Days with written entries (get a dot) */ entryDates: Set; onSelect: (date: string) => void; } const WEEKDAYS = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']; export const JournalCalendar: React.FC = ({ activeDate, entryDates, onSelect }) => { const active = parseISODate(activeDate); const [view, setView] = useState({ year: active.getFullYear(), month: active.getMonth() }); useEffect(() => { const d = parseISODate(activeDate); setView({ year: d.getFullYear(), month: d.getMonth() }); }, [activeDate]); const today = todayISO(); const weeks = useMemo(() => monthGrid(view.year, view.month), [view]); const years = useMemo(() => { const now = new Date().getFullYear(); let first = now - 5; entryDates.forEach((d) => { first = Math.min(first, Number(d.slice(0, 4))); }); const list: number[] = []; for (let y = now + 1; y >= first; y--) list.push(y); return list; }, [entryDates]); const shiftMonth = (delta: number) => setView((v) => { const d = new Date(v.year, v.month + delta, 1); return { year: d.getFullYear(), month: d.getMonth() }; }); return (
{WEEKDAYS.map((w) => ( {w} ))}
{weeks.flat().map((date, i) => date ? ( ) : ( ) )}
); };