import * as React from "react"; import { format } from "date-fns"; import { CalendarIcon, X } from "lucide-react"; import type { DateRange as CalendarDateRange } from "react-day-picker"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Calendar } from "@/components/ui/calendar"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Badge } from "@/components/ui/badge"; export interface DateRange { from?: Date; to?: Date; } export interface DateRangePickerProps { value?: DateRange; onChange?: (range: DateRange | undefined) => void; placeholder?: string; disabled?: boolean; className?: string; disableFuture?: boolean; disablePast?: boolean; fromYear?: number; toYear?: number; presets?: Array<{ label: string; range: DateRange; }>; } const defaultPresets = [ { label: "Today", range: { from: new Date(), to: new Date(), }, }, { label: "Last 7 days", range: { from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), to: new Date(), }, }, { label: "Last 30 days", range: { from: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), to: new Date(), }, }, { label: "This year", range: { from: new Date(new Date().getFullYear(), 0, 1), to: new Date(), }, }, ]; export function DateRangePicker({ value, onChange, placeholder = "Pick a date range", disabled = false, className, disableFuture = false, disablePast = false, fromYear, toYear, presets = defaultPresets, }: DateRangePickerProps) { const [open, setOpen] = React.useState(false); const handleSelect = (range: DateRange | undefined) => { onChange?.(range); }; const handlePresetSelect = (preset: DateRange) => { handleSelect(preset); setOpen(false); }; const handleClear = () => { handleSelect(undefined); }; const getDisabledDates = (date: Date) => { const now = new Date(); if (disableFuture && date > now) return true; if (disablePast && date < now) return true; return false; }; const formatRange = (range: DateRange | undefined) => { if (!range?.from) return placeholder; if (!range.to) return format(range.from, "MMM dd, yyyy"); if (range.from.getTime() === range.to.getTime()) { return format(range.from, "MMM dd, yyyy"); } return `${format(range.from, "MMM dd, yyyy")} - ${format(range.to, "MMM dd, yyyy")}`; }; return (
void} numberOfMonths={2} disabled={getDisabledDates} className="p-3 pointer-events-auto" fromYear={fromYear} toYear={toYear} />
{presets.length > 0 && (
Presets
{presets.map((preset, index) => ( ))}
)}
{value?.from && ( {formatRange(value)} )}
); }