spb/countryatlas
Public
TypeScript 57%
Python 38.6%
JavaScript 3.6%
CSS 0.6%
1import Link from 'next/link';2import { t } from '@/i18n';3import { cn } from '@/lib/cn';4import { fixed, grouped } from '@/lib/format';5import { routes } from '@/lib/site';6import { topicById } from '@/lib/topics';7import type { RelatedResponse } from '@/lib/types-analytics';89/** Statistically related indicators: ρ, r, N, year, direction; each row opens the scatter of the pair. */10export function RelatedTable({ data, slug }: { data: RelatedResponse; slug: string }) {11 if (!data.items.length) return <p className="text-sm text-ink-3">{t('indicator.related.noneStat')}</p>;12 return (13 <div className="min-w-0">14 <ul className="divide-y divide-rule border-y border-rule">15 {data.items.map((it) => {16 const rho = it.spearman ?? it.pearson ?? 0;17 const w = Math.min(100, Math.abs(rho) * 100);18 return (19 <li key={it.indicator.slug} className="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-4 gap-y-1 py-2 md:grid-cols-[minmax(0,16rem)_minmax(6rem,1fr)_4rem_4rem_4rem_3.5rem_5rem]">20 <Link href={routes.scatter({ x: slug, y: it.indicator.slug, year: it.year })} className="link-quiet min-w-0">21 <span className="block truncate text-sm font-medium text-ink">{it.indicator.short_name ?? it.indicator.name}</span>22 <span className="block truncate text-2xs text-ink-3">{topicById(it.indicator.topic ?? '')?.short ?? it.indicator.topic}</span>23 </Link>24 <div className="col-span-full flex items-center gap-2 md:col-span-1" aria-hidden>25 <span className="tnum w-8 text-right text-2xs text-ink-3">−1</span>26 <span className="relative h-1.5 min-w-0 flex-1 rounded-xs bg-surface-2">27 <span className="absolute inset-y-0 left-1/2 w-px bg-rule-strong" />28 <span className={cn('absolute inset-y-0 rounded-xs', rho >= 0 ? 'bg-inc' : 'bg-dec')} style={rho >= 0 ? { left: '50%', width: `${w / 2}%` } : { right: '50%', width: `${w / 2}%` }} />29 </span>30 <span className="tnum w-8 text-2xs text-ink-3">+1</span>31 </div>32 <span className="tnum text-right text-sm font-medium text-ink" title={t('scatter.stats.spearman')}>33 {it.spearman != null ? fixed(it.spearman, 2) : t('common.na')}34 </span>35 <span className="tnum hidden text-right text-xs text-ink-2 md:block" title={t('scatter.stats.pearson')}>36 r {it.pearson != null ? fixed(it.pearson, 2) : t('common.na')}37 </span>38 <span className="tnum hidden text-right text-xs text-ink-3 md:block">n {grouped(it.n)}</span>39 <span className="tnum hidden text-right text-xs text-ink-3 md:block">{it.year ?? ''}</span>40 <span className={cn('hidden text-right text-2xs uppercase tracking-wide md:block', it.direction === 'positive' ? 'text-inc' : 'text-dec')}>{t(`indicator.related.${it.direction}` as 'indicator.related.positive')}</span>41 </li>42 );43 })}44 </ul>45 <p className="mt-2 text-xs text-ink-3">46 {t('indicator.related.method', { year: data.year_used ?? '', n: grouped(data.n_candidates) })} <strong className="font-medium text-ink-2">{data.note}</strong>47 </p>48 </div>49 );50}51