import Link from 'next/link'; import { t } from '@/i18n'; import { adminApi, adminErrorMessage } from '@/lib/admin-api'; import { ApiError } from '@/lib/api'; import { grouped } from '@/lib/format'; import { routes } from '@/lib/site'; import type { AdminOverview } from '@/lib/types-explore'; import { AdminSection, AdminTable, Kv, Pill, bytes, statusTone, ts } from '@/components/admin/admin-ui'; import { clearCacheAction, refreshAction } from '../actions'; export const dynamic = 'force-dynamic'; function hb(o: AdminOverview, key: string): string | null { const h = o.scheduler.heartbeat; if (!h) return null; const v = h[key]; return v == null ? null : String(v); } export default async function AdminOverviewPage({ searchParams }: { searchParams: Promise<{ ok?: string; err?: string }> }) { const sp = await searchParams; let o: AdminOverview | null = null; let error: string | null = null; try { o = await adminApi.overview(); } catch (e) { error = e instanceof ApiError ? t('admin.unavailable', { status: e.status || 'network' }) + ` ${adminErrorMessage(e)}` : adminErrorMessage(e); } const actions = ( <>
); return ( <> {sp.ok ?

{t('admin.actions.done', { msg: sp.ok })}

: null} {sp.err ?

{t('admin.actions.failed', { msg: sp.err })}

: null} {error ?

{error}

: null} {o ? ( <>

{t('admin.snapshot')}

{o.status}], ['run_id', o.meta?.run_id ?? null], ['built_at', ts(o.meta?.built_at ?? null)], ['schema', o.meta?.schema_version != null ? String(o.meta.schema_version) : null], ['build_duration_s', o.meta?.build_duration_s != null ? String(o.meta.build_duration_s) : null], ]} />

{t('admin.db')}

{t('admin.scheduler')}

{t('admin.scheduler.alive', { pid: o.scheduler.pid })} : {t('admin.scheduler.dead', { pid: o.scheduler.pid })}], [t('admin.scheduler.last'), ts(hb(o, 'last_run_at') ?? hb(o, 'last_run') ?? hb(o, 'finished_at'))], [t('admin.scheduler.next'), ts(hb(o, 'next_run_at') ?? hb(o, 'next_run'))], ['heartbeat', ts(hb(o, 'heartbeat_at') ?? hb(o, 'updated_at') ?? hb(o, 'at'))], ['refresh', t('admin.scheduler.refreshAt', { time: o.settings.refresh_at })], ]} />
[k, grouped(v)] as [string, string])} /> [k, grouped(v)] as [string, string])} /> [k, String(v)] as [string, string])} />
r.connector} columns={[ { key: 'c', header: t('admin.connectors.connector'), cell: (r) => {r.connector} }, { key: 'n', header: t('admin.connectors.runs'), numeric: true, cell: (r) => grouped(r.n_runs) }, { key: 'last', header: t('admin.connectors.last'), cell: (r) => ts(r.last_finished_at) }, { key: 's', header: t('admin.connectors.status'), cell: (r) => {r.last_status ?? t('admin.na')} }, { key: 'ok', header: t('admin.connectors.ok'), numeric: true, cell: (r) => grouped(r.n_ok) }, { key: 'f', header: t('admin.connectors.failed'), numeric: true, cell: (r) => (r.n_failed ? {grouped(r.n_failed)} : '0') }, { key: 'rows', header: t('admin.connectors.rows'), numeric: true, cell: (r) => (r.rows_valid != null ? grouped(r.rows_valid) : t('admin.na')) }, { key: 'w', header: t('admin.connectors.warnings'), numeric: true, cell: (r) => (r.warnings != null ? grouped(r.warnings) : t('admin.na')) }, { key: 'e', header: t('admin.connectors.errors'), numeric: true, cell: (r) => (r.errors ? {grouped(r.errors)} : '0') }, ]} /> r.source_id} columns={[ { key: 's', header: t('admin.stale.source'), cell: (r) => {r.source_id} }, { key: 'n', header: t('admin.stale.observations'), numeric: true, cell: (r) => grouped(r.n_observations) }, { key: 'u', header: t('admin.stale.updated'), cell: (r) => ts(r.source_updated_at) }, { key: 'r', header: t('admin.stale.retrieved'), cell: (r) => ts(r.retrieved_at) }, { key: 'st', header: t('admin.stale.n'), numeric: true, cell: (r) => (r.n_stale ? {grouped(r.n_stale)} : '0') }, ]} /> ) : !error ? (

{t('admin.empty')}

) : null} ); }