spb/countryatlas
Public
TypeScript 57%
Python 38.6%
JavaScript 3.6%
CSS 0.6%
1import type { Metadata } from 'next';2import { Suspense } from 'react';3import { t } from '@/i18n';4import { isNotBuilt, safe } from '@/lib/api';5import { apiExplore } from '@/lib/api-explore';6import { grouped } from '@/lib/format';7import { routes } from '@/lib/site';8import { TOPICS, isTopicId, topicById } from '@/lib/topics';9import type { IndicatorSummary } from '@/lib/types';10import { NotBuiltState } from '@/components/data/empty-state';11import { PageHeader } from '@/components/explore/page-header';12import { IndicatorDirectory } from '@/components/indicators/directory';1314export const revalidate = 900;1516type Search = Promise<{ topic?: string | string[] }>;1718export async function generateMetadata({ searchParams }: { searchParams: Search }): Promise<Metadata> {19 const sp = await searchParams;20 const topic = typeof sp.topic === 'string' && isTopicId(sp.topic) ? topicById(sp.topic) : null;21 const title = topic ? `${topic.name} — ${t('indicators.title')}` : t('indicators.title');22 return {23 title,24 description: topic ? topic.blurb : t('indicators.sub', { n: 260 }),25 alternates: { canonical: routes.indicators(topic?.id) },26 };27}2829export default async function IndicatorsPage({ searchParams }: { searchParams: Search }) {30 const sp = await searchParams;31 const initialTopic = typeof sp.topic === 'string' && isTopicId(sp.topic) ? sp.topic : null;3233 let items: IndicatorSummary[] = [];34 let notBuilt = false;35 try {36 items = (await apiExplore.indicators()).items;37 } catch (e) {38 if (isNotBuilt(e)) notBuilt = true;39 else throw e;40 }41 // Topic membership + order from the API (an indicator can belong to several topics).42 const perTopic = notBuilt ? [] : await Promise.all(TOPICS.map((tp) => safe(apiExplore.indicators({ topic: tp.id }))));43 const topicMembers: Record<string, string[]> = {};44 TOPICS.forEach((tp, i) => {45 const res = perTopic[i];46 if (res) topicMembers[tp.id] = res.items.map((it) => it.slug);47 });4849 return (50 <>51 <PageHeader title={t('indicators.title')} lede={t('indicators.sub', { n: grouped(items.length || 260) })} />52 {notBuilt ? (53 <NotBuiltState />54 ) : (55 <Suspense fallback={null}>56 <IndicatorDirectory items={items} topicMembers={topicMembers} initialTopic={initialTopic} />57 </Suspense>58 )}59 </>60 );61}62