"use client"; type Props = { minYear: number; maxYear: number; windowStartYear: number; windowEndYear: number; onWindowStartYearChange: (year: number) => void; onWindowEndYearChange: (year: number) => void; year: number; onYearChange: (year: number) => void; isLoading: boolean; disabled: boolean; statusText?: string | null; }; export default function TimelineBar({ minYear, maxYear, windowStartYear, windowEndYear, onWindowStartYearChange, onWindowEndYearChange, year, onYearChange, isLoading, disabled, statusText, }: Props) { const lower = Math.min(minYear, maxYear); const upper = Math.max(minYear, maxYear); const globalLocked = lower === upper; const effectiveDisabled = disabled || globalLocked; const safeWindowStart = clampYear(windowStartYear, lower, upper); const safeWindowEnd = clampYear(windowEndYear, safeWindowStart, upper); const windowLocked = safeWindowStart === safeWindowEnd; const safeYear = clampYear(year, safeWindowStart, safeWindowEnd); const pointDisabled = effectiveDisabled || windowLocked; const windowStartPercent = toPercent(safeWindowStart, lower, upper); const windowEndPercent = toPercent(safeWindowEnd, lower, upper); const helperText = isLoading ? "Đang tải geometry theo mốc thời gian..." : statusText || (windowLocked ? "Khoảng lớn đang thu về một mốc duy nhất." : "Kéo mốc nhỏ để query trong khoảng lớn."); return (
Timeline {formatYear(safeYear)}
Khoảng thời gian lớn
onWindowStartYearChange( Math.min(Number(event.target.value), safeWindowEnd) ) } disabled={effectiveDisabled} aria-label="Timeline window start" /> onWindowEndYearChange( Math.max(Number(event.target.value), safeWindowStart) ) } disabled={effectiveDisabled} aria-label="Timeline window end" />
{formatYear(safeWindowStart)} {formatYear(safeWindowEnd)}
Mốc thời gian chi tiết
onYearChange(Number(event.target.value))} disabled={pointDisabled} aria-label="Timeline year" style={{ width: "100%", accentColor: "#22c55e", cursor: pointDisabled ? "not-allowed" : "pointer", opacity: pointDisabled ? 0.6 : 1, }} />
{formatYear(safeWindowStart)} {helperText} {formatYear(safeWindowEnd)}
); } function clampYear(year: number, minYear: number, maxYear: number): number { if (year < minYear) return minYear; if (year > maxYear) return maxYear; return year; } function formatYear(year: number): string { if (year < 0) { return `${Math.abs(year)} TCN`; } return `${year}`; } function toPercent(value: number, minValue: number, maxValue: number): number { if (maxValue <= minValue) return 0; return ((value - minValue) / (maxValue - minValue)) * 100; }