import dayjs from 'dayjs' import { getPropertyValue } from '../../../database/ObjectModels' const toTimestamp = (value) => { if (value == null || value === '') return null const date = dayjs(value) return date.isValid() ? date.valueOf() : null } export const getTimelineDates = (values = []) => { const timestamps = [] for (const value of values) { const timestamp = toTimestamp(value) if (timestamp != null) timestamps.push(timestamp) } return timestamps } export const getTimelineRangeFromValues = (startValues = [], endValues = []) => { const timestamps = [ ...getTimelineDates(startValues), ...getTimelineDates(endValues) ] if (timestamps.length === 0) return null const minimum = Math.min(...timestamps) const maximum = Math.max(...timestamps) const start = dayjs(minimum).startOf('day').subtract(1, 'day') const end = dayjs(maximum).startOf('day').add(2, 'day') return { start: start.valueOf(), end: end.valueOf() } } export const getTimelineRange = (records, startDate, endDate) => { const startValues = [] const endValues = [] records.forEach((record) => { if (record?.isSkeleton) return if (startDate) startValues.push(getPropertyValue(record, startDate)) if (endDate) endValues.push(getPropertyValue(record, endDate)) }) return getTimelineRangeFromValues(startValues, endValues) } export const getTimelineTicks = (rangeStart, rangeEnd) => { if (rangeStart == null || rangeEnd == null) return [] const start = dayjs(rangeStart).startOf('day') const end = dayjs(rangeEnd).startOf('day') const dayCount = Math.max(1, end.diff(start, 'day')) const lastDay = end.subtract(1, 'day') const includeYear = start.year() !== lastDay.year() || start.year() !== end.year() const format = includeYear ? 'MMM D YYYY' : 'MMM D' return Array.from({ length: dayCount + 1 }, (_, index) => { const value = start.add(index, 'day') return { value: value.valueOf(), label: value.format(format) } }) } export const getTimelineItemPosition = ( startValue, endValue, rangeStart, rangeEnd ) => { if (startValue == null || startValue === '') return null const start = dayjs(startValue) const rangeStartMs = dayjs(rangeStart).valueOf() const rangeEndMs = dayjs(rangeEnd).valueOf() const duration = rangeEndMs - rangeStartMs if (!start.isValid() || duration <= 0) return null const startMs = Math.min(rangeEndMs, Math.max(rangeStartMs, start.valueOf())) const end = endValue == null || endValue === '' ? null : dayjs(endValue) const hasValidEnd = end?.isValid() && end.valueOf() > startMs const endMs = hasValidEnd ? Math.min(rangeEndMs, Math.max(startMs, end.valueOf())) : startMs return { left: ((startMs - rangeStartMs) / duration) * 100, width: ((endMs - startMs) / duration) * 100, isPoint: !hasValidEnd } }