import type { TemporalObservation } from '../../types' interface TemporalTrendChartProps { timeline: TemporalObservation[] metricKey: string } const WIDTH = 560 const HEIGHT = 150 const PADDING_X = 34 const PADDING_Y = 24 function formatValue(value: number, unit: string): string { const maximumFractionDigits = unit === 'inwoners' || unit === 'objecten' ? 0 : 2 return `${value.toLocaleString('nl-BE', { maximumFractionDigits })} ${unit}` } export function TemporalTrendChart({ timeline, metricKey }: TemporalTrendChartProps): JSX.Element | null { const observations = timeline.flatMap((observation) => { const metric = observation.metrics.find((item) => item.metric_key === metricKey) return metric ? [{ observation, metric }] : [] }) if (observations.length < 2) { return null } const values = observations.map((item) => item.metric.value) const minimum = Math.min(...values) const maximum = Math.max(...values) const range = maximum - minimum const innerWidth = WIDTH - PADDING_X * 2 const innerHeight = HEIGHT - PADDING_Y * 2 const points = observations.map((item, index) => { const x = PADDING_X + (index / (observations.length - 1)) * innerWidth const normalized = range === 0 ? 0.5 : (item.metric.value - minimum) / range const y = HEIGHT - PADDING_Y - normalized * innerHeight return { ...item, x, y } }) const pointString = points.map((point) => `${point.x},${point.y}`).join(' ') const label = `${points[0].metric.label}: ${formatValue(points[0].metric.value, points[0].metric.unit)} tot ${formatValue( points[points.length - 1].metric.value, points[points.length - 1].metric.unit, )}` return (
Volledige tijdreeks {points[0].metric.label}
{points.length} meetmomenten
{points.map((point) => ( {new Date(point.observation.dataset.observed_at).getUTCFullYear()} ))}
{points.map((point) => (
{new Date(point.observation.dataset.observed_at).getUTCFullYear()} {formatValue(point.metric.value, point.metric.unit)}
))}
) }