140 lines
3.8 KiB
JavaScript
140 lines
3.8 KiB
JavaScript
import { useState, useEffect } from "react";
|
|
import { Link, useLocation } from "react-router-dom";
|
|
import PropTypes from "prop-types";
|
|
import { Sidebar as ProSidebar, Menu, MenuItem, SubMenu } from "react-pro-sidebar";
|
|
import { fetchMenuItems } from "../../APIServices/MenuAPI";
|
|
import routes from "routes.js";
|
|
import "../Sidebar/Sidebar.css";
|
|
|
|
const Sidebar = (props) => {
|
|
const [menuItems, setMenuItems] = useState([]);
|
|
const [collapsed, setCollapsed] = useState(false);
|
|
const [error, setError] = useState("");
|
|
const location = useLocation();
|
|
|
|
useEffect(() => {
|
|
loadMenuItems();
|
|
}, []);
|
|
|
|
const loadMenuItems = async () => {
|
|
try {
|
|
const respdata = await fetchMenuItems();
|
|
const data = respdata.data;
|
|
if (Array.isArray(data)) {
|
|
const dynamicRoutes = mapMenuToRoutes(data);
|
|
setMenuItems(dynamicRoutes);
|
|
} else if (data && typeof data === "object") {
|
|
const dynamicRoutes = mapMenuToRoutes([data]);
|
|
setMenuItems(dynamicRoutes);
|
|
} else {
|
|
console.error("Invalid menu data format:", data);
|
|
setError("Invalid menu data format.");
|
|
}
|
|
} catch (err) {
|
|
console.error("Error fetching menu items:", err);
|
|
setError(err.message || "Failed to fetch menu items.");
|
|
}
|
|
};
|
|
|
|
const mapMenuToRoutes = (menuArray) => {
|
|
if (!Array.isArray(menuArray)) {
|
|
console.error('Expected an array for menuArray, received:', menuArray);
|
|
return [];
|
|
}
|
|
|
|
return menuArray.map(menu => ({
|
|
path: menu.path || '#',
|
|
name: menu.name || menu.menuName || '',
|
|
icon: menu.icon || 'bi bi-grid',
|
|
submenu: Array.isArray(menu.submenu) ? mapMenuToRoutes(menu.submenu) : []
|
|
}));
|
|
};
|
|
|
|
const toggleSidebar = () => {
|
|
setCollapsed(!collapsed);
|
|
if (props.onSidebarToggle) {
|
|
props.onSidebarToggle(!collapsed);
|
|
}
|
|
};
|
|
|
|
const renderMenuItems = () => {
|
|
const allRoutes = [...routes, ...menuItems];
|
|
|
|
return allRoutes.map((route, key) => {
|
|
if (route.submenu && route.submenu.length > 0) {
|
|
return (
|
|
<SubMenu
|
|
key={key}
|
|
label={route.name}
|
|
icon={<i className={route.icon} />}
|
|
>
|
|
{route.submenu.map((submenu, subKey) => (
|
|
<MenuItem
|
|
key={`${key}-${subKey}`}
|
|
component={<Link to={submenu.path} />}
|
|
icon={<i className={submenu.icon || "bi bi-grid"} />}
|
|
>
|
|
{submenu.name}
|
|
</MenuItem>
|
|
))}
|
|
</SubMenu>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<MenuItem
|
|
key={key}
|
|
component={<Link to={route.path} />}
|
|
icon={<i className={route.icon || "bi bi-grid"} />}
|
|
>
|
|
{route.name}
|
|
</MenuItem>
|
|
);
|
|
});
|
|
};
|
|
|
|
const { logo } = props;
|
|
|
|
return (
|
|
<div className="sidebar-wrapper">
|
|
<ProSidebar
|
|
collapsed={collapsed}
|
|
className="app-sidebar"
|
|
backgroundColor="white"
|
|
width="220px"
|
|
collapsedWidth="30px"
|
|
>
|
|
<div className="sidebar-header">
|
|
{/* {logo && (
|
|
<Link to={logo.innerLink} className="logo-container">
|
|
<img alt={logo.imgAlt} className="navbar-brand-img" src={logo.imgSrc} />
|
|
</Link>
|
|
)} */}
|
|
<button
|
|
className="sidebar-toggle-btn"
|
|
type="button"
|
|
onClick={toggleSidebar}
|
|
title={collapsed ? "Expand sidebar" : "Collapse sidebar"}
|
|
>
|
|
<i className={`bi ${collapsed ? "bi-chevron-right" : "bi-chevron-left"}`} />
|
|
</button>
|
|
</div>
|
|
|
|
<Menu>
|
|
{renderMenuItems()}
|
|
</Menu>
|
|
</ProSidebar>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
Sidebar.defaultProps = {
|
|
logo: {},
|
|
};
|
|
|
|
Sidebar.propTypes = {
|
|
logo: PropTypes.object,
|
|
onSidebarToggle: PropTypes.func,
|
|
};
|
|
|
|
export default Sidebar; |