import { useState } from 'react'; import { Link, useLocation, useNavigate } from 'react-router-dom'; import { Avatar, Badge, Box, Button, Collapse, Divider, List, ListItem, ListItemAvatar, ListItemButton, ListItemIcon, ListItemText, Menu, MenuItem, Typography, alpha, useTheme, } from '@mui/material'; import ExpandLess from '@mui/icons-material/ExpandLess'; import ExpandMore from '@mui/icons-material/ExpandMore'; import HomeOutlinedIcon from '@mui/icons-material/HomeOutlined'; import GroupsOutlinedIcon from '@mui/icons-material/GroupsOutlined'; import CategoryOutlinedIcon from '@mui/icons-material/CategoryOutlined'; import PersonOutlineOutlinedIcon from '@mui/icons-material/PersonOutlineOutlined'; import CollectionsBookmarkOutlinedIcon from '@mui/icons-material/CollectionsBookmarkOutlined'; import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined'; import HelpOutlineOutlinedIcon from '@mui/icons-material/HelpOutlineOutlined'; import AdminPanelSettingsOutlinedIcon from '@mui/icons-material/AdminPanelSettingsOutlined'; import LogoutOutlinedIcon from '@mui/icons-material/LogoutOutlined'; import LoginOutlinedIcon from '@mui/icons-material/LoginOutlined'; import NotificationsOutlinedIcon from '@mui/icons-material/NotificationsOutlined'; import PeopleOutlineOutlinedIcon from '@mui/icons-material/PeopleOutlineOutlined'; import { useTranslation } from 'react-i18next'; import { useAuth } from '../../hooks/useAuth'; import { useNotifications } from '../../hooks/useNotifications'; import { GlobalSearch } from '../../app/GlobalSearch'; import { formatDate } from '../../utils/date'; import type { Notification } from '../../contexts/NotificationContext'; export const NAV_SIDEBAR_WIDTH = 280; export interface NavSidebarProps { categories: { name: string; slug: string }[]; onNavigate?: () => void; showSearch?: boolean; showNotifications?: boolean; } export const NavSidebar = ({ categories, onNavigate, showSearch = false, showNotifications = false, }: NavSidebarProps) => { const { t } = useTranslation(); const location = useLocation(); const navigate = useNavigate(); const theme = useTheme(); const { user, following, logout } = useAuth(); const { notifications, markAllRead, markRead } = useNotifications(); const [catOpen, setCatOpen] = useState(false); const [followingOpen, setFollowingOpen] = useState(false); const [notifAnchorEl, setNotifAnchorEl] = useState(null); const close = () => onNavigate?.(); const isActive = (path: string) => path === '/' ? location.pathname === '/' : location.pathname.startsWith(path); const handleNotificationClick = async (notif: Notification) => { if (!notif.is_read) await markRead(notif.id); setNotifAnchorEl(null); close(); if (notif.notification_type.startsWith('ticket')) { navigate(user?.is_superuser ? '/admin-panel/tickets' : '/support'); } else if (notif.notification_type === 'profile_comment') { navigate(`/profile/${user?.username}`); } else if (notif.notification_type === 'follow') { navigate(`/profile/${notif.actor_username}`); } else if (notif.flavor_id) { window.location.href = `/flavor/${notif.flavor_id}`; } }; const unreadCount = user?.unread_notifications_count || 0; return ( {user ? ( {user.username.charAt(0).toUpperCase()} {user.username} {t('nav.profile')} ) : null} {showSearch && ( )} {user && ( )} {user && showNotifications && ( setNotifAnchorEl(e.currentTarget)}> )} setCatOpen(!catOpen)} selected={location.pathname.startsWith('/category/')} > {catOpen ? : } {categories.map((cat) => ( ))} {user && ( <> {user.is_superuser && ( <> )} {following.length > 0 && ( <> setFollowingOpen(!followingOpen)}> {t('nav.following')} {following.length} } /> {followingOpen ? : } {following.map((f) => ( {!f.avatar && f.username.charAt(0).toUpperCase()} ))} )} )} {!user && ( <> )} {user && ( { close(); logout(); }} > )} {showNotifications && ( setNotifAnchorEl(null)} anchorOrigin={{ vertical: 'center', horizontal: 'right' }} transformOrigin={{ vertical: 'center', horizontal: 'left' }} elevation={3} PaperProps={{ sx: { width: 320, maxHeight: 400, borderRadius: 1, ml: 1 } }} > {t('nav.notifications', { defaultValue: 'Notifications' })} {unreadCount > 0 && ( )} {notifications.length === 0 ? ( {t('community.noNotifications', { defaultValue: 'No notifications yet' })} ) : ( notifications.map((n) => ( handleNotificationClick(n)} sx={{ py: 1.5, px: 2, borderBottom: '1px solid', borderColor: 'divider', bgcolor: n.is_read ? 'transparent' : alpha(theme.palette.primary.main, 0.05), whiteSpace: 'normal', display: 'flex', gap: 2, alignItems: 'flex-start', }} > {n.actor_username.charAt(0).toUpperCase()} {n.actor_username}{' '} {n.notification_type === 'reply' ? `replied to your review on ${n.flavor_name}` : n.notification_type === 'mention' ? `mentioned you on ${n.flavor_name}` : n.notification_type === 'follow' ? t('community.notifFollow') : n.notification_type === 'profile_comment' ? `left a message on your guestbook` : n.notification_type === 'ticket_new' ? t('community.notifTicketNew') : user?.is_superuser ? t('community.notifTicketReplyAdmin') : t('community.notifTicketReply')} {formatDate(n.created_at)} )) )} )} ); };