import React, { useState, useEffect, useRef } from 'react'; import { format, addMonths, subMonths, startOfMonth, endOfMonth, startOfWeek, endOfWeek, addDays, isSameMonth, isSameDay, setMonth, setYear, getYear, getMonth } from 'date-fns'; import { enUS, de } from 'date-fns/locale'; interface DatePickerProps { selected: Date; onSelect: (date: Date) => void; onClose: () => void; language?: string; } export default function DatePicker({ selected, onSelect, onClose, language = 'en' }: DatePickerProps) { const [currentMonth, setCurrentMonth] = useState(new Date(selected)); const [view, setView] = useState<'calendar' | 'month-year'>('calendar'); const modalRef = useRef(null); const locale = language === 'de' ? de : enUS; // Close on click outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (modalRef.current && !modalRef.current.contains(event.target as Node)) { onClose(); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, [onClose]); // Calendar Header const renderHeader = () => { return (
setView(view === 'calendar' ? 'month-year' : 'calendar')} > {format(currentMonth, 'MMMM yyyy', { locale })}
); }; // Days of Week Header const renderDays = () => { const days = []; const startDate = startOfWeek(currentMonth, { weekStartsOn: 1 }); // Monday start for (let i = 0; i < 7; i++) { days.push(
{format(addDays(startDate, i), 'EEEEEE', { locale })}
); } return
{days}
; }; // Calendar Cells const renderCells = () => { const monthStart = startOfMonth(currentMonth); const monthEnd = endOfMonth(monthStart); const startDate = startOfWeek(monthStart, { weekStartsOn: 1 }); const endDate = endOfWeek(monthEnd, { weekStartsOn: 1 }); const dateFormat = 'd'; const rows = []; let days = []; let day = startDate; let formattedDate = ''; while (day <= endDate) { for (let i = 0; i < 7; i++) { formattedDate = format(day, dateFormat); const cloneDay = day; days.push(
{ onSelect(cloneDay); onClose(); }} > {formattedDate}
); day = addDays(day, 1); } rows.push(
{days}
); days = []; } return
{rows}
; }; // Month/Year Selection View const renderMonthYearSelector = () => { const years = []; const currentYear = getYear(new Date()); for (let y = currentYear - 5; y <= currentYear + 5; y++) { years.push(y); } const months = Array.from({ length: 12 }, (_, i) => { return format(setMonth(new Date(), i), 'MMM', { locale }); }); return (
{years.map(year => (
setCurrentMonth(setYear(currentMonth, year))} > {year}
))}
{months.map((month, index) => (
{ setCurrentMonth(setMonth(currentMonth, index)); setView('calendar'); }} > {month}
))}
); }; return (
{renderHeader()} {view === 'calendar' ? ( <> {renderDays()} {renderCells()} ) : ( renderMonthYearSelector() )}
); }