import type { Metadata } from 'next'; import Link from 'next/link'; import { t, tOpt } from '@/i18n'; import { isNotBuilt, safe } from '@/lib/api'; import { apiAnalytics } from '@/lib/api-analytics'; import { apiExplore } from '@/lib/api-explore'; import { fixed, formatValue, grouped } from '@/lib/format'; import { routes } from '@/lib/site'; import type { RegionCompareResponse } from '@/lib/types-analytics'; import { NotBuiltState } from '@/components/data/empty-state'; import { Section } from '@/components/data/section'; import { PageHeader } from '@/components/explore/page-header'; import { GroupComparePicker } from '@/components/regions/group-compare-picker'; import { GroupHistory } from '@/components/regions/group-history'; export const revalidate = 900; type SP = Record; function slugOf(v: string | string[] | undefined, fallback: string): string { const s = (Array.isArray(v) ? v[0] : v) ?? ''; return /^[a-z0-9][a-z0-9-]*$/.test(s) ? s : fallback; } export async function generateMetadata({ searchParams }: { searchParams: Promise }): Promise { const sp = await searchParams; const a = slugOf(sp.a, 'g7'); const b = slugOf(sp.b, 'brics'); const data = await safe(apiAnalytics.regionsCompare(a, b)); const names = data ? data.groups.map((g) => g.name ?? g.id) : [a, b]; const title = t('regions.compare.title', { a: names[0] ?? a, b: names[1] ?? b }); const canonical = routes.regionCompare(a, b); return { title, description: t('regions.compare.description', { a: names[0] ?? a, b: names[1] ?? b }), alternates: { canonical }, robots: a === 'g7' && b === 'brics' ? undefined : { index: false, follow: true } }; } export default async function RegionsComparePage({ searchParams }: { searchParams: Promise }) { const sp = await searchParams; const a = slugOf(sp.a, 'g7'); const b = slugOf(sp.b, 'brics'); let data: RegionCompareResponse | null = null; try { data = await apiAnalytics.regionsCompare(a, b); } catch (e) { if (isNotBuilt(e)) return ; data = null; } const regions = await safe(apiExplore.regions()); const groups = regions?.items ?? []; const names: Record = data ? Object.fromEntries(data.groups.map((g) => [g.id, g.name ?? g.id])) : {}; const ids = data ? data.groups.map((g) => g.id) : []; return ( <>
{!data ? (

{t('regions.compare.unavailable')}

) : ( <>
{(['population_share_pct', 'gdp_share_pct'] as const).map((k) => (
{k === 'gdp_share_pct' ? t('regions.compare.gdpShare') : t('regions.compare.popShare')}
    {data.groups.map((g, i) => { const v = data.shares[g.id]?.[k] ?? null; return (
  1. {g.name} {v != null ? `${fixed(v, 1)} %` : t('common.na')}
  2. ); })}
))}
{data.groups.map((g, i) => ( ))} {data.rows.map((r) => ( {data.groups.map((g) => { const v = r.values[g.id]; return ( ); })} ))}
{t('regions.compare.table')}
{t('common.indicator')} {g.name}
{r.indicator.short_name ?? r.indicator.name} {tOpt(`regions.${r.kind}`, r.kind)} ยท {r.indicator.unit} {v ? formatValue(v.value, r.indicator) : t('common.na')} {v ? {t('region.aggregates.n', { n: grouped(v.n ?? 0), year: v.year ?? '' })} : null}
)} ); }