"use client"; import { useState, useRef, useEffect, useCallback } from "react"; import { useTranslations } from "next-intl"; interface CustomRangePickerProps { start: string; end: string; onApply: (start: string, end: string) => void; onClose: () => void; } function toLocalDatetime(iso: string): string { if (!iso) return ""; const d = new Date(iso); if (isNaN(d.getTime())) return ""; const pad = (n: number) => String(n).padStart(2, "0"); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; } function fromLocalDatetime(local: string): string { if (!local) return ""; return new Date(local).toISOString(); } function getPresetRange(preset: string): { start: string; end: string } { const now = new Date(); const end = toLocalDatetime(now.toISOString()); const s = new Date(now); switch (preset) { case "today": s.setHours(0, 0, 0, 0); break; case "yesterday": { s.setDate(s.getDate() - 1); s.setHours(0, 0, 0, 0); const e = new Date(s); e.setHours(23, 59, 59, 999); return { start: toLocalDatetime(s.toISOString()), end: toLocalDatetime(e.toISOString()) }; } case "thisWeek": s.setDate(s.getDate() - s.getDay()); s.setHours(0, 0, 0, 0); break; case "thisMonth": s.setDate(1); s.setHours(0, 0, 0, 0); break; case "last3d": s.setDate(s.getDate() - 3); break; case "last14d": s.setDate(s.getDate() - 14); break; default: s.setDate(s.getDate() - 7); } return { start: toLocalDatetime(s.toISOString()), end }; } export default function CustomRangePicker({ start, end, onApply, onClose, }: CustomRangePickerProps) { const t = useTranslations("analytics"); const [localStart, setLocalStart] = useState(toLocalDatetime(start) || ""); const [localEnd, setLocalEnd] = useState(toLocalDatetime(end) || ""); const ref = useRef(null); // Close on click outside useEffect(() => { function handleClick(e: MouseEvent) { if (ref.current && !ref.current.contains(e.target as Node)) { onClose(); } } document.addEventListener("mousedown", handleClick); return () => document.removeEventListener("mousedown", handleClick); }, [onClose]); // Close on Escape useEffect(() => { function handleKey(e: KeyboardEvent) { if (e.key === "Escape") onClose(); } document.addEventListener("keydown", handleKey); return () => document.removeEventListener("keydown", handleKey); }, [onClose]); const handleApply = useCallback(() => { if (localStart && localEnd) { onApply(fromLocalDatetime(localStart), fromLocalDatetime(localEnd)); } }, [localStart, localEnd, onApply]); const handlePreset = useCallback((preset: string) => { const { start: s, end: e } = getPresetRange(preset); setLocalStart(s); setLocalEnd(e); }, []); const isValid = localStart && localEnd && new Date(localStart) <= new Date(localEnd); const presets = [ { key: "today", label: t("rangeToday") }, { key: "yesterday", label: t("rangeYesterday") }, { key: "last3d", label: t("rangeLast3Days") }, { key: "thisWeek", label: t("rangeThisWeek") }, { key: "last14d", label: t("rangeLast14Days") }, { key: "thisMonth", label: t("rangeThisMonth") }, ]; return (
{/* Quick presets */}

{t("rangeQuickSelect")}

{presets.map((p) => ( ))}
{/* Date inputs */}
setLocalStart(e.target.value)} className="w-full rounded-lg border border-border/50 bg-black/[0.04] px-3 py-2 text-sm text-text-main focus:outline-none focus:border-primary dark:bg-white/[0.04]" />
setLocalEnd(e.target.value)} className="w-full rounded-lg border border-border/50 bg-black/[0.04] px-3 py-2 text-sm text-text-main focus:outline-none focus:border-primary dark:bg-white/[0.04]" />
{/* Validation hint */} {localStart && localEnd && !isValid && (

{t("rangeErrorInvalid")}

)} {/* Actions */}
); }