import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { CalendarRange, ChevronDown } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { getUser } from '@/lib/auth-storage' // 预设时间范围:unit 决定文案键(minutes/hours),count 用于插值与复数 const presets = [ { unit: 'minutes', count: 5, ms: 300000 }, { unit: 'minutes', count: 15, ms: 900000 }, { unit: 'hours', count: 1, ms: 3600000 }, { unit: 'hours', count: 6, ms: 21600000 }, { unit: 'hours', count: 24, ms: 86400000 }, ] as const const localTime = (date: Date) => new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, 19) const historyKey = () => `lokistack.logs.range-history.${getUser()?.id ?? 'anonymous'}` type SavedRange = { start: string; end: string } function readHistory(): SavedRange[] { try { const value: unknown = JSON.parse(localStorage.getItem(historyKey()) ?? '[]') return Array.isArray(value) ? value.filter((item): item is SavedRange => typeof item?.start === 'string' && typeof item?.end === 'string').slice(0, 5) : [] } catch { return [] } } export function TimeRangePicker({ start, end, onChange }: { start: string; end: string; onChange: (start: string, end: string) => void }) { const { t } = useTranslation('logs') const [open, setOpen] = useState(false) const [draftStart, setDraftStart] = useState(start) const [draftEnd, setDraftEnd] = useState(end) const [history, setHistory] = useState(readHistory) const [selection, setSelection] = useState({ start, end, ms: 300000 as number | null }) const root = useRef(null) useEffect(() => { const close = (event: PointerEvent) => { if (!root.current?.contains(event.target as Node)) setOpen(false) } document.addEventListener('pointerdown', close) return () => document.removeEventListener('pointerdown', close) }, []) function choose(nextStart: string, nextEnd: string, nextPreset: number | null = null) { if (!(new Date(nextStart).getTime() < new Date(nextEnd).getTime())) return setSelection({ start: nextStart, end: nextEnd, ms: nextPreset }) onChange(nextStart, nextEnd) setDraftStart(nextStart); setDraftEnd(nextEnd); setOpen(false) const next = [{ start: nextStart, end: nextEnd }, ...history.filter(item => item.start !== nextStart || item.end !== nextEnd)].slice(0, 5) setHistory(next) try { localStorage.setItem(historyKey(), JSON.stringify(next)) } catch { /* Storage may be unavailable. */ } } const presetLabel = (item: (typeof presets)[number]) => item.unit === 'minutes' ? t('range.lastMinutes', { count: item.count }) : t('range.lastHours', { count: item.count }) const activePreset = selection.start === start && selection.end === end ? presets.find(item => item.ms === selection.ms) : undefined const label = activePreset ? presetLabel(activePreset) : t('range.custom') const rangeText = `${new Date(start).toLocaleString()} ~ ${new Date(end).toLocaleString()}` return
{open &&

{t('range.title')}

{presets.map(item => )}
{history.length > 0 &&

{t('range.recent')}

{history.map(item => )}
}
}
}