61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
// Sidebar Navigation Component
|
|
import { NavLink } from 'react-router-dom';
|
|
import { ReactNode } from 'react';
|
|
import { clsx } from 'clsx';
|
|
import { useAuthStore } from '@/stores/authStore';
|
|
import './SidebarNavigation.css';
|
|
|
|
interface NavItem {
|
|
path: string;
|
|
label: string;
|
|
icon?: ReactNode;
|
|
badge?: number;
|
|
permission?: string;
|
|
}
|
|
|
|
interface SidebarNavigationProps {
|
|
items: NavItem[];
|
|
collapsed?: boolean;
|
|
onToggle?: () => void;
|
|
}
|
|
|
|
export default function SidebarNavigation({ items, collapsed = false, onToggle }: SidebarNavigationProps) {
|
|
const { checkPermission } = useAuthStore();
|
|
|
|
const visibleItems = items.filter((item) => !item.permission || checkPermission(item.permission));
|
|
|
|
return (
|
|
<nav className={clsx('sidebar', { 'sidebar--collapsed': collapsed })}>
|
|
<div className="sidebar__header">
|
|
<h2 className="sidebar__title">DBIS Admin</h2>
|
|
{onToggle && (
|
|
<button className="sidebar__toggle" onClick={onToggle} aria-label="Toggle sidebar">
|
|
☰
|
|
</button>
|
|
)}
|
|
</div>
|
|
<ul className="sidebar__list">
|
|
{visibleItems.map((item) => (
|
|
<li key={item.path}>
|
|
<NavLink
|
|
to={item.path}
|
|
className={({ isActive }) =>
|
|
clsx('sidebar__link', {
|
|
'sidebar__link--active': isActive,
|
|
})
|
|
}
|
|
>
|
|
{item.icon && <span className="sidebar__icon">{item.icon}</span>}
|
|
<span className="sidebar__label">{item.label}</span>
|
|
{item.badge !== undefined && item.badge > 0 && (
|
|
<span className="sidebar__badge">{item.badge}</span>
|
|
)}
|
|
</NavLink>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</nav>
|
|
);
|
|
}
|
|
|