website/components/DatePicker.tsx

99 lines
4.0 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 { Calendar } from '@/components/ui/calendar';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
interface DatePickerProps {
date: Date | undefined;
setDate: (date: Date | undefined) => void;
label?: string;
}
export function DatePicker({ date, setDate, label }: DatePickerProps) {
const [open, setOpen] = React.useState(false);
return (
<div className="space-y-2">
{label && (
<label className="text-sm font-medium text-gray-700 dark:text-gray-300">
{label}
</label>
)}
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild>
<Button
variant={'outline'}
size="sm"
className={cn(
'justify-start text-left font-normal',
!date && 'text-muted-foreground'
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{date ? format(date, 'PPP') : <span>Pick a date</span>}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-auto p-5 bg-gradient-to-br from-white to-gray-50 dark:from-gray-800 dark:to-gray-900 shadow-2xl border-2 border-gray-100 dark:border-gray-700 rounded-2xl" align="end" sideOffset={5}>
<Calendar
mode="single"
selected={date}
onSelect={(selectedDate) => {
setDate(selectedDate);
setOpen(false);
}}
initialFocus
classNames={{
months: "space-y-4",
month: "space-y-4",
caption: "flex justify-center pt-3 pb-5 relative items-center border-b border-gray-200 dark:border-gray-700 mb-4",
caption_label: "text-lg font-bold text-gray-800 dark:text-gray-100",
nav: "flex items-center justify-between absolute inset-0",
nav_button: cn(
"h-9 w-9 rounded-full bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 hover:bg-rose-50 dark:hover:bg-gray-600 hover:border-rose-300 dark:hover:border-rose-500 p-0 transition-all shadow-sm"
),
nav_button_previous: "absolute left-0",
nav_button_next: "absolute right-0",
table: "w-full border-collapse space-y-3",
head_row: "flex mb-3",
head_cell: "text-gray-600 dark:text-gray-400 rounded-md w-11 font-semibold text-xs",
row: "flex w-full mt-2",
cell: cn(
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20",
"[&>button]:h-11 [&>button]:w-11 [&>button]:p-0 [&>button]:font-semibold [&>button]:cursor-pointer [&>button]:rounded-full [&>button]:transition-all"
),
day: cn(
"h-11 w-11 p-0 font-semibold aria-selected:opacity-100 hover:bg-rose-500 hover:text-white rounded-full transition-all cursor-pointer",
"hover:scale-110 active:scale-95 hover:shadow-md"
),
day_selected:
"bg-rose-600 text-white hover:bg-rose-700 hover:text-white focus:bg-rose-600 focus:text-white font-bold shadow-xl scale-110 ring-4 ring-rose-200 dark:ring-rose-800",
day_today: "bg-blue-50 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 font-bold border-2 border-blue-300 dark:border-blue-600",
day_outside: "text-gray-300 dark:text-gray-600 opacity-50",
day_disabled: "text-gray-200 dark:text-gray-700 opacity-30 cursor-not-allowed",
day_range_middle:
"aria-selected:bg-rose-100 dark:aria-selected:bg-rose-900/30 aria-selected:text-rose-700 dark:aria-selected:text-rose-300",
day_hidden: "invisible",
}}
/>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
}