"use client"; import { Bell, Users } from "lucide-react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useEffect, useRef, useState } from "react"; import { completeEmployeeNote } from "@/actions/employees"; import { setNotizSichtbarkeit } from "@/actions/notes"; import { useToast } from "@/components/ui/Toast"; import { NOTE_CATEGORY_STYLES } from "@/lib/colors"; import { fmtDate } from "@/lib/format"; import type { OpenNote } from "@/lib/notes"; export type Kollege = { id: string; name: string; sichtbar: boolean }; // Click-outside mechanics borrowed from CountryPicker (useRef + mousedown // listener) — without its draft-text reset, which has no equivalent here. export function NotesBell({ notes, kollegen }: { notes: OpenNote[]; kollegen: Kollege[] }) { const { showToast } = useToast(); const router = useRouter(); const [open, setOpen] = useState(false); const [completingId, setCompletingId] = useState(null); const [zeigeEinstellung, setZeigeEinstellung] = useState(false); // Der Haken springt sofort um und wird zurückgedreht, wenn das Speichern // scheitert. Ohne das fühlt sich jeder Klick wie eine halbe Sekunde // Bedenkzeit an — die Liste wird beim Durchgehen mehrfach angetippt. const [eigen, setEigen] = useState>({}); const containerRef = useRef(null); const sichtbarkeit = (k: Kollege) => eigen[k.id] ?? k.sichtbar; const dazugewaehlt = kollegen.filter((k) => sichtbarkeit(k)).length; async function schalte(k: Kollege) { const neu = !sichtbarkeit(k); setEigen((v) => ({ ...v, [k.id]: neu })); const result = await setNotizSichtbarkeit({ kollegeId: k.id, sichtbar: neu }); if (result.success) { router.refresh(); } else { setEigen((v) => ({ ...v, [k.id]: !neu })); showToast(result.error ?? "Fehler beim Speichern.", "error"); } } useEffect(() => { function onClickOutside(e: MouseEvent) { if (containerRef.current && !containerRef.current.contains(e.target as Node)) { setOpen(false); } } document.addEventListener("mousedown", onClickOutside); return () => document.removeEventListener("mousedown", onClickOutside); }, []); async function handleComplete(note: OpenNote) { setCompletingId(note.id); const result = await completeEmployeeNote({ note_id: note.id, employee_id: note.employee_id }); setCompletingId(null); if (result.success) { showToast("Notiz erledigt."); router.refresh(); } else { showToast(result.error ?? "Fehler beim Speichern.", "error"); } } return (
{open && (
Meine Notizen ({notes.length})
{zeigeEinstellung && (
{/* Dass die Auswahl auch die Entwürfe auf der Übersicht steuert, steht hier und nicht nur dort: sie wird hier getroffen, und eine Wirkung, die zwei Klicks entfernt sichtbar wird, sucht sonst niemand. */}

Wessen Notizen hier und wessen Entwürfe auf der Übersicht zusätzlich erscheinen. Die eigenen sind immer dabei.

{kollegen.length === 0 ? (

Keine weiteren HR-Kolleg:innen freigeschaltet.

) : (
    {kollegen.map((k) => (
  • ))}
)}
)} {notes.length === 0 ? (

Keine offenen Notizen.

) : (
    {notes.map((n) => (
  • {n.category} {n.employeeName} {fmtDate(n.created_at)}

    {n.note_text}

    {/* Von wem die Notiz stammt. Sichtbar sind die eigenen und die hinzugewählten — ohne diese Zeile wäre nicht zu unterscheiden, welche davon man gerade liest. „Ich" statt des eigenen Namens: den kennt man. */}

    {n.vonMir ? "von mir" : `von ${n.author_name}`}

    {n.due_date &&

    🔔 fällig {fmtDate(n.due_date)}

    }
  • ))}
)}
)}
); }