import { Inbox } from "lucide-react"; import type { Metadata } from "next"; import Link from "next/link"; import type { ReactNode } from "react"; import { BenachrichtigungFormular } from "@/components/einstellungen/BenachrichtigungFormular"; import { Badge } from "@/components/ui/Badge"; import { Karte } from "@/components/ui/Karte"; import { Leerzustand } from "@/components/ui/Leerzustand"; import { MonoKopieren } from "@/components/ui/MonoKopieren"; import { Seitenkopf } from "@/components/ui/Seitenkopf"; import { Tabelle, TabellenZeile, TabellenZelle } from "@/components/ui/Tabelle"; import { datumZeit } from "@/lib/format"; import { darf } from "@/server/auth/rechte"; import { sitzungErforderlich } from "@/server/auth/sitzungspflicht"; import { einstellungenSeite, type Zeitplan, type ZustellungZeile } from "@/server/queries/einstellungen"; export const metadata: Metadata = { title: "Einstellungen" }; function Info({ titel, children }: { titel: string; children: ReactNode }) { return (
{titel}
{children}
); } function Abschnitt({ titel, id, children }: { titel: string; id: string; children: ReactNode }) { return (

{titel}

{children}
); } function ZeitplanAnzeige({ plan }: { plan: Zeitplan }) { return ( {plan.beschreibung && {plan.beschreibung}} {plan.ausdruck} ); } const KANAL_TEXT = { EMAIL: "E-Mail", WEBHOOK: "Webhook" } as const; function Zustellungen({ zeilen }: { zeilen: readonly ZustellungZeile[] }) { if (zeilen.length === 0) { return ( } titel="Noch nichts versendet" text="Hier erscheinen die letzten Zustellungen samt Ergebnis – auch Testnachrichten." /> ); } return ( {zeilen.map((z) => ( {KANAL_TEXT[z.kanal]} {z.betreff} {z.anlaesse === 1 ? "1 Anlass" : `${z.anlaesse} Anlässe`} {z.versuche > 1 && ` · ${z.versuche}. Versuch`} {z.ergebnis === "GESENDET" ? ( gesendet ) : ( fehlgeschlagen {z.fehler && {z.fehler}} {z.naechsterVersuchAm ? `neuer Versuch ab ${datumZeit(z.naechsterVersuchAm)}` : "kein weiterer Versuch"} )} ))} ); } /** Einstellungen (#028): lesen duerfen alle, aendern nur `einstellungenVerwalten` (Admin). */ export default async function Einstellungen() { // Jede Seite prueft selbst; die Huelle ist nur das zweite Netz (CLAUDE.md). const { benutzer } = await sitzungErforderlich("lesen", "/einstellungen"); const darfAendern = darf(benutzer.rolle, "einstellungenVerwalten"); const seite = await einstellungenSeite(); // Eine Webhook-Adresse traegt oft ein Token im Pfad – Leser sehen nur Schema und Host. const ansicht = darfAendern ? seite.benachrichtigung : { ...seite.benachrichtigung, webhook: { ...seite.benachrichtigung.webhook, url: seite.webhookZiel ?? "" }, }; const { instanz } = seite; return (
alle 5 Minuten geprüft

Zeitzone Europe/Berlin. Gesetzt über SSHKV_SYNC_CRON und{" "} SSHKV_MELDUNG_CRON in der Umgebung des Workers.

{/* Platz fuer den Abschnitt „Syslog“ – folgt in einem eigenen Issue. */}
{instanz.version} {instanz.deploymentKey ? ( <> {darf(benutzer.rolle, "deploymentKeyVerwalten") && ( Deployment-Key rotieren )} ) : ( noch nicht erzeugt – läuft der Worker? )} {instanz.oidc.konfiguriert ? ( instanz.oidc.name ) : ( nicht eingerichtet )} {!instanz.notfall.vorhanden ? ( nicht angelegt ) : instanz.notfall.totpEingerichtet ? ( TOTP eingerichtet ) : ( TOTP noch nicht eingerichtet )}
); }