"use client"; import Link from "next/link"; import { useCallback, useEffect, useState, useSyncExternalStore } from "react"; import { SearchDialog, type SuchEintrag } from "./SearchDialog"; import type { Rolle } from "@/generated/prisma/enums"; import { ROLLEN_TEXT } from "@/server/auth/rollen"; import { menuUmschalten } from "./menuZustand"; export interface KopfleistenAlert { id: string; titel: string; beschreibung: string; schwere: "INFO" | "WARNUNG" | "GEFAHR"; hostId: string | null; } const SCHWERE_ICON: Record = { GEFAHR: "bi-exclamation-octagon-fill pl-text-danger", WARNUNG: "bi-exclamation-triangle-fill pl-text-warning", INFO: "bi-info-circle-fill text-body-secondary", }; /** Farbschema aus dem -Attribut lesen, damit Server und Client übereinstimmen. */ function themaIstDunkel() { return document.documentElement.dataset.bsTheme === "dark"; } function themaAbonnieren(aenderung: () => void) { const beobachter = new MutationObserver(aenderung); beobachter.observe(document.documentElement, { attributes: true, attributeFilter: ["data-bs-theme"] }); return () => beobachter.disconnect(); } export function Header({ alerts, suchEintraege, benutzer, rolle, }: { alerts: KopfleistenAlert[]; suchEintraege: SuchEintrag[]; benutzer: string; rolle: Rolle; }) { const [sucheOffen, setSucheOffen] = useState(false); const [glockeOffen, setGlockeOffen] = useState(false); const [benutzerOffen, setBenutzerOffen] = useState(false); const dunkel = useSyncExternalStore(themaAbonnieren, themaIstDunkel, () => false); useEffect(() => { function tasten(event: KeyboardEvent) { if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "k") { event.preventDefault(); setSucheOffen(true); } } window.addEventListener("keydown", tasten); return () => window.removeEventListener("keydown", tasten); }, []); /** Seitenmenü umschalten – der Zustand liegt in menuZustand.ts, damit das Menü selbst ihn kennt. */ const sidebarUmschalten = useCallback(() => { menuUmschalten(); }, []); function themaUmschalten() { const neu = dunkel ? "light" : "dark"; document.documentElement.dataset.bsTheme = neu; try { localStorage.setItem("pl-theme", neu); } catch { // Speicherzugriff kann blockiert sein; das Thema gilt dann nur für diese Sitzung. } } function vollbild() { if (document.fullscreenElement) { void document.exitFullscreen(); } else { void document.documentElement.requestFullscreen(); } } return (