'use client'; import { ArrowDown, ArrowUp } from 'lucide-react'; import Link from 'next/link'; import { useMemo, useState } from 'react'; import { t } from '@/i18n'; import { cn } from '@/lib/cn'; import { formatValue, isNum } from '@/lib/format'; import { routes } from '@/lib/site'; import type { IndicatorCard } from '@/lib/types'; import type { RegionMember } from '@/lib/types-explore'; /** * Sortable members table (flag, name + up to 5 headline values). Table on sm+, list rows on phones (each row * shows the country and the first three values). Sorting is client-side; default = population desc. */ export function MembersTable({ members, indicators }: { members: RegionMember[]; indicators: IndicatorCard[] }) { const cols = indicators.slice(0, 5); const [sort, setSort] = useState<{ key: string; dir: 'asc' | 'desc' }>({ key: cols[0]?.slug ?? 'name', dir: 'desc' }); const rows = useMemo(() => { const copy = [...members]; const num = (m: RegionMember, k: string) => { const v = m.values[k]?.value; return isNum(v) ? v : null; }; copy.sort((a, b) => { if (sort.key === 'name') return (sort.dir === 'asc' ? 1 : -1) * (a.name ?? '').localeCompare(b.name ?? ''); const va = num(a, sort.key); const vb = num(b, sort.key); if (va == null && vb == null) return (a.name ?? '').localeCompare(b.name ?? ''); if (va == null) return 1; if (vb == null) return -1; return sort.dir === 'asc' ? va - vb : vb - va; }); return copy; }, [members, sort]); const toggle = (key: string) => setSort((s) => (s.key === key ? { key, dir: s.dir === 'asc' ? 'desc' : 'asc' } : { key, dir: key === 'name' ? 'asc' : 'desc' })); const Th = ({ k, label, numeric }: { k: string; label: string; numeric?: boolean }) => { const active = sort.key === k; return (
| {cols.map((c) => ( | ))} |
|---|---|
| {m.flag} {m.name} | {cols.map((c) => { const v = m.values[c.slug]; return ({v && isNum(v.value) ? ( <> {formatValue(v.value, c)} {v.year ? {v.year} : null} > ) : ( {t('region.members.noValue')} )} | ); })}