Files
tracksteel_app/src/components/AppSidebar.tsx

186 lines
6.3 KiB
TypeScript

import React, { useState, useMemo } from "react";
import { useLocation } from "react-router-dom";
import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu } from "@/components/ui/sidebar";
import { useSidebar } from "@/components/ui/sidebar";
import { useUserRole } from "@/hooks/useUserRole";
import { useIconStyle } from "@/hooks/useIconStyle";
import { useIsMobile } from "@/hooks/use-mobile";
import { useUserPermissions } from "@/hooks/useUserPermissions";
import { usePermissionControl } from "@/hooks/usePermissionControl";
import { menuGroups } from "./sidebar/menuConfig";
import { AppSidebarMenuItem } from "./sidebar/SidebarMenuItem";
export function AppSidebar() {
const location = useLocation();
const { setOpenMobile } = useSidebar();
const { isAdmin, loading: roleLoading } = useUserRole();
const { iconStyle } = useIconStyle();
const { hasAccess, loading: permissionsLoading } = useUserPermissions();
const { canAccessTools, canInteractWithSpecialMenus } = usePermissionControl();
const isMobile = useIsMobile();
const [openGroups, setOpenGroups] = useState<{ [key: string]: boolean }>({
'producao': true
});
// Handle mobile menu item click
const handleMenuItemClick = (hasSubItems: boolean = false) => {
if (isMobile && !hasSubItems) {
setOpenMobile(false);
}
};
// Handle submenu toggle
const handleSubmenuToggle = (itemKey: string, currentState: boolean) => {
setOpenGroups(prev => ({
...prev,
[itemKey]: !currentState
}));
};
const isActive = (url: string) => {
if (url === "/dashboard" && location.pathname === "/") {
return true;
}
return location.pathname === url;
};
const getIconProps = (itemKey?: string) => {
const baseProps = { className: "mr-2 h-4 w-4" };
// Mapeamento de cores específicas para cada ícone
const iconColors: { [key: string]: string } = {
'dashboard': '#3b82f6', // azul
'cadastro': '#10b981', // verde
'ferramentas': '#f59e0b', // laranja
'estoque': '#8b5cf6', // roxo
'ofs': '#eab308', // amarelo
'producao': '#ef4444', // vermelho
'painel-industrial': '#06b6d4', // ciano
'expedicao': '#ec4899', // rosa
'obra': '#a3a3a3', // marrom
'tarefas': '#059669', // verde escuro
'biblioteca': '#1d4ed8', // azul escuro
'sistema': '#6b7280', // cinza
'sugestoes': '#7c3aed', // violeta
'atribuicoes': '#14b8a6', // teal
'mapa-interativo': '#6366f1', // indigo
'configuracoes': '#475569', // slate
'admin': '#dc2626', // vermelho escuro
'gerenciar-usuarios': '#e11d48' // vermelho médio
};
// Se temos uma cor específica para este ícone, aplicá-la
if (itemKey && iconColors[itemKey]) {
return {
...baseProps,
style: { color: iconColors[itemKey] }
};
}
// Fallback para o comportamento original baseado no iconStyle
switch (iconStyle) {
case 'white':
return { ...baseProps, className: `${baseProps.className} text-white` };
case 'themed':
return { ...baseProps, className: `${baseProps.className} text-primary` };
case 'colorful':
return { ...baseProps, style: { color: 'inherit' } };
default:
return baseProps;
}
};
// Function to check if user can access an item
const canAccessItem = (itemKey: string, requiresSpecialPermission?: boolean): boolean => {
try {
// Admin can always access everything
if (isAdmin) return true;
// Se o item requer permissão especial, verificar permissões específicas
if (requiresSpecialPermission) {
if (itemKey === 'ferramentas') {
return canAccessTools();
}
if (itemKey === 'tarefas' || itemKey === 'sistema' || itemKey === 'sugestoes') {
return canInteractWithSpecialMenus();
}
}
// Users with any functional permission can see most menus
// Restriction will be applied in the pages/components themselves
return hasAccess();
} catch (error) {
console.warn('Error checking item access:', error);
return false;
}
};
// Wait for permissions loading
if (permissionsLoading || roleLoading) {
return (
<Sidebar>
<SidebarContent>
<div className="p-4 text-center text-slate-400">
Carregando menu...
</div>
</SidebarContent>
</Sidebar>
);
}
console.log('🖥️ Rendering sidebar with:', {
isAdmin,
hasBasicAccess: hasAccess(),
canAccessTools: canAccessTools(),
canInteractWithSpecialMenus: canInteractWithSpecialMenus()
});
return (
<Sidebar>
<SidebarContent>
{menuGroups.map(group => {
// Filter admin groups for non-admin users
if (!isAdmin && group.name === 'Administração') {
console.log('🚫 Hiding admin group for non-admin user');
return null;
}
// Skip groups with no items
if (!group.items || group.items.length === 0) {
return null;
}
return (
<SidebarGroup key={group.id}>
<SidebarGroupLabel
style={{ color: group.color }}
className="text-base font-semibold uppercase tracking-wide"
>
{group.name}
</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{group.items.map((item) => (
<AppSidebarMenuItem
key={item.key || item.title}
item={item}
isActive={isActive}
canAccessItem={(itemKey) => canAccessItem(itemKey, item.requiresSpecialPermission)}
isAdmin={isAdmin}
openGroups={openGroups}
onSubmenuToggle={handleSubmenuToggle}
onMenuItemClick={handleMenuItemClick}
getIconProps={(itemKey) => getIconProps(itemKey)}
/>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
);
})}
</SidebarContent>
</Sidebar>
);
}