Files
DABEEO-DETECTION-APPLICATION/web-app/app/shared/components/datePicker/DateRangePicker.tsx

114 lines
3.4 KiB
TypeScript

import {
DateRangePicker as AriaDateRangePicker,
Button,
Dialog,
Group,
OverlayArrow,
Popover,
} from 'react-aria-components';
import dayjs from 'dayjs';
import { tv } from 'tailwind-variants';
import { CalendarIcon } from '@/components/icons';
import { RangeCalendar } from '../calendar/RangeCalendar';
import { calendarDateToDate, dateToCalendarDate } from '../calendar/utils';
const trigger = tv({
base: 'flex h-9 w-[260px] cursor-pointer items-center border border-kc-gray-be bg-white text-left outline-none transition',
variants: {
isHovered: {
true: 'border-kc-black-34',
},
isFocused: {
true: 'border-kc-black-34',
},
isDisabled: {
true: 'cursor-default border-kc-gray-99 bg-kc-gray-eb',
},
isFocusVisible: {
true: 'ring-2 ring-offset-2 ring-primary',
},
},
});
export type DateRangePickerProps = {
value: { start: Date; end: Date } | null;
onChange: (value: { start: Date; end: Date } | null) => void;
maxValue?: Date | null;
minValue?: Date | null;
isDisabled?: boolean;
className?: string;
startName?: string;
endName?: string;
};
export function DateRangePicker({
value,
onChange,
maxValue,
minValue,
isDisabled,
className,
startName,
endName,
}: DateRangePickerProps) {
const ariaValue = value ? { start: dateToCalendarDate(value.start)!, end: dateToCalendarDate(value.end)! } : null;
return (
<AriaDateRangePicker
aria-label="날짜 범위 선택"
value={ariaValue}
onChange={(range) => {
if (!range) {
onChange(null);
} else {
onChange({
start: calendarDateToDate(range.start)!,
end: calendarDateToDate(range.end)!,
});
}
}}
maxValue={maxValue !== undefined ? dateToCalendarDate(maxValue) : undefined}
minValue={minValue !== undefined ? dateToCalendarDate(minValue) : undefined}
isDisabled={isDisabled}
granularity="day"
firstDayOfWeek="sun"
className={className}
startName={startName}
endName={endName}
>
<Group>
<Button className={(renderProps) => trigger(renderProps)}>
<span className={`tabular-nums px-3 text-sm ${value?.start ? 'text-kc-black-34' : 'text-kc-gray-99'}`}>
{value?.start ? dayjs(value.start).format('YYYY. MM. DD') : 'YYYY.MM.DD'}
</span>
<span className="text-sm text-kc-gray-99">~</span>
<span className={`tabular-nums flex-1 px-3 text-sm ${value?.end ? 'text-kc-black-34' : 'text-kc-gray-99'}`}>
{value?.end ? dayjs(value.end).format('YYYY. MM. DD') : 'YYYY.MM.DD'}
</span>
<span className="flex h-full w-8 shrink-0 items-center justify-center text-kc-gray-99">
<CalendarIcon className="h-4 w-4" />
</span>
</Button>
</Group>
<Popover className="bg-white border border-kc-gray-be p-3 px-6 pb-6 drop-shadow-modal outline-none" offset={12}>
<OverlayArrow className="group/arrow">
<svg
width="12"
height="8"
viewBox="0 0 12 8"
className="block fill-white stroke-kc-gray-be group-data-[placement=bottom]/arrow:rotate-180"
>
<path d="M0 0 L6 8 L12 0" />
</svg>
</OverlayArrow>
<Dialog className="outline-none">
<RangeCalendar />
</Dialog>
</Popover>
</AriaDateRangePicker>
);
}