import { Link, useLocation } from "react-router-dom"; import { LayoutDashboard, Building2, Users, Package, FileText, Settings, HelpCircle, X, Shield, BadgeCheck, GitBranch, } from "lucide-react"; import { cn } from "@/lib/utils"; import { useAppSelector } from "@/hooks/redux-hooks"; import { useTenantTheme } from "@/hooks/useTenantTheme"; import { AuthenticatedImage } from "@/components/shared"; 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: Building2, label: "Departments", path: "/tenant/departments", requiredPermission: { resource: "departments" }, }, { icon: BadgeCheck, label: "Designations", path: "/tenant/designations", requiredPermission: { resource: "designations" }, }, { icon: GitBranch, label: "Workflow Definitions", path: "/tenant/workflow-definitions", requiredPermission: { resource: "workflow" }, }, { icon: Users, label: "Suppliers", path: "/tenant/suppliers", requiredPermission: { resource: "supplier" }, }, { 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 */} ); };