feat: Enhance sidebar active state logic with path exclusion and add new permissions for pedidos, atas, objetos, and empresas.

This commit is contained in:
2025-12-05 16:36:56 -03:00
parent 6a99ab74f1
commit 80e9b76649
2 changed files with 129 additions and 5 deletions

View File

@@ -58,6 +58,8 @@
label: string; label: string;
link: string; link: string;
permission?: MenuItemPermission; permission?: MenuItemPermission;
excludePaths?: string[];
exact?: boolean;
} }
interface MenuItem { interface MenuItem {
@@ -66,6 +68,8 @@
link: string; link: string;
permission?: MenuItemPermission; permission?: MenuItemPermission;
submenus?: SubMenuItem[]; submenus?: SubMenuItem[];
excludePaths?: string[];
exact?: boolean;
} }
// Estrutura do menu definida no frontend // Estrutura do menu definida no frontend
@@ -107,7 +111,8 @@
{ {
label: 'Meus Pedidos', label: 'Meus Pedidos',
link: '/pedidos', link: '/pedidos',
permission: { recurso: 'pedidos', acao: 'listar' } permission: { recurso: 'pedidos', acao: 'listar' },
excludePaths: ['/pedidos/aceite', '/pedidos/minhas-analises']
}, },
{ {
label: 'Pedidos para Aceite', label: 'Pedidos para Aceite',
@@ -261,7 +266,15 @@
return iconMap[name] || Home; return iconMap[name] || Home;
} }
function isRouteActive(path: string, exact = false) { function isRouteActive(path: string, options: { exact?: boolean; excludePaths?: string[] } = {}) {
const { exact = false, excludePaths = [] } = options;
if (excludePaths.length > 0) {
if (excludePaths.some((excludePath) => currentPath.startsWith(excludePath))) {
return false;
}
}
if (exact) return currentPath === path; if (exact) return currentPath === path;
return currentPath === path || currentPath.startsWith(path + '/'); return currentPath === path || currentPath.startsWith(path + '/');
} }
@@ -630,7 +643,10 @@
<!-- Sidebar menu items --> <!-- Sidebar menu items -->
{#snippet menuItem(item: MenuItem)} {#snippet menuItem(item: MenuItem)}
{@const Icon = getIconComponent(item.icon)} {@const Icon = getIconComponent(item.icon)}
{@const isActive = isRouteActive(item.link, item.link === '/')} {@const isActive = isRouteActive(item.link, {
exact: item.link === '/',
excludePaths: item.excludePaths
})}
{@const hasSubmenus = item.submenus && item.submenus.length > 0} {@const hasSubmenus = item.submenus && item.submenus.length > 0}
<li class="mb-1"> <li class="mb-1">
@@ -651,10 +667,13 @@
class="h-4 w-4 opacity-50 transition-transform duration-200 group-open/details:rotate-180" class="h-4 w-4 opacity-50 transition-transform duration-200 group-open/details:rotate-180"
/> />
</summary> </summary>
<ul class="border-base-200 mt-1 ml-4 space-y-1 border-l-2 pl-2"> <ul class="border-base-200 mt-1 ml-4 space-y-1 pl-2">
{#if item.submenus} {#if item.submenus}
{#each item.submenus as sub (sub.link)} {#each item.submenus as sub (sub.link)}
{@const isSubActive = isRouteActive(sub.link)} {@const isSubActive = isRouteActive(sub.link, {
excludePaths: sub.excludePaths,
exact: sub.exact
})}
<li> <li>
<a href={resolve(sub.link)} class={getMenuClasses(isSubActive, true)}> <a href={resolve(sub.link)} class={getMenuClasses(isSubActive, true)}>
<span>{sub.label}</span> <span>{sub.label}</span>

View File

@@ -433,6 +433,111 @@ const PERMISSOES_BASE = {
acao: 'remover_item', acao: 'remover_item',
descricao: 'Remover itens do pedido' descricao: 'Remover itens do pedido'
}, },
{
nome: 'pedidos.editar',
recurso: 'pedidos',
acao: 'editar',
descricao: 'Editar dados gerais do pedido'
},
{
nome: 'pedidos.excluir',
recurso: 'pedidos',
acao: 'excluir',
descricao: 'Excluir pedidos'
},
// Atas
{
nome: 'atas.listar',
recurso: 'atas',
acao: 'listar',
descricao: 'Listar atas de registro de preços'
},
{
nome: 'atas.criar',
recurso: 'atas',
acao: 'criar',
descricao: 'Criar novas atas'
},
{
nome: 'atas.ver',
recurso: 'atas',
acao: 'ver',
descricao: 'Visualizar detalhes de atas'
},
{
nome: 'atas.editar',
recurso: 'atas',
acao: 'editar',
descricao: 'Editar atas'
},
{
nome: 'atas.excluir',
recurso: 'atas',
acao: 'excluir',
descricao: 'Excluir atas'
},
// Objetos
{
nome: 'objetos.listar',
recurso: 'objetos',
acao: 'listar',
descricao: 'Listar objetos de contratação'
},
{
nome: 'objetos.criar',
recurso: 'objetos',
acao: 'criar',
descricao: 'Criar novos objetos'
},
{
nome: 'objetos.ver',
recurso: 'objetos',
acao: 'ver',
descricao: 'Visualizar detalhes de objetos'
},
{
nome: 'objetos.editar',
recurso: 'objetos',
acao: 'editar',
descricao: 'Editar objetos'
},
{
nome: 'objetos.excluir',
recurso: 'objetos',
acao: 'excluir',
descricao: 'Excluir objetos'
},
// Empresas
{
nome: 'empresas.listar',
recurso: 'empresas',
acao: 'listar',
descricao: 'Listar empresas'
},
{
nome: 'empresas.criar',
recurso: 'empresas',
acao: 'criar',
descricao: 'Criar novas empresas'
},
{
nome: 'empresas.ver',
recurso: 'empresas',
acao: 'ver',
descricao: 'Visualizar detalhes de empresas'
},
{
nome: 'empresas.editar',
recurso: 'empresas',
acao: 'editar',
descricao: 'Editar empresas'
},
{
nome: 'empresas.excluir',
recurso: 'empresas',
acao: 'excluir',
descricao: 'Excluir empresas'
},
// Produtos // Produtos
{ {
nome: 'produtos.listar', nome: 'produtos.listar',