import React, { useState, useEffect } from 'react'; import { Bell, MessageCircle, AtSign, Heart, Award, TrendingUp, X, Check } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; import { useWebSocket } from '@/contexts/WebSocketContext'; import { useToast } from '@/hooks/use-toast'; interface Notification { id: string; type: 'mention' | 'reply' | 'vote' | 'badge' | 'proposal'; title: string; message: string; timestamp: Date; read: boolean; actionUrl?: string; sender?: { name: string; avatar: string; }; } export const NotificationCenter: React.FC = () => { const { subscribe, unsubscribe } = useWebSocket(); const { toast } = useToast(); const [notifications, setNotifications] = useState([]); const [isOpen, setIsOpen] = useState(false); const [unreadCount, setUnreadCount] = useState(0); const [settings, setSettings] = useState({ mentions: true, replies: true, votes: true, badges: true, proposals: true, pushEnabled: false, }); useEffect(() => { // Request notification permission if ('Notification' in window && Notification.permission === 'default') { Notification.requestPermission(); } // Subscribe to WebSocket events const handleMention = (data: Record) => { const notification: Notification = { id: Date.now().toString(), type: 'mention', title: 'You were mentioned', message: `${data.sender} mentioned you in a discussion`, timestamp: new Date(), read: false, actionUrl: data.url, sender: data.senderInfo, }; addNotification(notification); }; const handleReply = (data: Record) => { const notification: Notification = { id: Date.now().toString(), type: 'reply', title: 'New reply', message: `${data.sender} replied to your comment`, timestamp: new Date(), read: false, actionUrl: data.url, sender: data.senderInfo, }; addNotification(notification); }; subscribe('mention', handleMention); subscribe('reply', handleReply); return () => { unsubscribe('mention', handleMention); unsubscribe('reply', handleReply); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [subscribe, unsubscribe]); const addNotification = (notification: Notification) => { setNotifications(prev => [notification, ...prev]); setUnreadCount(prev => prev + 1); // Show toast toast({ title: notification.title, description: notification.message, }); // Show push notification if enabled if (settings.pushEnabled && 'Notification' in window && Notification.permission === 'granted') { new Notification(notification.title, { body: notification.message, icon: '/logo.png', }); } }; const markAsRead = (id: string) => { setNotifications(prev => prev.map(n => n.id === id ? { ...n, read: true } : n) ); setUnreadCount(prev => Math.max(0, prev - 1)); }; const markAllAsRead = () => { setNotifications(prev => prev.map(n => ({ ...n, read: true }))); setUnreadCount(0); }; const getIcon = (type: string) => { switch (type) { case 'mention': return ; case 'reply': return ; case 'vote': return ; case 'badge': return ; case 'proposal': return ; default: return ; } }; return (
{isOpen && (
All Unread Settings
{notifications.length} notifications
{notifications.map(notification => (
markAsRead(notification.id)} >
{getIcon(notification.type)}

{notification.title}

{notification.message}

{new Date(notification.timestamp).toLocaleTimeString()}

))}
{notifications.filter(n => !n.read).map(notification => (
markAsRead(notification.id)} >
{getIcon(notification.type)}

{notification.title}

{notification.message}

))}
{ if (checked && 'Notification' in window) { Notification.requestPermission().then(permission => { setSettings(prev => ({ ...prev, pushEnabled: permission === 'granted' })); }); } else { setSettings(prev => ({ ...prev, pushEnabled: checked })); } }} />
setSettings(prev => ({ ...prev, mentions: checked }))} />
setSettings(prev => ({ ...prev, replies: checked }))} />
)}
); };