import { Link, useLocation } from 'react-router-dom'; import { LayoutDashboard, Building2, Users, Package, FileText, Settings, HelpCircle, X, Shield } from 'lucide-react'; import { cn } from '@/lib/utils'; import { useAppSelector } from '@/hooks/redux-hooks'; import { useTenantTheme } from '@/hooks/useTenantTheme'; interface MenuItem { icon: React.ComponentType<{ className?: string }>; label: string; path: string; requiredPermission?: { resource: string; action?: string; // If not provided, checks for '*' or 'read' }; } interface SidebarProps { isOpen: boolean; onClose: () => void; } // Super Admin menu items const superAdminPlatformMenu: MenuItem[] = [ { icon: LayoutDashboard, label: 'Dashboard', path: '/dashboard' }, { icon: Building2, label: 'Tenants', path: '/tenants' }, // { icon: Users, label: 'User Management', path: '/users' }, // { icon: Shield, label: 'Roles', path: '/roles' }, { icon: Package, label: 'Modules', path: '/modules' }, ]; const superAdminSystemMenu: MenuItem[] = [ { icon: FileText, label: 'Audit Logs', path: '/audit-logs' }, // { icon: Settings, label: 'Settings', path: '/settings' }, ]; // Tenant Admin menu items const tenantAdminPlatformMenu: MenuItem[] = [ { icon: LayoutDashboard, label: 'Dashboard', path: '/tenant' }, { icon: Shield, label: 'Roles', path: '/tenant/roles', requiredPermission: { resource: 'roles' } }, { icon: Users, label: 'Users', path: '/tenant/users', requiredPermission: { resource: 'users' } }, { icon: Package, label: 'Modules', path: '/tenant/modules' }, ]; const tenantAdminSystemMenu: MenuItem[] = [ { icon: FileText, label: 'Audit Logs', path: '/tenant/audit-logs', requiredPermission: { resource: 'audit_logs' } }, { icon: Settings, label: 'Settings', path: '/tenant/settings', requiredPermission: { resource: 'tenants' } }, ]; export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { const location = useLocation(); const { roles, permissions } = useAppSelector((state) => state.auth); const { theme, logoUrl } = useAppSelector((state) => state.theme); // Fetch theme for tenant admin const isSuperAdminCheck = () => { let rolesArray: string[] = []; if (Array.isArray(roles)) { rolesArray = roles; } else if (typeof roles === 'string') { try { rolesArray = JSON.parse(roles); } catch { rolesArray = []; } } return rolesArray.includes('super_admin'); }; const isSuperAdmin = isSuperAdminCheck(); // Get role name for display const getRoleName = (): string => { if (isSuperAdmin) { return 'Super Admin'; } let rolesArray: string[] = []; if (Array.isArray(roles)) { rolesArray = roles; } else if (typeof roles === 'string') { try { rolesArray = JSON.parse(roles); } catch { rolesArray = []; } } // Get the first role and format it if (rolesArray.length > 0) { const role = rolesArray[0]; // Convert snake_case to Title Case return role .split('_') .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) .join(' '); } return 'User'; }; const roleName = getRoleName(); // Fetch theme if tenant admin if (!isSuperAdmin) { useTenantTheme(); } // Helper function to check if user has permission for a resource const hasPermission = (resource: string, requiredAction?: string): boolean => { if (isSuperAdmin) { return true; // Super admin has all permissions } const allowedActions = requiredAction ? [requiredAction] : ['*', 'read']; return permissions.some((perm) => { // Check if resource matches (exact match or wildcard) const resourceMatches = perm.resource === resource || perm.resource === '*'; // Check if action matches (exact match or wildcard) const actionMatches = allowedActions.some( (allowedAction) => perm.action === allowedAction || perm.action === '*' ); return resourceMatches && actionMatches; }); }; // Filter menu items based on permissions for tenant users const filterMenuItems = (items: MenuItem[]): MenuItem[] => { if (isSuperAdmin) { return items; // Show all items for super admin } return items.filter((item) => { // If no required permission, always show (e.g., Dashboard, Modules, Settings) if (!item.requiredPermission) { return true; } return hasPermission( item.requiredPermission.resource, item.requiredPermission.action ); }); }; // Select and filter menu items based on role and permissions const platformMenu = filterMenuItems( isSuperAdmin ? superAdminPlatformMenu : tenantAdminPlatformMenu ); const systemMenu = filterMenuItems( isSuperAdmin ? superAdminSystemMenu : tenantAdminSystemMenu ); const MenuSection = ({ title, items }: { title: string; items: MenuItem[] }) => (
{title}
{items.map((item) => { const Icon = item.icon; const isActive = location.pathname === item.path; return ( { // Close sidebar on mobile when navigating if (window.innerWidth < 768) { onClose(); } }} className={cn( 'flex items-center gap-2 md:gap-2 lg:gap-2.5 px-2 md:px-2 lg:px-3 py-2 rounded-md transition-colors min-h-[44px]', isActive ? 'shadow-[0px_2px_8px_0px_rgba(15,23,42,0.15)]' : 'text-[#0f1724] hover:bg-gray-50' )} style={ isActive ? { backgroundColor: !isSuperAdmin && theme?.primary_color ? theme.primary_color : '#112868', color: !isSuperAdmin && theme?.secondary_color ? theme.secondary_color : '#23dce1', } : undefined } > {item.label} ); })}
); return ( <> {/* Mobile Sidebar */} {/* Desktop Sidebar */} ); };