initial setup sidebar menus from backend
This commit is contained in:
parent
1772a2fcd1
commit
0df19cb78e
36
src/components/Layout/MenuItemSkeleton.jsx
Normal file
36
src/components/Layout/MenuItemSkeleton.jsx
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
const SkeletonLine = ({ height = 50, width = "100%", className = "" }) => (
|
||||
<div
|
||||
className={`skeleton mb-2 ${className}`}
|
||||
style={{
|
||||
height,
|
||||
width,
|
||||
}}
|
||||
></div>
|
||||
);
|
||||
export const MenuItemSkeleton = ({ hasSubmenu = false, submenuCount = 3 }) => {
|
||||
return (
|
||||
<li className="menu-item">
|
||||
<div className="menu-link d-flex align-items-center gap-2 ">
|
||||
{/* icon placeholder */}
|
||||
<SkeletonLine height={25} width="25px" className="rounded" />
|
||||
{/* text placeholder */}
|
||||
<SkeletonLine height={25} width="100%" />
|
||||
</div>
|
||||
|
||||
{/* Submenu skeletons */}
|
||||
{hasSubmenu && (
|
||||
<ul className="menu-sub mt-1 ms-4">
|
||||
{[...Array(submenuCount)].map((_, idx) => (
|
||||
<li key={idx} className="menu-item">
|
||||
<div className="menu-link d-flex align-items-center gap-2">
|
||||
<SkeletonLine height={20} width="20px" className="rounded" />
|
||||
<SkeletonLine height={24} width="100px" />
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
};
|
@ -2,10 +2,12 @@ import React from "react";
|
||||
import { Link, NavLink, useLocation, useNavigate } from "react-router-dom";
|
||||
import menuData from "../../data/menuData.json";
|
||||
import { getCachedProfileData } from "../../slices/apiDataManager";
|
||||
import { useSidBarMenu } from "../../hooks/useProfile";
|
||||
import { MenuItemSkeleton } from "./MenuItemSkeleton";
|
||||
|
||||
const Sidebar = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { data, isError, isLoading, isFetched } = useSidBarMenu();
|
||||
return (
|
||||
<aside
|
||||
id="layout-menu"
|
||||
@ -33,33 +35,42 @@ const Sidebar = () => {
|
||||
<div className="menu-inner-shadow"></div>
|
||||
|
||||
<ul className="menu-inner py-1">
|
||||
{menuData.map((section) => (
|
||||
<React.Fragment key={(Math.random() + 1).toString(36)}>
|
||||
{section.header && (
|
||||
{isLoading && (
|
||||
<>
|
||||
{[...Array(7)].map((_, idx) => (
|
||||
<MenuItemSkeleton
|
||||
key={idx}
|
||||
hasSubmenu={idx % 2 === 1}
|
||||
submenuCount={Math.floor(Math.random() * 3) + 2}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
{data &&
|
||||
data.map((section) => (
|
||||
<React.Fragment key={(Math.random() + 1).toString(36)}>
|
||||
{/* {section.header && (
|
||||
<li className="menu-header small text-uppercase">
|
||||
<span className="menu-header-text">{section.header}</span>
|
||||
</li>
|
||||
)}
|
||||
{section.items.map(MenuItem)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
)} */}
|
||||
{section.items.map(MenuItem)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</ul>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
const MenuItem = (item) => {
|
||||
item.id = Math.random();
|
||||
const location = useLocation();
|
||||
const isActive = location.pathname === item.link;
|
||||
const hasSubmenu = item.submenu && item.submenu.length > 0;
|
||||
const hasSubmenu = Array.isArray(item.submenu) && item.submenu.length > 0;
|
||||
const isSubmenuActive =
|
||||
hasSubmenu &&
|
||||
item.submenu.some((subitem) => location.pathname === subitem.link);
|
||||
hasSubmenu && item.submenu.some((sub) => location.pathname === sub.link);
|
||||
|
||||
return (
|
||||
<li
|
||||
key={(Math.random() + 1).toString(36)}
|
||||
className={`menu-item ${isActive || isSubmenuActive ? "active" : ""} ${
|
||||
hasSubmenu && isSubmenuActive ? "open" : ""
|
||||
}`}
|
||||
@ -67,21 +78,24 @@ const MenuItem = (item) => {
|
||||
<NavLink
|
||||
aria-label={`Navigate to ${item.text} ${!item.available ? "Pro" : ""}`}
|
||||
to={item.link}
|
||||
className={`menu-link ${item.submenu ? "menu-toggle" : ""}`}
|
||||
key={(Math.random() + 1).toString(36)}
|
||||
target={item.link.includes("http") ? "_blank" : undefined}
|
||||
className={`menu-link ${hasSubmenu ? "menu-toggle" : ""}`}
|
||||
target={item.link?.includes("http") ? "_blank" : undefined}
|
||||
>
|
||||
<i className={`menu-icon tf-icons ${item.icon}`}></i>
|
||||
<div>{item.text}</div>{" "}
|
||||
<div>{item.text}</div>
|
||||
{item.available === false && (
|
||||
<div className="badge bg-label-primary fs-tiny rounded-pill ms-auto">
|
||||
Pro
|
||||
</div>
|
||||
)}
|
||||
</NavLink>
|
||||
{item.submenu && (
|
||||
<ul className="menu-sub" key={(Math.random() + 1).toString(36)}>
|
||||
{item.submenu.map(MenuItem)}
|
||||
|
||||
{/* Only render submenu if exists */}
|
||||
{hasSubmenu && (
|
||||
<ul className="menu-sub">
|
||||
{item.submenu.map((sub) => (
|
||||
<MenuItem key={sub.id || sub.link} {...sub} />
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
|
@ -99,3 +99,13 @@ export const useProfile = () => {
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export const useSidBarMenu = ()=>{
|
||||
const userLogged = useSelector((store)=>store.globalVariables.loginUser);
|
||||
return useQuery({
|
||||
queryKey:["AppMenu"],
|
||||
queryFn:async()=> await AuthRepository.appmenu(),
|
||||
enabled: !!userLogged
|
||||
})
|
||||
}
|
@ -15,6 +15,8 @@ const AuthRepository = {
|
||||
logout: (data) => api.post("/api/auth/logout", data),
|
||||
profile: () => api.get("/api/user/profile"),
|
||||
changepassword: (data) => api.post("/api/auth/change-password", data),
|
||||
appmenu:()=>api.get('/api/AppMenu/sidebar/menu-section')
|
||||
|
||||
};
|
||||
|
||||
export default AuthRepository;
|
||||
|
Loading…
x
Reference in New Issue
Block a user