import { useState, useRef, useEffect } from "react"; import { format, parse } from "date-fns"; import { CalendarIcon } from "lucide-react"; import { Calendar } from "@/components/ui/calendar"; import { cn } from "@/lib/utils"; interface CustomDateInputProps { value: string | null; onChange: (date: string | null) => void; placeholder?: string; label?: string; disabled?: boolean; minDate?: Date; maxDate?: Date; className?: string; error?: string; } export function CustomDateInput({ value, onChange, placeholder = "Pick a date", label, disabled = false, minDate, maxDate, className, error }: CustomDateInputProps) { const [open, setOpen] = useState(false); const datePickerRef = useRef(null); // Convert string date to Date object for the calendar const getDateValue = (): Date | undefined => { if (!value) return undefined; try { return parse(value, "yyyy-MM-dd", new Date()); } catch (e) { console.error("Invalid date format:", value); return undefined; } }; // Update the date value as string in yyyy-MM-dd format const handleDateSelect = (date: Date | undefined) => { if (!date) { onChange(null); return; } try { const formattedDate = format(date, "yyyy-MM-dd"); onChange(formattedDate); setOpen(false); } catch (e) { console.error("Error formatting date:", e); } }; // Format date for display const getDisplayDate = (): string => { if (!value) return placeholder; try { const date = parse(value, "yyyy-MM-dd", new Date()); return format(date, "PPP"); // Human readable format } catch (e) { console.error("Error parsing date for display:", e); return value; } }; // Close date picker when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (datePickerRef.current && !datePickerRef.current.contains(event.target as Node)) { setOpen(false); } }; if (open) { document.addEventListener("mousedown", handleClickOutside); } return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [open]); const toggleOpen = (e: React.MouseEvent) => { if (disabled) return; e.preventDefault(); e.stopPropagation(); setOpen(!open); }; return (
{label &&
{label}
}
{getDisplayDate()}
{open && (
{ if (minDate && date < minDate) return true; if (maxDate && date > maxDate) return true; return false; }} initialFocus />
)}
{error &&

{error}

}
); }