"use client" import * as React from "react" import { format } from "date-fns" import { CalendarIcon } from "lucide-react" import { parseAsString, useQueryStates } from "nuqs" import { type DateRange } from "react-day-picker" import { cn } from "@/lib/utils" import { Button, type ButtonProps } from "@/components/ui/button" import { Calendar } from "@/components/ui/calendar" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" interface DateRangePickerProps extends React.ComponentPropsWithoutRef { /** * The selected date range. * @default undefined * @type DateRange * @example { from: new Date(), to: new Date() } */ defaultDateRange?: DateRange /** * The placeholder text of the calendar trigger button. * @default "Pick a date" * @type string | undefined */ placeholder?: string /** * The variant of the calendar trigger button. * @default "outline" * @type "default" | "outline" | "secondary" | "ghost" */ triggerVariant?: Exclude /** * The size of the calendar trigger button. * @default "default" * @type "default" | "sm" | "lg" */ triggerSize?: Exclude /** * The class name of the calendar trigger button. * @default undefined * @type string */ triggerClassName?: string /** * Controls whether query states are updated client-side only (default: true). * Setting to `false` triggers a network request to update the querystring. * @default true */ shallow?: boolean } export function DateRangePicker({ defaultDateRange, placeholder = "Pick a date", triggerVariant = "outline", triggerSize = "default", triggerClassName, shallow = true, className, ...props }: DateRangePickerProps) { const [dateParams, setDateParams] = useQueryStates( { from: parseAsString.withDefault( defaultDateRange?.from?.toISOString() ?? "" ), to: parseAsString.withDefault(defaultDateRange?.to?.toISOString() ?? ""), }, { clearOnDefault: true, shallow, } ) const date = React.useMemo(() => { function parseDate(dateString: string | null) { if (!dateString) return undefined const parsedDate = new Date(dateString) return isNaN(parsedDate.getTime()) ? undefined : parsedDate } return { from: parseDate(dateParams.from) ?? defaultDateRange?.from, to: parseDate(dateParams.to) ?? defaultDateRange?.to, } }, [dateParams, defaultDateRange]) return (
{ void setDateParams({ from: newDateRange?.from?.toISOString() ?? "", to: newDateRange?.to?.toISOString() ?? "", }) }} numberOfMonths={2} />
) }