'use client'; import { useEffect, useId, useRef, useState } from 'react'; import { ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react'; import { addCalendarDays, startOfLocalDay } from '@/components/appointments/appointmentTime'; interface ScheduleDayPickerProps { value: Date; onChange: (day: Date) => void; label?: string; } const MONTH_LABELS = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', ] as const; function daysInMonth(year: number, month: number): number { return new Date(year, month + 1, 0).getDate(); } function buildLocalDay(year: number, month: number, day: number): Date { return new Date(year, month, day, 0, 0, 0, 0); } function yearRange(anchor: Date): number[] { const anchorYear = anchor.getFullYear(); const startYear = anchorYear - 10; const endYear = anchorYear + 2; const years: number[] = []; for (let y = startYear; y <= endYear; y += 1) { years.push(y); } return years; } const selectClassName = ` w-full appearance-none rounded-[var(--radius-sm)] border border-border bg-background-card/90 text-text-primary text-sm pl-2 pr-7 py-1.5 focus:outline-none focus:ring-2 focus:ring-primary/35 focus:border-border-strong `; /** * Calendar day navigator (arrows + year/month/day panel). * Does not restrict past dates — parent pages enforce read-only vs editable for schedule grids/forms. */ export function ScheduleDayPicker({ value, onChange, label = 'Schedule date' }: ScheduleDayPickerProps) { const panelId = useId(); const rootRef = useRef(null); const [panelOpen, setPanelOpen] = useState(false); const normalizedValue = startOfLocalDay(value); const labelText = normalizedValue.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', }); const years = yearRange(normalizedValue); const selectedYear = normalizedValue.getFullYear(); const selectedMonth = normalizedValue.getMonth(); const selectedDay = normalizedValue.getDate(); const dayCount = daysInMonth(selectedYear, selectedMonth); function applyParts(year: number, month: number, day: number, closePanel = false) { const maxDay = daysInMonth(year, month); onChange(buildLocalDay(year, month, Math.min(Math.max(1, day), maxDay))); if (closePanel) { setPanelOpen(false); } } useEffect(() => { if (!panelOpen) return; function onPointerDown(event: MouseEvent) { if (!rootRef.current?.contains(event.target as Node)) { setPanelOpen(false); } } function onKeyDown(event: KeyboardEvent) { if (event.key === 'Escape') { setPanelOpen(false); } } document.addEventListener('mousedown', onPointerDown); document.addEventListener('keydown', onKeyDown); return () => { document.removeEventListener('mousedown', onPointerDown); document.removeEventListener('keydown', onKeyDown); }; }, [panelOpen]); return (

{label}

{panelOpen && ( )}
); }