Merge branch 'fix/timetravel-future-window' into 'main'

fix(timetravel): extend slider max до now + 30 days (или future marks)

See merge request 2-6/2-6-4/terravault/ordinis!220
This commit is contained in:
Александр Зимин
2026-05-15 17:03:00 +00:00
@@ -39,14 +39,32 @@ export function TimeTravelPicker({
return Number.isNaN(d.getTime()) ? undefined : d
}, [value])
// Range: from min(marks, value) padding до now + padding.
// Range: from min(marks, value) padding до max(now, future marks) + padding.
//
// Future support: если у dict'а есть records с validFrom > now (scheduled),
// или user navigated к future date (asOf=18.05 для preview new record),
// slider должен дотягиваться до этой даты. Раньше max = now + 1day pad —
// scheduled records на дату дальше 1 день были недоступны через slider
// (user не мог время-travel'ить чтобы их увидеть).
//
// Default future window = 30 days, чтобы планирование на месяц вперёд
// (типичный business horizon для NSI updates) было без ручного URL hack.
const range = useMemo(() => {
const now = Date.now()
let minMark = marks.length > 0 ? Math.min(...marks) : now - 365 * 86_400_000
if (valueDate) minMark = Math.min(minMark, valueDate.getTime())
const span = now - minMark
const pad = Math.max(span * 0.05, 86_400_000) // ≥1 день
return { min: minMark - pad, max: now + pad }
const DAY_MS = 86_400_000
const FUTURE_WINDOW_MS = 30 * DAY_MS
let minMark = marks.length > 0 ? Math.min(...marks) : now - 365 * DAY_MS
let maxMark = marks.length > 0 ? Math.max(...marks) : now
if (valueDate) {
minMark = Math.min(minMark, valueDate.getTime())
maxMark = Math.max(maxMark, valueDate.getTime())
}
// Push max forward: at least now + 30 days, и further если есть будущие marks.
const effectiveMax = Math.max(maxMark, now + FUTURE_WINDOW_MS)
const span = effectiveMax - minMark
const pad = Math.max(span * 0.05, DAY_MS) // ≥1 день
return { min: minMark - pad, max: effectiveMax + pad }
}, [marks, valueDate])
return (