diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 3ee4237..7692cd6 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -1,4 +1,4 @@ -import { Link, useLocation } from 'react-router-dom'; +import { Link, useLocation } from "react-router-dom"; import { LayoutDashboard, Building2, @@ -9,12 +9,14 @@ import { HelpCircle, X, Shield, - BadgeCheck -} from 'lucide-react'; -import { cn } from '@/lib/utils'; -import { useAppSelector } from '@/hooks/redux-hooks'; -import { useTenantTheme } from '@/hooks/useTenantTheme'; -import { AuthenticatedImage } from '@/components/shared'; + 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 }>; @@ -33,31 +35,67 @@ interface SidebarProps { // Super Admin menu items const superAdminPlatformMenu: MenuItem[] = [ - { icon: LayoutDashboard, label: 'Dashboard', path: '/dashboard' }, - { icon: Building2, label: 'Tenants', path: '/tenants' }, + { 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' }, + { icon: Package, label: "Modules", path: "/modules" }, ]; const superAdminSystemMenu: MenuItem[] = [ - { icon: FileText, label: 'Audit Logs', path: '/audit-logs' }, + { 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: Package, label: 'Modules', path: '/tenant/modules' }, + { 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: 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' } }, + { + 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) => { @@ -70,14 +108,14 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { let rolesArray: string[] = []; if (Array.isArray(roles)) { rolesArray = roles; - } else if (typeof roles === 'string') { + } else if (typeof roles === "string") { try { rolesArray = JSON.parse(roles); } catch { rolesArray = []; } } - return rolesArray.includes('super_admin'); + return rolesArray.includes("super_admin"); }; const isSuperAdmin = isSuperAdminCheck(); @@ -85,12 +123,12 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { // Get role name for display const getRoleName = (): string => { if (isSuperAdmin) { - return 'Super Admin'; + return "Super Admin"; } let rolesArray: string[] = []; if (Array.isArray(roles)) { rolesArray = roles; - } else if (typeof roles === 'string') { + } else if (typeof roles === "string") { try { rolesArray = JSON.parse(roles); } catch { @@ -102,11 +140,13 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { const role = rolesArray[0]; // Convert snake_case to Title Case return role - .split('_') - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) - .join(' '); + .split("_") + .map( + (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(), + ) + .join(" "); } - return 'User'; + return "User"; }; const roleName = getRoleName(); @@ -117,20 +157,24 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { } // Helper function to check if user has permission for a resource - const hasPermission = (resource: string, requiredAction?: string): boolean => { + const hasPermission = ( + resource: string, + requiredAction?: string, + ): boolean => { if (isSuperAdmin) { return true; // Super admin has all permissions } - const allowedActions = requiredAction ? [requiredAction] : ['*', 'read']; + const allowedActions = requiredAction ? [requiredAction] : ["*", "read"]; return permissions.some((perm) => { // Check if resource matches (exact match or wildcard) - const resourceMatches = perm.resource === resource || perm.resource === '*'; + 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 === '*' + (allowedAction) => perm.action === allowedAction || perm.action === "*", ); return resourceMatches && actionMatches; @@ -151,20 +195,26 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { return hasPermission( item.requiredPermission.resource, - item.requiredPermission.action + item.requiredPermission.action, ); }); }; // Select and filter menu items based on role and permissions const platformMenu = filterMenuItems( - isSuperAdmin ? superAdminPlatformMenu : tenantAdminPlatformMenu + isSuperAdmin ? superAdminPlatformMenu : tenantAdminPlatformMenu, ); const systemMenu = filterMenuItems( - isSuperAdmin ? superAdminSystemMenu : tenantAdminSystemMenu + isSuperAdmin ? superAdminSystemMenu : tenantAdminSystemMenu, ); - const MenuSection = ({ title, items }: { title: string; items: MenuItem[] }) => ( + const MenuSection = ({ + title, + items, + }: { + title: string; + items: MenuItem[]; + }) => (
@@ -187,22 +237,30 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { } }} 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]', + "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' + ? "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', - } + backgroundColor: + !isSuperAdmin && theme?.primary_color + ? theme.primary_color + : "#112868", + color: + !isSuperAdmin && theme?.secondary_color + ? theme.secondary_color + : "#23dce1", + } : undefined } > - {item.label} + + {item.label} + ); })} @@ -216,10 +274,10 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { {/* Mobile Sidebar */}