357 lines
14 KiB
JavaScript
357 lines
14 KiB
JavaScript
/* eslint-disable no-unused-vars */
|
|
import CloseIcon from "@mui/icons-material/Close";
|
|
import {
|
|
Accordion,
|
|
AccordionDetails,
|
|
AccordionSummary,
|
|
Box,
|
|
List,
|
|
ListItem,
|
|
ListItemText,
|
|
} from "@mui/material";
|
|
import React, { useEffect, useState } from "react";
|
|
import { NavLink, useLocation } from "react-router-dom";
|
|
|
|
/* ------------------- Custom Imports ------------------- */
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import arrowDownImg from "../../../assets/images/icon/arrow-down.svg"; // Make sure this path is correct
|
|
import companyLogo from "../../../assets/images/logo/app.svg"; // Make sure this path is correct
|
|
import { HIDE_FUNCTIONALITY } from "../../../common/envVariables";
|
|
import { CLINIC_STATUS, HIDE_MODULES } from "../../../constants";
|
|
import { isBSPortal } from "../../../utils/share";
|
|
import { hideAndShowFunctionality } from "../../../views/Signup/signupAction";
|
|
import { useStyles } from "../mainLayoutStyles";
|
|
// Import the configuration from the separate file
|
|
import { SIDEBAR_CONFIG } from "./sideBarConfig"; // Adjust path if necessary
|
|
import {
|
|
selectClinicStatus,
|
|
selectUserRole,
|
|
} from "../../../redux/userRoleSlice";
|
|
|
|
// NOTE: Removed the internal SIDEBAR_ITEMS definition.
|
|
// We will now use the imported SIDEBAR_CONFIG.
|
|
|
|
// NOTE: Removed direct icon imports as they should come from SIDEBAR_CONFIG
|
|
// Ensure @mui/icons-material is installed and icons are correctly referenced in sideBarConfig.js
|
|
|
|
const Sidebar = ({ onClose, showCloseIcon }) => {
|
|
const classes = useStyles();
|
|
const location = useLocation();
|
|
const { isSuperAdmin } = isBSPortal();
|
|
const [activeLink, setActiveLink] = useState("Dashboard");
|
|
const [accordianActiveLink, setAccordianActiveLink] = useState("All Jobs");
|
|
const [parentRoute, setParentRoute] = useState("");
|
|
const [childRoute, setchildRoute] = useState("");
|
|
const [combinedRoute, setcombinedRoute] = useState("");
|
|
const dispatch = useDispatch();
|
|
const clinicStatus = useSelector(selectClinicStatus);
|
|
|
|
// Assuming companyStatus is fetched or defined elsewhere correctly
|
|
const companyStatus = "APPROVED"; // Example status, replace with actual logic if needed
|
|
|
|
const handleHideFeatures = (hideFeatures) => {
|
|
if (hideFeatures) {
|
|
dispatch(hideAndShowFunctionality({ hideFeatures }));
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
const { pathname } = location;
|
|
// Ensure pathname splitting is safe
|
|
const pathParts = pathname?.split?.("/") ?? [];
|
|
const activeLinkFromPath = pathParts[1] ?? ""; // Default to empty string if no segment
|
|
const accordianActiveLinkFromPath = pathParts[2]; // Can be undefined
|
|
|
|
if (accordianActiveLinkFromPath) {
|
|
setParentRoute(activeLinkFromPath);
|
|
setchildRoute(accordianActiveLinkFromPath);
|
|
setcombinedRoute(`${activeLinkFromPath}/${accordianActiveLinkFromPath}`);
|
|
} else {
|
|
setParentRoute(""); // Reset if no child route
|
|
setchildRoute("");
|
|
setcombinedRoute("");
|
|
}
|
|
|
|
// Set active link based on the first path segment, default to '' which matches Dashboard path
|
|
setActiveLink(activeLinkFromPath || ""); // Use '' for Dashboard path
|
|
// Set accordion active link based on the full path segment if available
|
|
setAccordianActiveLink(activeLinkFromPath ? `${activeLinkFromPath}` : "");
|
|
}, [location]);
|
|
|
|
// Get companyId at the component level
|
|
const companyId = useSelector(
|
|
(state) => state?.loginAsCompanyAdmin?.companyId // Make sure this selector path is correct
|
|
);
|
|
|
|
// Get current user role from Redux store
|
|
const userRole = useSelector((state) => state.userRole.role);
|
|
|
|
// Function to determine visibility and render a single sidebar item link
|
|
// The checkVisibility function with fixed logic
|
|
const checkVisibility = (item, i) => {
|
|
// Check if the user has the necessary role for this item
|
|
const hasRole = !item.roles || item.roles.includes(userRole);
|
|
|
|
// Only render if user has the required role
|
|
if (hasRole) {
|
|
// Determine if the link should be disabled
|
|
// FIXED LOGIC: If clinic status is rejected, only allow "/" and "/docs" paths
|
|
const isDisabled = (clinicStatus === "rejected" || clinicStatus === "under_review" || clinicStatus === "payment_due") && !(item.path == "" || item.path == "docs");
|
|
|
|
// Set the correct target path
|
|
const targetPath = isDisabled ? "#" : `/${item.path}`;
|
|
const isActive = activeLink === item.path; // Check if this link is the active one
|
|
|
|
return (
|
|
<Box
|
|
className={classes.marginBottom}
|
|
onClick={() => handleHideFeatures(isDisabled)} // Pass isDisabled to handleHideFeatures
|
|
key={item.path || i} // Use a stable key like item.path
|
|
>
|
|
<NavLink
|
|
className={`${isActive ? classes.activeLink : ""} ${
|
|
classes.textDecorationNone
|
|
} ${isDisabled ? classes.disabledLink : ""}`}
|
|
to={targetPath}
|
|
// Prevent navigation for disabled links
|
|
onClick={(e) => {
|
|
if (isDisabled) e.preventDefault();
|
|
handleLinkClick(item.path); // Set active link on click
|
|
}}
|
|
>
|
|
<ListItem
|
|
button // Make it clear it's clickable
|
|
className={`${classes.listItem} ${
|
|
isActive && classes.activeLink
|
|
}`}
|
|
disabled={isDisabled} // Visually disable the ListItem as well
|
|
>
|
|
<Box className={classes.sidebarListImg}>
|
|
{isActive
|
|
? React.createElement(item.activeIcon, {
|
|
className: classes.sidebarLinkIcons,
|
|
})
|
|
: React.createElement(item.icon, {
|
|
className: classes.sidebarLinkIcons,
|
|
style: { color: "black" },
|
|
})}
|
|
</Box>
|
|
<ListItemText
|
|
primary={item.text}
|
|
primaryTypographyProps={{
|
|
className: isActive
|
|
? classes.activeLinkTextColor
|
|
: classes.normalLinkTextColor,
|
|
}}
|
|
/>
|
|
</ListItem>
|
|
</NavLink>
|
|
</Box>
|
|
);
|
|
}
|
|
return null; // Return null if item shouldn't be rendered
|
|
};
|
|
|
|
// Function to render a sidebar item that has children (accordion)
|
|
const rendersideMenu = (item, i) => {
|
|
// Check if the parent item has the necessary role
|
|
const hasParentRole = !item.roles || item.roles.includes(userRole);
|
|
|
|
// Only proceed if the parent item has the necessary role
|
|
if (!hasParentRole) return null;
|
|
|
|
// Filter visible children first
|
|
const visibleChildren = item.children
|
|
?.filter((childItem) => {
|
|
// Check if child has the necessary role
|
|
const hasChildRole =
|
|
!childItem.roles || childItem.roles.includes(userRole);
|
|
return hasChildRole;
|
|
})
|
|
.filter(Boolean); // Filter out any null/undefined results
|
|
|
|
// Only render the accordion if there are visible children
|
|
if (!visibleChildren || visibleChildren.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
// Check if the current parent route matches this accordion item's path
|
|
const isParentActive =
|
|
activeLink === parentRoute && item.path === parentRoute;
|
|
|
|
return (
|
|
<React.Fragment key={item.path || i}>
|
|
{" "}
|
|
{/* Use stable key */}
|
|
<Accordion
|
|
disableGutters
|
|
elevation={0}
|
|
className={`${classes.accordionDiv} ${classes.marginBottom}`}
|
|
// Control expanded state based on parentRoute matching item.path
|
|
expanded={item.path === parentRoute}
|
|
// Prevent accordion expansion/collapse if parent link is clicked directly?
|
|
// onChange={(event, isExpanded) => {
|
|
// // Handle accordion expansion logic if needed, e.g., update parentRoute
|
|
// // setParentRoute(isExpanded ? item.path : "");
|
|
// }}
|
|
>
|
|
<AccordionSummary
|
|
className={`${classes.listItem} ${
|
|
isParentActive ? classes.activeLink : "" // Apply active styles based on parentRoute
|
|
} ${classes.accordionSummary}`}
|
|
expandIcon={
|
|
<Box>
|
|
<img src={arrowDownImg} alt="Expand" />
|
|
</Box>
|
|
}
|
|
// Clicking the summary might navigate or just expand/collapse
|
|
// Consider if clicking the summary should set the activeLink or parentRoute
|
|
onClick={() => {
|
|
// Toggle parent route or handle navigation
|
|
// If clicking the parent should navigate, handle it here
|
|
// If it just expands/collapses, maybe update parentRoute state
|
|
setParentRoute(item.path === parentRoute ? "" : item.path); // Basic toggle example
|
|
}}
|
|
>
|
|
<Box className={classes.sidebarListImg}>
|
|
{/* Use the helper function to render the icon */}
|
|
{activeLink === item.path
|
|
? React.createElement(item.activeIcon, {
|
|
className: classes.sidebarLinkIcons,
|
|
})
|
|
: React.createElement(item.icon, {
|
|
className: classes.sidebarLinkIcons,
|
|
style: { color: "black" },
|
|
})}
|
|
</Box>
|
|
{/* Removed redundant Box wrapping ListItem */}
|
|
<ListItemText
|
|
primary={item.text}
|
|
primaryTypographyProps={{
|
|
className: isParentActive
|
|
? classes.activeLinkTextColor
|
|
: classes.normalLinkTextColor,
|
|
}}
|
|
/>
|
|
</AccordionSummary>
|
|
<AccordionDetails>
|
|
<List component="div" disablePadding className={classes.listClass}>
|
|
{/* Removed unnecessary <ul> */}
|
|
{visibleChildren.map((subItem, subIndex) => {
|
|
// Determine if the sub-item link should be disabled
|
|
const isSubDisabled =
|
|
!isSuperAdmin && companyStatus !== CLINIC_STATUS.APPROVED; // Add hideFeature logic if needed for sub-items
|
|
const subTargetPath = isSubDisabled ? "#" : `/${subItem.path}`;
|
|
const isSubActive = combinedRoute === subItem.path; // Check if this child link is active
|
|
|
|
return (
|
|
<NavLink
|
|
key={subItem.path || subIndex} // Use stable key
|
|
to={subTargetPath}
|
|
className={classes.textDecorationNone}
|
|
onClick={(e) => {
|
|
if (isSubDisabled) e.preventDefault();
|
|
// Set parent and child routes on click
|
|
setParentRoute(item.path); // Ensure parent is marked active
|
|
setchildRoute(subItem.path.split("/")[1]); // Extract child part
|
|
handleAccordianLinkClick(subItem.path); // Update combined route state
|
|
}}
|
|
>
|
|
{/* Use ListItem for better structure and accessibility */}
|
|
<ListItem
|
|
button
|
|
key={subItem.path || subIndex}
|
|
disableRipple={true}
|
|
className={classes.dotOuterDiv} // Apply styling class to ListItem
|
|
disabled={isSubDisabled}
|
|
>
|
|
<div
|
|
className={`${classes.dotInnerDiv} ${
|
|
isSubActive
|
|
? classes.activeLinkChildrenBackgroundColor
|
|
: classes.normalLinkChildrenBackgroundColor
|
|
}`}
|
|
></div>
|
|
<ListItemText
|
|
primary={subItem.text}
|
|
primaryTypographyProps={{
|
|
className: isSubActive
|
|
? classes.activeLinkChildrenTextColor
|
|
: classes.normalLinkChildrenTextColor,
|
|
}}
|
|
/>
|
|
</ListItem>
|
|
</NavLink>
|
|
);
|
|
})}
|
|
{/* Removed unnecessary </ul> */}
|
|
</List>
|
|
</AccordionDetails>
|
|
</Accordion>
|
|
</React.Fragment>
|
|
);
|
|
};
|
|
|
|
const closeSidebar = () => {
|
|
if (onClose) {
|
|
// Check if onClose is provided
|
|
onClose();
|
|
}
|
|
};
|
|
|
|
// Sets the main active link (top-level or parent of accordion)
|
|
const handleLinkClick = (linkPath) => {
|
|
// If the clicked link is part of an accordion, don't reset parentRoute
|
|
const clickedItem = SIDEBAR_CONFIG.find((item) => item.path === linkPath);
|
|
if (!clickedItem?.children) {
|
|
setParentRoute(""); // Reset parent route if it's a top-level link
|
|
setchildRoute(""); // Reset child route
|
|
setcombinedRoute(""); // Reset combined route
|
|
}
|
|
setActiveLink(linkPath);
|
|
};
|
|
|
|
// Sets the active state for accordion children links
|
|
const handleAccordianLinkClick = (fullPath) => {
|
|
// Accordion link click implies a parent is active
|
|
// We already set parentRoute and childRoute in the NavLink onClick
|
|
setcombinedRoute(fullPath); // Update the combined route state
|
|
// Optionally update activeLink to the parent path if needed for styling
|
|
// setActiveLink(fullPath.split('/')[0]);
|
|
};
|
|
|
|
return (
|
|
<Box className={classes.sidebarMain}>
|
|
{/* Only show close icon if prop is true */}
|
|
{showCloseIcon && (
|
|
<Box sx={{ textAlign: "right", padding: 1 }}>
|
|
{" "}
|
|
{/* Added some padding/alignment */}
|
|
<CloseIcon
|
|
className={classes.blackColor} // Ensure this class provides styling
|
|
onClick={closeSidebar}
|
|
sx={{ cursor: "pointer" }} // Make it look clickable
|
|
/>
|
|
</Box>
|
|
)}
|
|
<Box className={classes.companyImgDiv}>
|
|
{/* Ensure companyLogo is imported correctly and alt text is descriptive */}
|
|
<img
|
|
className={classes.companyImg}
|
|
src={companyLogo}
|
|
alt="Company Logo"
|
|
/>
|
|
</Box>
|
|
{/* Use the imported SIDEBAR_CONFIG */}
|
|
<List className={classes?.listMainDiv}>
|
|
{SIDEBAR_CONFIG?.map((item, i) =>
|
|
// Render either an accordion menu or a direct link
|
|
item.children ? rendersideMenu(item, i) : checkVisibility(item, i)
|
|
)}
|
|
</List>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default Sidebar;
|