import Link from "next/link"; import { notFound, redirect } from "next/navigation"; import { ArrowLeft } from "lucide-react"; import { aktuelleSitzung } from "@/lib/auth"; import { darfPersonSehen } from "@/lib/authz"; import { fuerOrganisation } from "@/lib/db"; import { alsDatum, personAnrede } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { FristAnzeige, NichtsGefunden } from "@/components/stammdaten/anzeige"; export const metadata = { title: "Mitglied" }; const DIENSTGRAD_TEXT: Record = { FEUERWEHRANWAERTER: "Feuerwehranwärter", FEUERWEHRMANN: "Feuerwehrmann", OBERFEUERWEHRMANN: "Oberfeuerwehrmann", HAUPTFEUERWEHRMANN: "Hauptfeuerwehrmann", LOESCHMEISTER: "Löschmeister", OBERLOESCHMEISTER: "Oberlöschmeister", HAUPTLOESCHMEISTER: "Hauptlöschmeister", BRANDMEISTER: "Brandmeister", OBERBRANDMEISTER: "Oberbrandmeister", HAUPTBRANDMEISTER: "Hauptbrandmeister", KEIN: "—", }; /** * Mitgliedsdetail. * * Die Zugriffsprüfung läuft über darfPersonSehen(): die eigenen Daten darf * jeder sehen, fremde nur mit dem Recht person.lesen. Adressen und * Geburtsdatum sind personenbezogene Daten — sie stehen deshalb hinter * derselben Schranke wie alles andere. */ export default async function MitgliedSeite({ params }: { params: Promise<{ id: string }> }) { const sitzung = await aktuelleSitzung(); if (!sitzung) redirect("/anmelden"); const { id } = await params; if (!darfPersonSehen(sitzung, id)) redirect("/mitglieder"); const person = await fuerOrganisation(sitzung.organisationId, (db) => db.person.findUnique({ where: { id }, select: { id: true, vorname: true, nachname: true, mitgliedsnummer: true, dienstgrad: true, abteilung: true, email: true, telefon: true, mobil: true, strasse: true, plz: true, ort: true, geburtsdatum: true, eintrittsdatum: true, austrittsdatum: true, aktiv: true, letzteAnmeldung: true, rollen: { include: { rolle: true } }, qualifikationen: { where: { geloeschtAm: null }, include: { typ: true }, orderBy: [{ gueltigBis: "asc" }, { erworbenAm: "desc" }], }, ausweisTokens: { where: { geloeschtAm: null, aktiv: true }, select: { id: true, typ: true, bezeichnung: true, letzteNutzung: true }, }, }, }), ); if (!person) notFound(); const angaben: Array<[string, React.ReactNode]> = [ ["Mitgliedsnummer", {person.mitgliedsnummer ?? "—"}], ["Dienstgrad", DIENSTGRAD_TEXT[person.dienstgrad] ?? person.dienstgrad], ["Abteilung", person.abteilung ?? "—"], ["Eintritt", alsDatum(person.eintrittsdatum)], ["Geburtsdatum", alsDatum(person.geburtsdatum)], ["E-Mail", person.email ?? "—"], ["Telefon", person.telefon ?? "—"], ["Mobil", person.mobil ?? "—"], [ "Anschrift", person.strasse ? `${person.strasse}, ${person.plz ?? ""} ${person.ort ?? ""}`.trim() : "—", ], ]; return (

{personAnrede(person)}

{person.rollen.map((zuweisung) => ( {zuweisung.rolle.name} ))} {!person.aktiv && ausgetreten}
Angaben
{angaben.map(([bezeichnung, wert]) => (
{bezeichnung}
{wert}
))}
Terminal-Zugang Anmeldemittel für das Gerätehaus. Gespeichert wird nur ein Hash. {person.ausweisTokens.length === 0 ? (

Kein Terminal-Zugang hinterlegt.

) : (
    {person.ausweisTokens.map((token) => (
  • {token.typ}{" "} {token.bezeichnung ?? ""} {token.letzteNutzung ? alsDatum(token.letzteNutzung) : "noch nicht benutzt"}
  • ))}
)}
Qualifikationen Lehrgänge, Befähigungen und Untersuchungen samt Gültigkeit. {person.qualifikationen.length === 0 ? ( ) : (
    {person.qualifikationen.map((qualifikation) => (
  • {qualifikation.typ.name} {qualifikation.typ.kuerzel && ( {qualifikation.typ.kuerzel} )} erworben {alsDatum(qualifikation.erworbenAm)} {qualifikation.gueltigBis ? ( ) : ( unbefristet )}
  • ))}
)}
); }