80 lines
2.5 KiB
TypeScript
80 lines
2.5 KiB
TypeScript
'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>
|
|
);
|
|
}
|