import { Sun, Moon, Bell, LogOut, ChevronDown, Menu, BookOpen, X, CheckCheck, CalendarCheck2, CalendarX2, Sparkles, AlertTriangle, Star, CreditCard, Info, ArrowRight, Wrench, } from 'lucide-react' import { useTheme } from '../../contexts/ThemeContext' import { useAuth } from '../../contexts/AuthContext' import { ROLE_LABELS } from '../../lib/utils' import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { cn } from '../../lib/utils' import { useNotifications, type NotifType, type Notification } from '../../contexts/NotificationsContext' // ── Helpers ──────────────────────────────────────────────────────────────────── const NOTIF_META: Record = { booking_new: { icon: BookOpen, iconBg: 'bg-brand-100 dark:bg-brand-900/40', iconColor: 'text-brand-600 dark:text-brand-400' }, booking_cancelled: { icon: CalendarX2, iconBg: 'bg-red-100 dark:bg-red-900/30', iconColor: 'text-red-600 dark:text-red-400' }, booking_checkin: { icon: CalendarCheck2, iconBg: 'bg-emerald-100 dark:bg-emerald-900/30', iconColor: 'text-emerald-600 dark:text-emerald-400' }, booking_checkout: { icon: ArrowRight, iconBg: 'bg-slate-100 dark:bg-slate-700', iconColor: 'text-slate-600 dark:text-slate-400' }, housekeeping: { icon: Sparkles, iconBg: 'bg-sky-100 dark:bg-sky-900/30', iconColor: 'text-sky-600 dark:text-sky-400' }, channel_error: { icon: AlertTriangle, iconBg: 'bg-orange-100 dark:bg-orange-900/30', iconColor: 'text-orange-600 dark:text-orange-400' }, payment: { icon: CreditCard, iconBg: 'bg-violet-100 dark:bg-violet-900/30', iconColor: 'text-violet-600 dark:text-violet-400' }, review: { icon: Star, iconBg: 'bg-yellow-100 dark:bg-yellow-900/30', iconColor: 'text-yellow-600 dark:text-yellow-400' }, system: { icon: Info, iconBg: 'bg-slate-100 dark:bg-slate-700', iconColor: 'text-slate-500 dark:text-slate-400' }, maintenance: { icon: Wrench, iconBg: 'bg-red-100 dark:bg-red-900/30', iconColor: 'text-red-600 dark:text-red-400' }, } function relativeTime(iso: string): string { const diff = Math.floor((Date.now() - new Date(iso).getTime()) / 1000) if (diff < 60) return 'только что' if (diff < 3600) return `${Math.floor(diff / 60)} мин. назад` if (diff < 86400) return `${Math.floor(diff / 3600)} ч. назад` if (diff < 172800) return 'вчера' return new Date(iso).toLocaleDateString('ru-RU', { day: 'numeric', month: 'short' }) } // ── NotificationsPanel ───────────────────────────────────────────────────────── function NotificationsPanel({ onClose }: { onClose: () => void }) { const navigate = useNavigate() const { notifications, markRead, markAllRead, removeNotif } = useNotifications() const [tab, setTab] = useState<'all' | 'unread'>('all') const unreadCount = notifications.filter(n => !n.isRead).length const handleClick = (n: Notification) => { markRead(n.id) if (n.link) { navigate(n.link); onClose() } } const shown = tab === 'unread' ? notifications.filter(n => !n.isRead) : notifications return (
{/* Header */}

Уведомления

{unreadCount > 0 && ( {unreadCount} )}
{unreadCount > 0 && ( )}
{/* Tabs */}
{([ { id: 'all' as const, label: 'Все', count: notifications.length }, { id: 'unread' as const, label: 'Непрочитанные', count: unreadCount }, ]).map(t => ( ))}
{/* List */}
{shown.length === 0 ? (

Нет уведомлений

{tab === 'unread' ? 'Все уведомления прочитаны' : 'Пока ничего нет'}

) : (
{shown.map(n => { const meta = NOTIF_META[n.type] const Icon = meta.icon return (
handleClick(n)} className={cn( 'group flex gap-3 px-4 py-3.5 cursor-pointer transition-colors relative', n.isRead ? 'hover:bg-slate-50 dark:hover:bg-slate-700/40' : 'bg-brand-50/60 dark:bg-brand-900/10 hover:bg-brand-50 dark:hover:bg-brand-900/20', )} > {/* Unread dot */} {!n.isRead && (
)} {/* Icon */}
{/* Content */}

{n.title}

{relativeTime(n.time)}

{n.body}

{n.link && (

Перейти

)}
) })}
)}
{/* Footer */} {notifications.length > 0 && (
)}
) } // ── Topbar ───────────────────────────────────────────────────────────────────── interface TopbarProps { onMenuToggle?: () => void title?: string } export function Topbar({ onMenuToggle, title }: TopbarProps) { const { theme, toggle } = useTheme() const { user, logout } = useAuth() const navigate = useNavigate() const { notifications } = useNotifications() const [userMenuOpen, setUserMenuOpen] = useState(false) const [notifPanelOpen, setNotifPanelOpen] = useState(false) const unreadCount = notifications.filter(n => !n.isRead).length const handleLogout = () => { logout() navigate('/login') } return (
{/* Mobile menu button */} {title && ( {title} )}
{/* Notification bell */}
{notifPanelOpen && ( <>
setNotifPanelOpen(false)} />
setNotifPanelOpen(false)} />
)}
{/* Theme toggle */} {/* User menu */}
{userMenuOpen && ( <>
setUserMenuOpen(false)} />

{user?.name}

{user?.email}

)}
) }