import { PureComponent } from 'react'; import Box from '@mui/material/Box'; import List from '@mui/material/List'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; import ButtonBase from '@mui/material/ButtonBase'; import Typography from '@mui/material/Typography'; import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import UserMenu from './UserMenu'; import HelpBadge from './HelpBadge'; import { NAV_ITEMS, SUB_NAV, resolveActiveNav, resolveActiveSub } from '../nav'; import { artikelQueryPath } from './article/artikelQuery'; import { defaultCategoryPath } from './category/categoryRoute'; import { navigationAutomat } from '../automats'; import { ChatFab, ChatDrawer } from './chat'; const SIDEBAR_WIDTH = 144; const SUB_NAV_WIDTH = 88; class AppSidebar extends PureComponent { constructor(props) { super(props); this.state = { lastDeliveryPath: navigationAutomat.state.lastDeliveryPath, lastArticleSku: navigationAutomat.state.lastArticleSku, }; } componentDidMount() { this.unsub = navigationAutomat.subscribe(this, (state) => ({ lastDeliveryPath: state.lastDeliveryPath, lastArticleSku: state.lastArticleSku, })); } componentWillUnmount() { this.unsub?.(); } render() { const { activeNav, navigate } = this.props; const { lastDeliveryPath, lastArticleSku } = this.state; return ( ({ width: SIDEBAR_WIDTH, flexShrink: 0, display: 'flex', flexDirection: 'column', backgroundColor: theme.nav.backgroundColor || '#1a3533', background: theme.nav.background, position: 'sticky', top: 0, alignSelf: 'flex-start', height: '100vh', })} > {NAV_ITEMS.map(({ path, label, help, icon: Icon }) => { const active = path === activeNav; return ( e.preventDefault()} onClick={() => { if (path === '/artikel') { if (lastArticleSku) { navigate(`/artikel/${lastArticleSku}`); } else { navigate(artikelQueryPath()); } } else if (path === '/lieferung') { if (lastDeliveryPath) { navigate(lastDeliveryPath); } else { navigate(path); } } else { navigate(path); } }} sx={(theme) => ({ borderRadius: 0, px: 1.5, py: 1.25, borderLeft: '3px solid transparent', color: theme.nav.item, '& .MuiListItemIcon-root': { color: 'inherit' }, '&:hover': { bgcolor: theme.nav.itemHover, color: theme.nav.itemHoverText, }, '&.Mui-selected': { bgcolor: theme.nav.itemActive, color: theme.nav.itemActiveText, fontWeight: 600, borderLeftColor: theme.nav.itemActiveAccent, '&:hover': { bgcolor: theme.nav.itemActive, color: theme.nav.itemActiveText, }, }, })} > ); })} ); } } class AppSubNav extends PureComponent { render() { const { activeNav, activeSub, navigate } = this.props; const subNav = activeNav ? SUB_NAV[activeNav] : null; if (!subNav?.length) { return ( ); } return ( {subNav.map(({ segment, label, title, help, icon: Icon }) => { const active = segment === activeSub; return ( e.preventDefault()} onClick={() => { if (!segment && activeNav === '/artikel') { navigate(artikelQueryPath()); return; } if (segment === 'kategorien') { navigate(defaultCategoryPath()); return; } navigate(segment ? `${activeNav}/${segment}` : activeNav); }} sx={(theme) => ({ width: SUB_NAV_WIDTH, py: 1, px: 0.5, borderRadius: 2, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 0.5, color: active ? theme.palette.primary.main : theme.palette.text.secondary, bgcolor: active ? theme.palette.action.selected : 'transparent', '&:hover': { bgcolor: theme.palette.action.hover, color: theme.palette.primary.main, }, })} > {label ? ( {label} ) : null} ); })} ); } } export default function AppShell() { const navigate = useNavigate(); const { pathname } = useLocation(); const activeNav = resolveActiveNav(pathname); const activeSub = activeNav ? resolveActiveSub(pathname, activeNav) : null; return ( ({ flexGrow: 1, display: 'flex', gap: 2, py: 4, px: 3, bgcolor: theme.nav.mainBackground, minWidth: 0, })} > ); }