CoffeeJoo_Panel_kafeDar/src/components/layout/Sidebar/sidebar.jsx

180 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Link, useLocation, useNavigate } from "react-router-dom";
import { useState, useEffect } from "react";
import LogoDM from "../../../assets/icons/LogoDM.svg";
import LogoLM from "../../../assets/icons/Logo-LM.svg";
import { BiBarChartAlt2 } from "react-icons/bi";
import { AiOutlinePieChart } from "react-icons/ai";
import { PiCoffee } from "react-icons/pi";
import { HiOutlineLogout } from "react-icons/hi";
import { FiMenu, FiX } from "react-icons/fi";
const SIDEBAR = {
navigation: [
{
id: 'dashboard',
path: '/dashboard',
icon: BiBarChartAlt2,
label: 'داشبورد',
},
{
id: 'cafe-management',
path: '/cafe-management',
icon: PiCoffee,
label: 'مدیریت کافه ها',
},
{
id: 'stats',
path: '/stats',
icon: AiOutlinePieChart,
label: 'آمار و تحلیل',
},
],
logout: {
icon: HiOutlineLogout,
label: 'خروج',
},
styles: {
activeColor: 'primary',
inactiveColor: '#402E32',
borderColor: '#D9CAB3',
padding: 'p-2.5',
gap: 'gap-2.5',
rounded: 'rounded-lg',
},
};
export default function Sidebar({ className, isOpen, setIsOpen }) {
const location = useLocation();
const navigate = useNavigate();
const [currentLogo, setCurrentLogo] = useState(localStorage.getItem('theme') === 'light' ? LogoDM : LogoLM);
useEffect(() => {
const observer = new MutationObserver(() => {
setCurrentLogo(localStorage.getItem('theme') === 'light' ? LogoDM : LogoLM);
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
});
return () => observer.disconnect();
}, []);
const isActive = (path) => location.pathname === path;
const handleLogout = () => {
try {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('token');
localStorage.removeItem('adminInfo');
navigate('/login');
} catch (error) {
console.error('Logout error:', error);
navigate('/login');
}
};
const closeSidebar = () => setIsOpen(false);
const renderNavItem = (item) => {
const Icon = item.icon;
const active = isActive(item.path);
return (
<Link
key={item.id}
to={item.path}
onClick={closeSidebar}
className={`group flex items-center ${SIDEBAR.styles.gap} ${SIDEBAR.styles.rounded} ${SIDEBAR.styles.padding} transition-all duration-200 ${active
? `bg-primary shadow-md`
: `hover:bg-primary hover:text-text2`
}`}
>
<Icon
className={`w-5 h-5 flex-shrink-0 text-text1 transition-colors ${active
? "text-white"
: `text-[${SIDEBAR.styles.inactiveColor}] group-hover:text-white`
}`}
/>
<span
className={`text-sm font-medium transition-colors ${active
? "text-text2"
: ` text-text1 group-hover:text-white`
}`}
>
{item.label}
</span>
</Link>
);
};
return (
<>
<div className="lg:hidden fixed top-0 px-6 bg-header right-0 left-0 z-[70] flex justify-between p-3">
<button
onClick={() => setIsOpen(true)}
className=" text-primary"
aria-label="Toggle menu"
>
<FiMenu className="w-6 h-6" />
</button>
<img src={currentLogo} className="h-12 w-12 " alt="Logo" />
</div>
{isOpen && (
<div
className="lg:hidden fixed inset-0 bg-black/50 z-[60]"
onClick={closeSidebar}
/>
)}
<aside
dir="rtl"
className={`${className}
transition-transform duration-300 ease-in-out
${isOpen ? 'translate-x-0' : 'translate-x-full'}
lg:translate-x-0 lg:w-[220px] bg-header
`}
>
<button
onClick={() => setIsOpen(false)}
className="lg:hidden absolute top-4 right-4 z-[70] text-primary p-2.5"
aria-label="Toggle menu"
>
<FiX className="w-6 h-6" />
</button>
<div className="flex justify-center mt-5 mb-2">
<img src={currentLogo} className="h-10 w-10 lg:h-16 lg:w-16" alt="Logo" />
</div>
<nav className="flex-1 px-3 mt-6 space-y-3 overflow-y-auto">
{SIDEBAR.navigation.map(renderNavItem)}
</nav>
<div className={`p-3 border-t border-[${SIDEBAR.styles.borderColor}]`}>
<button
onClick={() => {
handleLogout();
closeSidebar();
}}
className={`group flex items-center ${SIDEBAR.styles.gap} ${SIDEBAR.styles.rounded} ${SIDEBAR.styles.padding} transition-all duration-200 hover:bg-button1 w-full`}
>
{(() => {
const LogoutIcon = SIDEBAR.logout.icon;
return <LogoutIcon className="w-5 h-5 flex-shrink-0 text-[#402E32] transition-colors group-hover:text-white" />;
})()}
<span className="text-sm text-[#402E32] font-medium transition-colors group-hover:text-white">
{SIDEBAR.logout.label}
</span>
</button>
</div>
</aside>
</>
);
};