'use client';
import Link from 'next/link';
import { useMemo } from 'react';
import { t } from '@/i18n';
import { formatValue, grouped } from '@/lib/format';
import { routes } from '@/lib/site';
import type { FormatSpec } from '@/lib/types';
import type { PointCountry } from '@/lib/types-analytics';
import { Histogram } from '@/components/charts/histogram';
import { LineChart, type LineSeries } from '@/components/charts/line-chart';
import { RankedBars, type RankedBarRow } from '@/components/charts/ranked-bars';
import { histogramOf, median, wantsLog } from './geo';
export interface YearRow {
country: PointCountry;
value: number;
rank: number;
}
/** Rank view: the top N of the current year, plus the selected country pinned when outside the top. */
export function RankView({ rows, year, spec, selectedId, indicatorSlug, top = 25 }: { rows: YearRow[]; year: number; spec: FormatSpec; selectedId: string | null; indicatorSlug: string; top?: number }) {
const shown = rows.slice(0, top);
const sel = selectedId ? rows.find((r) => r.country.id === selectedId) : null;
if (sel && !shown.some((r) => r.country.id === sel.country.id)) shown.push(sel);
const bars: RankedBarRow[] = shown.map((r) => ({ id: r.country.id, label: r.country.name ?? r.country.id, flag: r.country.flag, href: r.country.slug ? routes.country(r.country.slug) : null, value: r.value, rank: r.rank }));
if (!rows.length) return
{t('explorer.noDataYear', { indicator: spec.name ?? '', year })}
;
return (
{t('explorer.rank.sub', { n: grouped(rows.length), year })}
{t('explorer.rank.full')} →
);
}
/** Trend view: world median (and the country count), plus the selected country's own series. */
export function TrendView({ years, values, spec, selected, subject }: { years: number[]; values: Record>; spec: FormatSpec; selected: { country: PointCountry; series: Array } | null; subject: string }) {
const series: LineSeries[] = useMemo(() => {
const med = years.map((y, i) => ({ period: `${y}-01-01`, year: y, value: median(Object.values(values).map((arr) => arr[i])) }));
const out: LineSeries[] = [{ id: 'median', name: t('explorer.trend.median'), points: med.filter((p) => p.value != null), colorIndex: 0 }];
if (selected) out.push({ id: selected.country.id, name: selected.country.name ?? selected.country.id, points: years.map((y, i) => ({ period: `${y}-01-01`, year: y, value: selected.series[i] ?? null })).filter((p) => p.value != null), colorIndex: 1 });
return out;
}, [years, values, selected]);
const counts = years.map((_, i) => Object.values(values).filter((arr) => arr[i] != null).length);
return (
{t('explorer.trend.note')}
);
}
/** Distribution view: histogram of the current year with world median and selected country markers. */
export function DistributionView({ rows, year, spec, selected }: { rows: YearRow[]; year: number; spec: FormatSpec; selected: { country: PointCountry; value: number | null } | null }) {
const vals = rows.map((r) => r.value);
const log = wantsLog(spec, vals);
const h = useMemo(() => histogramOf(vals, 20, log), [vals, log]);
const med = median(vals);
const markers = [
...(med != null ? [{ id: 'median', label: t('explorer.trend.median'), value: med, tone: 'ink' as const }] : []),
...(selected && selected.value != null ? [{ id: selected.country.id, label: selected.country.name ?? selected.country.id, value: selected.value, tone: 'accent' as const }] : []),
];
if (!rows.length) return {t('explorer.noDataYear', { indicator: spec.name ?? '', year })}
;
return (
);
}