'use client'; import { ChevronRight, Search, X } from 'lucide-react'; import Link from 'next/link'; import { useMemo, useState } from 'react'; import { t } from '@/i18n'; import { grouped } from '@/lib/format'; import { routes } from '@/lib/site'; import { TOPICS } from '@/lib/topics'; import type { RankingRow } from '@/lib/types'; import type { RankableIndicator } from '@/lib/types-compare'; import { Top3Preview } from './top3-preview'; /** * /rankings directory: featured first, then every rankable indicator grouped by topic. Each entry shows * "n countries · year" and a top-3 preview. The search box filters client-side on name / unit / topic. */ export function RankingsDirectory({ items, previews }: { items: RankableIndicator[]; previews: Record }) { const [q, setQ] = useState(''); const ql = q.trim().toLowerCase(); const filtered = useMemo(() => (ql ? items.filter((i) => (i.name ?? '').toLowerCase().includes(ql) || (i.short_name ?? '').toLowerCase().includes(ql) || (i.unit ?? '').toLowerCase().includes(ql) || (i.topic ?? '').includes(ql) || (i.subtopic ?? '').toLowerCase().includes(ql)) : items), [items, ql]); const featured = filtered.filter((i) => i.featured); const byTopic = TOPICS.map((tp) => ({ tp, items: filtered.filter((i) => i.topic === tp.id).sort((a, b) => Number(!!b.featured) - Number(!!a.featured) || (a.name ?? '').localeCompare(b.name ?? '')) })).filter((g) => g.items.length); const other = filtered.filter((i) => !TOPICS.some((tp) => tp.id === i.topic)); return (
setQ(e.target.value)} placeholder={t('rankings.search')} aria-label={t('rankings.search')} className="h-11 w-full rounded-sm border border-rule bg-surface pl-9 pr-9 text-sm text-ink outline-none placeholder:text-ink-3 focus:border-accent md:h-10" /> {q ? ( ) : null}
{ql ? t('rankings.countOf', { n: grouped(filtered.length), total: grouped(items.length) }) : t('rankings.count', { n: grouped(items.length) })}
{filtered.length === 0 ?

{t('rankings.noMatch', { q })}

: null} {featured.length && !ql ? (

{t('rankings.featured.sub')}

    {featured.map((i) => ( ))}
) : null} {byTopic.map(({ tp, items: rows }) => (

{tp.name}

{t('rankings.count', { n: rows.length })}
    {rows.map((i) => ( ))}
))} {other.length ? (
    {other.map((i) => ( ))}
) : null}
); } function Entry({ item, preview }: { item: RankableIndicator; preview: RankingRow[] | null | undefined }) { const name = item.name ?? item.slug; return (
  • {name} {t('rankings.meta', { n: grouped(item.ranking_n ?? item.n_countries ?? 0), year: item.ranking_year ?? item.last_year ?? '' })} {item.unit ? ` · ${item.unit}` : ''}
  • ); }