spb/countryatlas
Public
TypeScript 57%
Python 38.6%
JavaScript 3.6%
CSS 0.6%
1import type { Metadata } from 'next';2import { t } from '@/i18n';3import { isNotBuilt, safe } from '@/lib/api';4import { apiAnalytics } from '@/lib/api-analytics';5import { apiExplore } from '@/lib/api-explore';6import { routes } from '@/lib/site';7import { NotBuiltState } from '@/components/data/empty-state';8import { DEFAULT_TRAJ, explorerIndicators, firstParam, parseYearParam, slugParam, type SP } from '@/components/explorer/options';9import { ScatterView } from '@/components/explorer/scatter-view';1011export const revalidate = 900;1213function parseState(sp: SP) {14 const log = (firstParam(sp, 'log') ?? '').toLowerCase();15 const country = (firstParam(sp, 'country') ?? '').toLowerCase();16 return {17 x: slugParam(firstParam(sp, 'x'), DEFAULT_TRAJ.x)!,18 y: slugParam(firstParam(sp, 'y'), DEFAULT_TRAJ.y)!,19 size: slugParam(firstParam(sp, 'size'), DEFAULT_TRAJ.size)!,20 year: parseYearParam(firstParam(sp, 'year')),21 group: slugParam(firstParam(sp, 'group'), 'world')!,22 log: /^(x|y|x,y|y,x|none)$/.test(log) ? log : null,23 fit: firstParam(sp, 'fit') === '1',24 country: /^[a-z]{3}$/.test(country) ? country : null,25 };26}2728export async function generateMetadata({ searchParams }: { searchParams: Promise<SP> }): Promise<Metadata> {29 const sp = await searchParams;30 return {31 title: t('scatter.metaTitle'),32 description: t('scatter.description'),33 alternates: { canonical: routes.scatter() },34 robots: Object.keys(sp).length ? { index: false, follow: true } : undefined,35 openGraph: { title: `${t('scatter.metaTitle')} — ${t('site.name')}`, description: t('scatter.description'), url: routes.scatter(), type: 'website' },36 };37}3839export default async function ScatterPage({ searchParams }: { searchParams: Promise<SP> }) {40 const state = parseState(await searchParams);41 let indicatorsRes;42 try {43 indicatorsRes = await apiExplore.indicators({ with_data: true });44 } catch (e) {45 if (isNotBuilt(e)) return <NotBuiltState />;46 throw e;47 }48 const logX = state.log == null ? null : state.log.includes('x');49 const logY = state.log == null ? null : state.log.includes('y');50 const [groupsRes, scatter, related] = await Promise.all([51 safe(apiExplore.regions()),52 safe(apiAnalytics.scatter({ x: state.x, y: state.y, size: state.size, year: state.year, group: state.group !== 'world' ? state.group : null, log_x: logX == null ? null : String(logX), log_y: logY == null ? null : String(logY) })),53 safe(apiAnalytics.indicatorRelated(state.x, { limit: 8 })),54 ]);55 return <ScatterView indicators={explorerIndicators(indicatorsRes.items)} groups={groupsRes?.items ?? []} initial={scatter} initialRelated={related} initialState={state} />;56}57