"use client"; import { useState, Fragment } from "react"; import { Popover, PopoverButton, PopoverPanel, Transition } from "@headlessui/react"; import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon, ClockIcon } from "@heroicons/react/24/outline"; import { format, addMonths, subMonths, startOfMonth, endOfMonth, startOfWeek, endOfWeek, isSameMonth, isSameDay, addDays, eachDayOfInterval, isWithinInterval, isBefore, subDays } from "date-fns"; import { ptBR } from "date-fns/locale"; interface DatePickerProps { value?: { start: Date | null; end: Date | null } | Date | null; onChange: (val: any) => void; placeholder?: string; className?: string; buttonClassName?: string; mode?: 'single' | 'range'; label?: string; } export default function DatePicker({ value, onChange, placeholder, className = "", buttonClassName = "", mode = 'range', label }: DatePickerProps) { const [currentMonth, setCurrentMonth] = useState(new Date()); // Helper to normalize value const getRange = () => { if (mode === 'single') { const date = value instanceof Date ? value : (value as any)?.start || null; return { start: date, end: date }; } const range = (value as { start: Date | null; end: Date | null }) || { start: null, end: null }; return range; }; const range = getRange(); const quickRanges = [ { label: 'Hoje', getValue: () => ({ start: new Date(), end: new Date() }) }, { label: 'Últimos 7 dias', getValue: () => ({ start: subDays(new Date(), 7), end: new Date() }) }, { label: 'Últimos 14 dias', getValue: () => ({ start: subDays(new Date(), 14), end: new Date() }) }, { label: 'Últimos 30 dias', getValue: () => ({ start: subDays(new Date(), 30), end: new Date() }) }, { label: 'Este Mês', getValue: () => ({ start: startOfMonth(new Date()), end: endOfMonth(new Date()) }) }, ]; const handleDateClick = (day: Date) => { if (mode === 'single') { onChange(day); return; } if (!range.start || (range.start && range.end)) { onChange({ start: day, end: null }); } else { if (isBefore(day, range.start)) { onChange({ start: day, end: range.start }); } else { onChange({ start: range.start, end: day }); } } }; const isInRange = (day: Date) => { if (range.start && range.end) { return isWithinInterval(day, { start: range.start, end: range.end }); } return false; }; const displayValue = () => { if (!range.start) return placeholder || (mode === 'single' ? "Selecionar data" : "Selecionar período"); if (mode === 'single') return format(range.start, "dd/MM/yyyy", { locale: ptBR }); if (!range.end || isSameDay(range.start, range.end)) return format(range.start, "dd MMM yyyy", { locale: ptBR }); return `${format(range.start, "dd MMM", { locale: ptBR })} - ${format(range.end, "dd MMM yyyy", { locale: ptBR })}`; }; const handleClear = (e: React.MouseEvent) => { e.stopPropagation(); onChange(mode === 'single' ? null : { start: null, end: null }); }; return ( {label && ( )} {displayValue()} {range.start && ( )} {/* Filtros Rápidos (Apenas para Range) */} {mode === 'range' && (

Atalhos

{quickRanges.map((r) => ( ))}
)} {/* Calendário */}
{format(currentMonth, "MMMM yyyy", { locale: ptBR })}
{["D", "S", "T", "Q", "Q", "S", "S"].map((day, idx) => (
{day}
))}
{eachDayOfInterval({ start: startOfWeek(startOfMonth(currentMonth)), end: endOfWeek(endOfMonth(currentMonth)) }).map((day, idx) => { const isStart = range.start && isSameDay(day, range.start); const isEnd = range.end && isSameDay(day, range.end); const isSelected = isStart || isEnd; const isRange = isInRange(day); const isCurrentMonth = isSameMonth(day, startOfMonth(currentMonth)); const isTodayDate = isSameDay(day, new Date()); return ( ); })}
); }