'use client' import React, { useState, useEffect } from 'react' import { useRouter, usePathname } from 'next/navigation' import Image from 'next/image' import useUIStore from '../../app/store/uiStore' import useNavigationStore from '../../app/store/navigationStore' import { useNavigationService } from '@/services/navigationService' import useUserStore from '../../app/store/userStore' import { signOut } from 'next-auth/react' interface NavigationItem { id: number label: string icon: React.ComponentType<{ className?: string }> } interface SidebarProps { navigationItems?: NavigationItem[] logoSrc?: string userInfo?: { name: string role: string avatar?: string } activeItem?: number | null onCustomItemClick?: (itemId: number) => boolean } const IconWrapper = ({ src, alt, className }: { src: string; alt: string; className?: string }) => (
{alt}
) const BookOpen = ({ className }: { className?: string }) => ( ) const Bot = ({ className }: { className?: string }) => ( ) const SquareTerminal = ({ className }: { className?: string }) => ( ) const CircleDot = ({ className }: { className?: string }) => ( ) const BellDot = ({ className }: { className?: string }) => ( ) const History = ({ className }: { className?: string }) => ( ) const Settings2 = ({ className }: { className?: string }) => ( ) const Monitor = ({ className }: { className?: string }) => ( ) const Building = ({ className }: { className?: string }) => ( ) // основные routes const mainNavigationItems: NavigationItem[] = [ { id: 1, icon: BookOpen, label: 'Дашборд' }, { id: 2, icon: Bot, label: 'Навигация по зданию' }, { id: 8, icon: History, label: 'История тревог' }, { id: 9, icon: Settings2, label: 'Отчеты' } ] // суб-меню под "Навигация по зданию" const navigationSubItems: NavigationItem[] = [ { id: 3, icon: Monitor, label: 'Зоны Мониторинга' }, { id: 4, icon: Building, label: 'Навигация по этажам' }, { id: 5, icon: BellDot, label: 'Уведомления' }, { id: 6, icon: CircleDot, label: 'Сенсоры' }, { id: 7, icon: SquareTerminal, label: 'Список датчиков' } ] const Sidebar: React.FC = ({ logoSrc, userInfo = { name: '—', role: '—' }, activeItem: propActiveItem, onCustomItemClick }) => { const navigationService = useNavigationService() const router = useRouter() const pathname = usePathname() const [internalActiveItem, setInternalActiveItem] = useState(null) const [isHydrated, setIsHydrated] = useState(false) const [manuallyToggled, setManuallyToggled] = useState(false) const activeItem = propActiveItem !== undefined ? propActiveItem : internalActiveItem const { isSidebarCollapsed: isCollapsed, toggleSidebar, isNavigationSubMenuExpanded: showNavigationSubItems, setNavigationSubMenuExpanded: setShowNavigationSubItems, toggleNavigationSubMenu } = useUIStore() const { user, logout } = useUserStore() const roleLabelMap: Record = { engineer: 'Инженер', operator: 'Оператор', admin: 'Администратор', } const fullName = [user?.name, user?.surname].filter(Boolean).join(' ').trim() const uiUserInfo = { name: fullName || user?.login || userInfo?.name || '—', role: roleLabelMap[(user?.account_type ?? '').toLowerCase()] || userInfo?.role || '—', avatar: user?.image || userInfo?.avatar, } const handleLogout = async () => { try { await fetch('/api/auth/logout', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', }) } catch (e) { console.error('Logout request failed:', e) } finally { logout() await signOut({ redirect: true, callbackUrl: '/login' }) } } const { openMonitoring, openFloorNavigation, openNotifications, closeMonitoring, closeFloorNavigation, closeNotifications, showMonitoring, showFloorNavigation, showNotifications } = useNavigationStore() useEffect(() => { setIsHydrated(true) }, []) // Чек если суб-меню активны const isNavigationSubItemActive = activeItem && [3, 4, 5, 6, 7].includes(activeItem) const shouldShowNavigationAsActive = activeItem === 2 || isNavigationSubItemActive // Авто-расткрытие меню, если суб-меню стало активным (только если не было ручного переключения) useEffect(() => { if (isNavigationSubItemActive && !showNavigationSubItems && !manuallyToggled) { setShowNavigationSubItems(true) } }, [isNavigationSubItemActive, showNavigationSubItems, manuallyToggled, setShowNavigationSubItems]) const handleItemClick = (itemId: number) => { let handled = false // Управление суб-меню через navigationStore (суб-меню - работают как отдельные элементы, но не страницы) switch (itemId) { case 2: if (pathname !== '/navigation') { router.push('/navigation') } handled = true break case 3: // Monitoring if (pathname !== '/navigation') { router.push('/navigation') setTimeout(() => openMonitoring(), 100) } else if (showMonitoring) { closeMonitoring() } else { openMonitoring() } handled = true break case 4: // Floor Navigation if (pathname !== '/navigation') { router.push('/navigation') setTimeout(() => openFloorNavigation(), 100) } else if (showFloorNavigation) { closeFloorNavigation() } else { openFloorNavigation() } handled = true break case 5: // Notifications if (pathname !== '/navigation') { router.push('/navigation') setTimeout(() => openNotifications(), 100) } else if (showNotifications) { closeNotifications() } else { openNotifications() } handled = true break default: // Для остального используем routes if (navigationService) { handled = navigationService.handleSidebarItemClick(itemId, pathname) } break } if (handled) { if (propActiveItem === undefined) { setInternalActiveItem(itemId) } if (onCustomItemClick) { onCustomItemClick(itemId) } } } return ( ) } export default Sidebar