import React, { useCallback, useMemo, useState } from 'react'; import { format } from 'date-fns'; import { DayPicker, SelectSingleEventHandler, DateRange, } from 'react-day-picker'; import { Button, Input, Popover, PopoverContent, PopoverHandler, } from '@material-tailwind/react'; import HorizontalLine from './HorizontalLine'; // https://www.material-tailwind.com/docs/react/plugins/date-picker#date-picker const DAY_PICKER_CLASS_NAMES = { caption: 'flex justify-center py-2 mb-4 relative items-center', caption_label: 'text-sm font-medium text-gray-900', nav: 'flex items-center', nav_button: 'h-6 w-6 bg-transparent hover:bg-blue-gray-50 p-1 rounded-md transition-colors duration-300', nav_button_previous: 'absolute left-1.5', nav_button_next: 'absolute right-1.5', table: 'w-full border-collapse', head_row: 'flex font-medium text-gray-900', head_cell: 'm-0.5 w-9 font-normal text-sm', row: 'flex w-full mt-2', cell: 'text-gray-600 rounded-md h-9 w-9 text-center text-sm p-0 m-0.5 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-gray-900/20 [&:has([aria-selected].day-outside)]:text-white [&:has([aria-selected])]:bg-gray-900/50 first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20', day: 'h-9 w-9 p-0 font-normal', day_range_end: 'day-range-end', day_selected: 'rounded-md bg-gray-900 text-white hover:bg-gray-900 hover:text-white focus:bg-gray-900 focus:text-white', day_today: 'rounded-md bg-gray-200 text-gray-900', day_outside: 'day-outside text-gray-500 opacity-50 aria-selected:bg-gray-500 aria-selected:text-gray-900 aria-selected:bg-opacity-10', day_disabled: 'text-gray-500 opacity-50', day_hidden: 'invisible', }; type SingleDateHandler = (value: Date) => void; type RangeDateHandler = (value: DateRange) => void; interface SingleDatePickerProps { mode: 'single'; selected?: Date; onSelect: SingleDateHandler; } interface RangeDatePickerProps { mode: 'range'; selected?: DateRange; onSelect: RangeDateHandler; } const DatePicker = ({ mode = 'single', selected, onSelect, }: SingleDatePickerProps | RangeDatePickerProps) => { const [isOpen, setIsOpen] = useState(false); const [rangeSelected, setRangeSelected] = useState(); const inputValue = useMemo(() => { if (mode === 'single') { return selected ? format(selected as Date, 'PPP') : 'Select Date'; } if (mode === 'range') { const selectedRange = selected as DateRange | undefined; return selectedRange && selectedRange.from && selectedRange.to ? format(selectedRange.from, 'PP') + '-' + format(selectedRange.to, 'PP') : 'All time'; } }, [selected, mode]); const handleSingleSelect = useCallback((value) => { if (value) { (onSelect as SingleDateHandler)(value); setIsOpen(false); } }, []); const handleRangeSelect = useCallback(() => { if (rangeSelected?.to) { (onSelect as RangeDateHandler)(rangeSelected); setIsOpen(false); } }, [rangeSelected]); const components = { IconLeft: ({ ...props }) => ( {'<'} ), IconRight: ({ ...props }) => ( {'>'} ), }; const commonDayPickerProps = { components, className: 'border-0', classNames: DAY_PICKER_CLASS_NAMES, showOutsideDays: true, }; return ( setIsOpen(value)} > null} value={inputValue} crossOrigin={undefined} /> {mode === 'single' && ( )} {mode === 'range' && ( <>
)}
); }; export default DatePicker;