website/components/DatePicker.tsx

80 lines
2.5 KiB
TypeScript
Raw Permalink Normal View History

'use client';
import * as React from 'react';
import { Calendar as CalendarIcon } from 'lucide-react';
import { format } from 'date-fns';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import DatePickerLib from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
interface DatePickerProps {
date: Date | undefined;
setDate: (date: Date | undefined) => void;
label?: string;
}
export function DatePicker({ date, setDate, label }: DatePickerProps) {
const [isOpen, setIsOpen] = React.useState(false);
const wrapperRef = React.useRef<HTMLDivElement>(null);
// Close calendar when clicking outside
React.useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
};
if (isOpen) {
document.addEventListener('mousedown', handleClickOutside);
}
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [isOpen]);
return (
<div className="space-y-2">
{label && (
<label className="text-sm font-medium text-gray-700 dark:text-gray-300">
{label}
</label>
)}
<div className="relative" ref={wrapperRef}>
<Button
type="button"
variant="outline"
onClick={() => setIsOpen(!isOpen)}
className={cn(
"w-full justify-start text-left font-normal h-10",
!date && "text-muted-foreground",
"bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 text-gray-900 dark:text-white hover:bg-gray-50 dark:hover:bg-gray-600"
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{date ? format(date, "PPP") : <span>Pick a date</span>}
</Button>
{isOpen && (
<div className="absolute z-[9999] mt-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-md shadow-lg">
<DatePickerLib
selected={date || null}
onChange={(selectedDate: Date | null) => {
setDate(selectedDate || undefined);
if (selectedDate) {
setIsOpen(false);
}
}}
minDate={new Date()}
inline
calendarClassName="!border-0"
wrapperClassName="w-full"
/>
</div>
)}
</div>
</div>
);
}