211 lines
7.3 KiB
JavaScript
211 lines
7.3 KiB
JavaScript
import React, { useState, useEffect, useRef } from "react";
|
||
import FullLogo from '../../assets/images/logo.svg?react';
|
||
import MiniLogo from '../../assets/images/system_monitor_icon.svg?react';
|
||
|
||
import {
|
||
Drawer,
|
||
List,
|
||
Typography,
|
||
styled,
|
||
IconButton,
|
||
Tooltip,
|
||
Box
|
||
} from "@mui/material";
|
||
import {
|
||
ChevronLeft,
|
||
ChevronRight,
|
||
Menu as MenuIcon
|
||
} from "@mui/icons-material";
|
||
import MenuItem from "./SidebarMenuComponents/MenuItem";
|
||
import SidebarFooter from "./SidebarMenuComponents/SidebarFooter";
|
||
import { statusManager1 } from "../TreeChart/dataUtils";
|
||
import tabContent from "../TreeChart/tabContent";
|
||
|
||
|
||
const SidebarResizer = styled('div')(({ theme }) => ({
|
||
width: "5px",
|
||
cursor: "ew-resize",
|
||
backgroundColor: 'transparent',
|
||
height: "100%",
|
||
position: "absolute",
|
||
right: 0,
|
||
top: 0,
|
||
transition: 'background-color 0.2s',
|
||
'&:hover': {
|
||
backgroundColor: theme.palette.primary.main,
|
||
},
|
||
zIndex: 2
|
||
}));
|
||
|
||
const SidebarMenu = ({ data, onOpenTab, sidebarWidth, startResizing, collapsed, setCollapsed, isDarkMode, setIsDarkMode }) => {
|
||
const [hovered, setHovered] = useState(false);
|
||
const [menuData, setMenuData] = useState(data);
|
||
const contentCache = useRef({});
|
||
|
||
useEffect(() => {
|
||
if (data) {
|
||
const dataCopy = JSON.parse(JSON.stringify(data));
|
||
statusManager1.updateStatuses(dataCopy);
|
||
setMenuData(dataCopy);
|
||
}
|
||
}, [data]);
|
||
|
||
const handleToggleCollapse = () => {
|
||
setCollapsed(!collapsed);
|
||
};
|
||
|
||
const handleSelectItem = (id, title, children) => {
|
||
onOpenTab(id, title);
|
||
|
||
contentCache.current = tabContent({ items: children }, contentCache.current);
|
||
if (contentCache.current[id]) {
|
||
onOpenTab(id, title, contentCache.current[id].content);
|
||
}
|
||
};
|
||
|
||
|
||
|
||
const drawerWidth = collapsed ? 64 : sidebarWidth;
|
||
|
||
return (
|
||
<Box
|
||
onMouseEnter={() => setHovered(true)}
|
||
onMouseLeave={() => setHovered(false)}
|
||
sx={{
|
||
position: 'relative',
|
||
width: drawerWidth,
|
||
transition: 'width 0.3s ease',
|
||
}}
|
||
>
|
||
<Drawer
|
||
variant="permanent"
|
||
sx={{
|
||
width: drawerWidth,
|
||
flexShrink: 0,
|
||
'& .MuiDrawer-paper': {
|
||
width: drawerWidth,
|
||
boxSizing: "border-box",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
backgroundColor: 'custom.sidebar',
|
||
color: 'custom.sidebarText',
|
||
transition: 'width 0.3s ease',
|
||
overflowX: 'hidden',
|
||
borderRight: 'none'
|
||
},
|
||
}}
|
||
>
|
||
{/* Верхняя часть с логотипом и кнопкой */}
|
||
<Box sx={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'space-between',
|
||
p: 1,
|
||
borderBottom: '1px solid',
|
||
borderColor: 'divider',
|
||
backgroundColor: 'custom.sidebar'
|
||
}}>
|
||
{/* Логотип - центрируется в доступном пространстве */}
|
||
<Box sx={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
flexGrow: 1,
|
||
overflow: 'hidden',
|
||
transition: 'opacity 0.3s ease',
|
||
opacity: collapsed ? 0 : 1,
|
||
width: collapsed ? 0 : 'auto'
|
||
}}>
|
||
<FullLogo style={{
|
||
height: '32px',
|
||
width: 'auto',
|
||
maxWidth: '100%'
|
||
}} />
|
||
</Box>
|
||
|
||
{/* Мини-логотип (только в свернутом состоянии) */}
|
||
{collapsed && (
|
||
<Box sx={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
width: '100%'
|
||
}}>
|
||
<MiniLogo style={{
|
||
height: '24px',
|
||
width: '24px'
|
||
}} />
|
||
</Box>
|
||
)}
|
||
|
||
{/* Кнопка сворачивания/разворачивания */}
|
||
<Tooltip title={collapsed ? "Развернуть меню" : "Свернуть меню"}>
|
||
<IconButton
|
||
onClick={handleToggleCollapse}
|
||
size="small"
|
||
sx={{
|
||
color: 'custom.sidebarText',
|
||
'&:hover': {
|
||
backgroundColor: 'custom.sidebarHover',
|
||
},
|
||
ml: collapsed ? 'auto' : 0 // В свернутом состоянии кнопка центрируется
|
||
}}
|
||
>
|
||
{collapsed ? <ChevronRight /> : <ChevronLeft />}
|
||
</IconButton>
|
||
</Tooltip>
|
||
</Box>
|
||
|
||
{/* Содержимое меню */}
|
||
<Box sx={{
|
||
flexGrow: 1,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
overflow: 'hidden'
|
||
}}>
|
||
<List sx={{
|
||
overflowY: 'auto',
|
||
overflowX: 'hidden',
|
||
flex: '1 1 auto'
|
||
}}>
|
||
{!collapsed && (
|
||
<Typography
|
||
variant="h6"
|
||
sx={{
|
||
p: 2,
|
||
fontWeight: 'bold',
|
||
textAlign: 'center'
|
||
}}
|
||
>
|
||
Меню
|
||
</Typography>
|
||
)}
|
||
{menuData && (
|
||
<MenuItem
|
||
item={menuData}
|
||
onSelectItem={handleSelectItem}
|
||
collapsed={collapsed}
|
||
/>
|
||
)}
|
||
</List>
|
||
|
||
{/* Футер */}
|
||
|
||
<SidebarFooter
|
||
collapsed={collapsed}
|
||
isDarkMode={isDarkMode}
|
||
setIsDarkMode={setIsDarkMode}
|
||
/>
|
||
|
||
</Box>
|
||
|
||
{/* Ресайзер */}
|
||
{!collapsed && (
|
||
<SidebarResizer onMouseDown={startResizing} />
|
||
)}
|
||
</Drawer>
|
||
</Box>
|
||
);
|
||
};
|
||
|
||
export default SidebarMenu; |