89 lines
4.0 KiB
JavaScript
89 lines
4.0 KiB
JavaScript
import ChevronDownIcon from '@heroicons/react/24/outline/ChevronDownIcon';
|
|
import { useEffect, useState } from 'react';
|
|
import { NavLink, useLocation } from 'react-router-dom';
|
|
import { useSelector } from 'react-redux';
|
|
|
|
function SidebarSubmenu({ submenu, name, icon, closeMobileSidebar }) {
|
|
const location = useLocation();
|
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
// ดึง Role จาก Redux
|
|
const userRole = useSelector(state => state.auth.role);
|
|
|
|
// ฟังก์ชันตรวจสอบสิทธิ์
|
|
const canAccess = (requiredRole) => {
|
|
// userRole ที่มาจาก Redux ควรเป็นตัวพิมพ์ใหญ่แล้ว
|
|
if (!requiredRole) return true;
|
|
|
|
const allowedRoles = Array.isArray(requiredRole)
|
|
? requiredRole
|
|
: [requiredRole];
|
|
|
|
return allowedRoles.includes(userRole);
|
|
};
|
|
|
|
// เปิด Submenu หาก Path ปัจจุบันอยู่ใน Submenu นั้น
|
|
useEffect(() => {
|
|
// ตรวจสอบว่ามีเมนูย่อยใดที่ผู้ใช้เข้าถึงได้และเป็น Path ปัจจุบันหรือไม่
|
|
const isActive = submenu.some(
|
|
// ใช้ userRole ใน canAccess
|
|
m => canAccess(m.requiredRole) && m.path === location.pathname
|
|
);
|
|
if (isActive) {
|
|
setIsExpanded(true);
|
|
}
|
|
}, [location.pathname, submenu, userRole]);
|
|
|
|
return (
|
|
<div className='flex flex-col'>
|
|
{/** Route header */}
|
|
<a
|
|
className='w-full block cursor-pointer flex items-center justify-between text-base'
|
|
onClick={() => setIsExpanded(!isExpanded)}
|
|
>
|
|
<div className="flex items-center">
|
|
{icon}
|
|
<span className="ml-3 whitespace-nowrap">{name}</span>
|
|
</div>
|
|
<ChevronDownIcon
|
|
className={'w-5 h-5 mt-1 float-right delay-400 duration-500 transition-all ' +
|
|
(isExpanded ? 'rotate-180' : '')}
|
|
/>
|
|
</a>
|
|
|
|
{/** Submenu list */}
|
|
<div className={` w-full ` + (isExpanded ? "" : "hidden")}>
|
|
<ul className={`menu menu-compact`}>
|
|
{submenu.map((m, k) => {
|
|
// กรองเมนูย่อยตามสิทธิ์ (RBAC)
|
|
if (!canAccess(m.requiredRole)) return null;
|
|
|
|
return (
|
|
<li key={k}>
|
|
{/* ใช้ NavLink เพื่อแสดงสถานะ Active และใช้ onClick เพื่อปิด Sidebar (สำหรับ Mobile) */}
|
|
<NavLink
|
|
to={m.path}
|
|
onClick={closeMobileSidebar}
|
|
className={({ isActive }) =>
|
|
`text-base ${isActive ? 'bg-base-200 text-primary font-semibold' : 'hover:bg-base-400'}`
|
|
}
|
|
>
|
|
{m.icon} {m.name}
|
|
|
|
{/* แถบสี Primary แสดงสถานะ Active */}
|
|
{location.pathname === m.path ? (
|
|
<span
|
|
className="absolute mt-1 mb-1 inset-y-0 left-0 w-1 rounded-tr-md rounded-br-md bg-primary "
|
|
aria-hidden="true"
|
|
></span>
|
|
) : null}
|
|
</NavLink>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default SidebarSubmenu; |