import type { Metadata } from 'next' import { Suspense } from 'react' import { requirePermission } from '@/lib/auth/current' import { collectHealth, type ComponentState } from '@/lib/health/check' import { de } from '@/lib/i18n/de' import { formatVital, summarizeVitals } from '@/lib/dashboard/vitals' import { SkeletonLine } from '@/components/Skeleton' export const metadata: Metadata = { title: de.health.heading } export const dynamic = 'force-dynamic' const STATE_LABEL: Record = { up: de.health.ok, degraded: de.health.degraded, down: de.health.down, } async function SystemState() { const report = await collectHealth() return ( {Object.entries(report.components).map(([key, value]) => ( ))}
{de.health.checkedAt(new Date(report.checkedAt).toLocaleString('de-DE'))}
{de.health.service} {de.health.state}
{de.health.components[key] ?? key} {/* Zustand als Text, nicht nur als Farbe. */} {STATE_LABEL[value.status]} {value.detail ? ( {value.detail} ) : null}
) } export default async function SystemPage() { await requirePermission('admin') return (

{de.health.heading}

} >

{de.vitals.heading}

{de.vitals.intro}

{de.export.heading}

{de.export.databaseHint}

{de.export.database} {de.export.bundle}

) } /** * Die Ladewerte der letzten sieben Tage. Median und 75. Perzentil, kein * Mittelwert - ein Ausreisser auf einem alten Laptop soll die Zahl nicht * bestimmen. */ async function VitalsTable() { const { metriken, routen } = await summarizeVitals() if (metriken.length === 0) { return

{de.vitals.empty}

} return (
{/* Auf schmalen Schirmen scrollt die Tabelle in sich, statt die Seite breiter zu machen. Siehe docs/09-performance-und-ux.md. */}
{metriken.map((zeile) => ( ))}
{de.vitals.metric} {de.vitals.median} {de.vitals.p75} {de.vitals.count} {de.vitals.target}
{zeile.metric} {formatVital(zeile.metric, zeile.median)} {formatVital(zeile.metric, zeile.p75)} {zeile.count} {de.vitals.targets[zeile.metric] ?? ''}
{routen.length > 0 ? (

{de.vitals.worstRoutes}

{routen.map((zeile) => ( ))}
{zeile.route} {formatVital(zeile.metric, zeile.p75)} {zeile.count}
) : null}
) }