"use client"; import { useActionState, useState } from "react"; import { Card } from "@/components/ui/Card"; import type { Rolle } from "@/generated/prisma/enums"; import { formatDatumZeit } from "@/lib/format"; import { PASSWORT_MINDESTLAENGE } from "@/lib/passwort"; import { type AktionsErgebnis, benutzerAnlegen, benutzerLoeschen, benutzerSpeichern, benutzerSperreUmschalten, } from "@/server/actions/benutzer"; import { ROLLEN_BESCHREIBUNG, ROLLEN_TEXT } from "@/server/auth/rollen"; export interface BenutzerZeile { id: string; email: string; name: string; rolle: Rolle; kundeId: string | null; kundeName: string | null; aktiv: boolean; hatPasswort: boolean; hatOidc: boolean; passkeys: number; letzterLoginAm: Date | null; } const LEER: AktionsErgebnis = {}; const ROLLEN: Rolle[] = ["ADMIN", "TECHNIKER", "KUNDE"]; function RollenFelder({ eintrag, kunden, fehler, }: { eintrag?: BenutzerZeile; kunden: { id: string; name: string }[]; fehler: Record; }) { const [rolle, setRolle] = useState(eintrag?.rolle ?? "TECHNIKER"); return ( <>
{ROLLEN_BESCHREIBUNG[rolle]}
{/* Der Kunde zählt nur für ein Kundenkonto – deshalb erscheint das Feld auch nur dann. */} {rolle === "KUNDE" ? (
{fehler.kundeId ?
{fehler.kundeId}
: null}
) : null} ); } function NeuFormular({ kunden }: { kunden: { id: string; name: string }[] }) { const [ergebnis, aktion, laeuft] = useActionState(benutzerAnlegen, LEER); const fehler = ergebnis.felder ?? {}; return (
{ergebnis.fehler ?
{ergebnis.fehler}
: null} {ergebnis.erfolg ?
{ergebnis.erfolg}
: null}
{fehler.name ?
{fehler.name}
: null}
{fehler.email ?
{fehler.email}
: null}
Leer lassen, wenn sich das Konto nur über OIDC oder einen Passkey anmelden soll.
{fehler.passwort ?
{fehler.passwort}
: null}
); } function Zeile({ eintrag, kunden, ichSelbst, }: { eintrag: BenutzerZeile; kunden: { id: string; name: string }[]; ichSelbst: boolean; }) { const [ergebnis, aktion, laeuft] = useActionState(benutzerSpeichern, LEER); const [offen, setOffen] = useState(false); const fehler = ergebnis.felder ?? {}; const anmeldewege = [ eintrag.hatPasswort ? "Passwort" : null, eintrag.hatOidc ? "OIDC" : null, eintrag.passkeys > 0 ? `${eintrag.passkeys} Passkey${eintrag.passkeys === 1 ? "" : "s"}` : null, ].filter(Boolean); return ( <> {ichSelbst ? Sie : null}
{eintrag.email}
{ROLLEN_TEXT[eintrag.rolle]} {eintrag.kundeName ?
{eintrag.kundeName}
: null} {anmeldewege.length > 0 ? anmeldewege.join(" · ") : kein Zugang} {eintrag.letzterLoginAm ? formatDatumZeit(eintrag.letzterLoginAm) : "noch nie"} {eintrag.aktiv ? ( aktiv ) : ( gesperrt )}
{!ichSelbst ? ( <>
) : null}
{offen ? (
{ergebnis.fehler ?
{ergebnis.fehler}
: null} {ergebnis.erfolg ?
{ergebnis.erfolg}
: null}
Leer lassen heißt: unverändert. Ein neues beendet alle Sitzungen.
) : null} ); } export function BenutzerVerwaltung({ benutzer, kunden, ichId, }: { benutzer: BenutzerZeile[]; kunden: { id: string; name: string }[]; ichId: string; }) { return ( <>
{benutzer.map((eintrag) => ( ))}
Name Rolle Anmeldung Zuletzt angemeldet Zustand Aktionen
); }