import { useMemo, useState } from 'react' import { Badge, Box, Divider, IconButton, Popover, Typography } from '@mui/material' import { Bell } from 'lucide-react' import { useNavigate } from 'react-router' import { useNeedProfiles } from '../../hooks/useNeeds' import { useMatches } from '../../hooks/useMatches' import { ROUTES } from '../../lib/constants' function loadSeenCounts(): Record { try { return JSON.parse(localStorage.getItem('notif-seen-counts') ?? '{}') } catch { return {} } } function saveSeenCounts(counts: Record) { localStorage.setItem('notif-seen-counts', JSON.stringify(counts)) } export function NotificationButton() { const [anchorEl, setAnchorEl] = useState(null) const [seenCounts, setSeenCounts] = useState>(loadSeenCounts) const navigate = useNavigate() const { data: needs = [] } = useNeedProfiles() const { data: allMatches = [] } = useMatches() const profilesWithMatches = useMemo(() => { const active = needs.filter(n => (!n.status || n.status === 'ACTIVE' || n.status === 'DRAFT') && (n.notificationConfig?.enabled !== false), ) return active .map(n => { const minScore = n.notificationConfig?.minScore ?? 80 return { need: n, count: allMatches.filter(m => m.needId === n.id && m.matchScore >= minScore).length, minScore, } }) .filter(x => x.count > 0) }, [needs, allMatches]) // Badge only lights up for profiles with matches the user hasn't seen yet const newProfiles = useMemo( () => profilesWithMatches.filter(x => x.count > (seenCounts[x.need.id] ?? 0)), [profilesWithMatches, seenCounts], ) const badgeCount = newProfiles.length function handleOpen(e: React.MouseEvent) { setAnchorEl(e.currentTarget) // Mark all current matches as seen const updated = { ...seenCounts } for (const { need, count } of profilesWithMatches) { updated[need.id] = count } setSeenCounts(updated) saveSeenCounts(updated) } function handleClose() { setAnchorEl(null) } function goToResults(needId: string) { navigate(ROUTES.DEMAND.RESULTS, { state: { fromNeedBuilder: true, activeNeedId: needId } }) handleClose() } return ( <> Neue Treffer {profilesWithMatches.length === 0 ? ( Keine aktiven Benachrichtigungen ) : ( <> {profilesWithMatches.map(({ need, count, minScore }) => ( goToResults(need.id)} sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', px: 1, py: 0.875, borderRadius: 1, cursor: 'pointer', '&:hover': { bgcolor: '#f8fafc' }, transition: 'background 0.1s', }} > {need.companyName} ab {minScore}% {count} Treffer → ))} { navigate(ROUTES.DEMAND.AI_SEARCH); handleClose() }} sx={{ textAlign: 'center', cursor: 'pointer', color: '#152642', fontSize: '0.8rem', fontWeight: 600, py: 0.25, '&:hover': { color: '#16304d' } }} > Alle Suchprofile anzeigen → )} ) }