trading-platform-frontend-v2/src/modules/notifications/components/NotificationBell.tsx
Adrian Flores Cortes b7de2a3d58 feat: Add NotificationCenter UI components
- Add notification service for API calls
- Add notification Zustand store with WebSocket integration
- Create NotificationBell component with badge
- Create NotificationDropdown with recent notifications
- Create NotificationItem with icons and actions
- Update MainLayout to use NotificationBell

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 03:57:45 -06:00

71 lines
2.0 KiB
TypeScript

/**
* NotificationBell Component
* Bell icon with badge showing unread count, opens dropdown on click
*/
import { useState, useEffect } from 'react';
import { Bell } from 'lucide-react';
import clsx from 'clsx';
import { useNotificationStore } from '../../../stores/notificationStore';
import NotificationDropdown from './NotificationDropdown';
export default function NotificationBell() {
const [isOpen, setIsOpen] = useState(false);
const { unreadCount, fetchUnreadCount, initializeWebSocket } = useNotificationStore();
// Fetch unread count on mount and setup WebSocket
useEffect(() => {
fetchUnreadCount();
// Initialize WebSocket for real-time notifications
const unsubscribe = initializeWebSocket();
// Refresh count periodically
const interval = setInterval(fetchUnreadCount, 60000);
return () => {
unsubscribe();
clearInterval(interval);
};
}, [fetchUnreadCount, initializeWebSocket]);
const toggleDropdown = () => {
setIsOpen(!isOpen);
};
const closeDropdown = () => {
setIsOpen(false);
};
return (
<div className="relative">
<button
onClick={toggleDropdown}
className={clsx(
'relative p-2 rounded-lg transition-colors',
isOpen ? 'bg-gray-700' : 'hover:bg-gray-700'
)}
aria-label={`Notificaciones${unreadCount > 0 ? ` (${unreadCount} sin leer)` : ''}`}
>
<Bell className="w-5 h-5" />
{/* Unread badge */}
{unreadCount > 0 && (
<span
className={clsx(
'absolute flex items-center justify-center rounded-full bg-red-500 text-white font-medium',
unreadCount > 9
? 'top-0 right-0 min-w-[18px] h-[18px] text-[10px] px-1'
: 'top-1 right-1 w-4 h-4 text-[10px]'
)}
>
{unreadCount > 99 ? '99+' : unreadCount}
</span>
)}
</button>
<NotificationDropdown isOpen={isOpen} onClose={closeDropdown} />
</div>
);
}