import React, { useState, useEffect, useCallback } from 'react'; import { Bell, CheckCheck, Loader2 } from 'lucide-react'; import { backendApi, NotificationItem } from '../services/apiClient'; function formatNotificationDate(iso: string): string { const d = new Date(iso); const now = new Date(); const diff = now.getTime() - d.getTime(); if (diff < 60000) return 'только что'; if (diff < 3600000) return `${Math.floor(diff / 60000)} мин. назад`; if (diff < 86400000) return d.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }); return d.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' }); } interface NotificationPanelProps { isOpen: boolean; onClose: () => void; unreadCount: number; onUnreadCountChange: (count: number) => void; onNavigate: (entityType: string, entityId: string) => void; } export const NotificationPanel: React.FC = ({ isOpen, onClose, unreadCount, onUnreadCountChange, onNavigate, }) => { const [list, setList] = useState([]); const [loading, setLoading] = useState(false); const [readAllLoading, setReadAllLoading] = useState(false); const fetchList = useCallback(async () => { setLoading(true); try { const data = await backendApi.getNotifications({ limit: 50 }); setList(Array.isArray(data) ? data : []); } catch { setList([]); } finally { setLoading(false); } }, []); useEffect(() => { if (isOpen) { fetchList(); } }, [isOpen, fetchList]); const handleMarkRead = useCallback( async (id: number) => { try { await backendApi.markNotificationRead(id); setList((prev) => prev.map((n) => (n.id === id ? { ...n, readAt: new Date().toISOString() } : n))); onUnreadCountChange(Math.max(0, unreadCount - 1)); } catch { // ignore } }, [unreadCount, onUnreadCountChange] ); const handleReadAll = useCallback(async () => { setReadAllLoading(true); try { await backendApi.markAllNotificationsRead(); setList((prev) => prev.map((n) => ({ ...n, readAt: n.readAt || new Date().toISOString() }))); onUnreadCountChange(0); } catch { // ignore } finally { setReadAllLoading(false); } }, [onUnreadCountChange]); const handleItemClick = useCallback( (item: NotificationItem) => { if (item.entityType && item.entityId) { onNavigate(item.entityType, item.entityId); onClose(); if (!item.readAt) { handleMarkRead(item.id); } } }, [onNavigate, onClose, handleMarkRead] ); if (!isOpen) return null; return ( <>