import { t } from '@/i18n'; import { fixed, isNum } from '@/lib/format'; import { seriesVar } from './palette'; /** * Age structure as a single stacked bar (0–14 / 15–64 / 65+ shares, % of population). Ordinal colouring * (one hue, three lightness steps via the sequential ramp) because the categories are ordered. * A 2 px surface gap separates segments; labels inside only when the segment is wide enough. */ export function PopulationPyramid({ shares, name, year, className, }: { shares: { young: number | null; working: number | null; old: number | null }; name: string; year?: number | null; className?: string; }) { const parts = [ { key: 'young', label: '0–14', value: shares.young, color: 'var(--seq-2)' }, { key: 'working', label: '15–64', value: shares.working, color: 'var(--seq-4)' }, { key: 'old', label: '65+', value: shares.old, color: 'var(--seq-6)' }, ]; const valid = parts.filter((p) => isNum(p.value)); if (valid.length === 0) return

{t('chart.noData')}

; const total = valid.reduce((a, p) => a + (p.value as number), 0) || 100; const summary = t('chart.summary.pyramid', { name, parts: valid.map((p) => `${p.label}: ${fixed(p.value as number, 1)} %`).join(', ') }); return (
{valid.map((p) => { const pct = ((p.value as number) / total) * 100; return (
{pct > 14 ? ( {fixed(p.value as number, 0)} % ) : null}
); })}
{valid.map((p) => ( {p.label} {fixed(p.value as number, 1)} % ))} {year ? {year} : null}
{seriesVar(0) ? null : null}
); }