import { useState } from 'react'; import type { RefObject } from 'react'; import { useRef } from 'react'; import { CalendarDays, CalendarClock, Check, ChevronDown, Clock3, DatabaseZap, Search } from 'lucide-react'; import type { CurrentItem } from '../../../entities/current/types'; import { HistoryChart } from '../../../features/history-chart/HistoryChart'; import { RANGE_PRESETS, createRange, type DateRangeState } from '../../../features/history/dateRange'; import { toIsoFromInput } from '../../../utils/format'; import type { HistoryGranularity } from '../../../utils/historyGranularity'; type ArchiveViewProps = { edgeId: string; getTagLabel: (tag: string) => string; historyAxis: HistoryGranularity; historyGranulate?: string; items: CurrentItem[]; range: DateRangeState; search: string; selectedTags: string[]; tagLabels: Record; onClearTags: () => void; onClearVisibleTags: () => void; onRangeChange: (value: DateRangeState) => void; onSearchChange: (value: string) => void; onSelectFirstTags: () => void; onSelectVisibleTags: () => void; onToggleTag: (tag: string) => void; }; type RangePart = 'from' | 'to'; type RangeInputPart = 'date' | 'time'; function getRangeInputPart(value: string, part: RangeInputPart): string { const [date = '', time = ''] = value.split('T'); return part === 'date' ? date : time; } function updateRangeInputPart(value: string, part: RangeInputPart, nextValue: string): string { const date = getRangeInputPart(value, 'date'); const time = getRangeInputPart(value, 'time'); return part === 'date' ? `${nextValue}T${time}` : `${date}T${nextValue}`; } function openInputPicker(input: HTMLInputElement | null): void { input?.focus(); input?.showPicker?.(); } type DateRangeFieldProps = { icon: 'date' | 'time'; inputRef: RefObject; type: 'date' | 'time'; value: string; onChange: (value: string) => void; }; function DateRangeField({ icon, inputRef, type, value, onChange }: DateRangeFieldProps) { const Icon = icon === 'date' ? CalendarDays : Clock3; const label = icon === 'date' ? 'Открыть календарь' : 'Открыть выбор времени'; return (
openInputPicker(inputRef.current)}> onChange(event.target.value)} />
); } export function ArchiveView({ edgeId, getTagLabel, historyAxis, historyGranulate, items, range, search, selectedTags, tagLabels, onClearTags, onClearVisibleTags, onRangeChange, onSearchChange, onSelectFirstTags, onSelectVisibleTags, onToggleTag, }: ArchiveViewProps) { const [selectorOpen, setSelectorOpen] = useState(false); const selectedPreview = selectedTags.slice(0, 10); const hiddenSelectedCount = Math.max(0, selectedTags.length - selectedPreview.length); const fromDateRef = useRef(null); const fromTimeRef = useRef(null); const toDateRef = useRef(null); const toTimeRef = useRef(null); const fromIso = toIsoFromInput(range.from) as string; const toIso = toIsoFromInput(range.to) as string; const updateRangePart = (rangePart: RangePart, inputPart: RangeInputPart, value: string) => { onRangeChange({ ...range, [rangePart]: updateRangeInputPart(range[rangePart], inputPart, value), }); }; return (
История

График параметров

cloud-v3 · {historyGranulate ?? 'ожидание'}
{selectorOpen ? (
{selectedPreview.length ? ( selectedPreview.map((tag) => {getTagLabel(tag)}) ) : ( Не выбрано )} {hiddenSelectedCount > 0 ? +{hiddenSelectedCount} : null}
{items.map((item) => { const selected = selectedTags.includes(item.tag); const label = getTagLabel(item.tag); return ( ); })}
) : null}
setSelectorOpen(false)} onPointerDown={() => setSelectorOpen(false)} onPointerEnter={() => setSelectorOpen(false)} >
{RANGE_PRESETS.map((preset) => ( ))}
С updateRangePart('from', 'date', value)} /> updateRangePart('from', 'time', value)} />
По updateRangePart('to', 'date', value)} /> updateRangePart('to', 'time', value)} />
{selectedTags.length ? ( ) : (
Разверните список показателей и выберите серию для графика
)}
); }