'use client' import { useEffect, useRef } from 'react' import Button from './Button' import { formatDistanceToNow } from 'date-fns' import { de } from 'date-fns/locale' type Notification = { id: string text: string read: boolean actionType?: string // z. B. "team-invite" | "team-join-request" actionData?: string // invitationId oder teamId createdAt?: string } type Props = { notifications: Notification[] markAllAsRead: () => void onSingleRead: (id: string) => void onClose: () => void onAction: (action: 'accept' | 'reject', invitationId: string) => void onClickNotification?: (notification: Notification) => void } export default function NotificationDropdown({ notifications, markAllAsRead, onSingleRead, onClose, onAction, onClickNotification }: Props) { const dropdownRef = useRef(null) /* --- Klick außerhalb schließt Dropdown ------------------------- */ useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { onClose() } } document.addEventListener('mousedown', handleClickOutside) return () => document.removeEventListener('mousedown', handleClickOutside) }, [onClose]) /* --- Render ----------------------------------------------------- */ return (
{/* Kopfzeile */}
Benachrichtigungen
{/* Liste */}
{notifications.length === 0 ? (
Keine Benachrichtigungen
) : ( notifications.map((n) => { const needsAction = !n.read && (n.actionType === 'team-invite' || n.actionType === 'team-join-request') return (
{ onClickNotification?.(n) // ⬅️ Navigation / Weiterverarbeitung if (!n.read) onSingleRead(n.id) // ⬅️ erst danach als gelesen markieren }} > {/* roter Punkt */}
{/* Text + Timestamp */}
{n.text} {n.createdAt && formatDistanceToNow(new Date(n.createdAt), { addSuffix: true, locale: de, })}
{/* Aktionen */}
{needsAction ? ( <> ) : ( !n.read && ( ) )}
) }) )}
) }