SPB Git forge

spb/countryatlas

Public
20commits 1branches 0releases
268.3 MBsize
maindefault branch
12 days agolast push
TypeScript 57% Python 38.6% JavaScript 3.6% CSS 0.6%
3.2 KB · 51 lines tsx
Raw Blame History
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