import { BadgeCheck, ClipboardList, Scale, ShieldCheck, Users, Wallet, Warehouse, } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; export type ProcurementEntry = { id: string; label: string; path: string; roles?: string[]; fullPage?: boolean; }; export type ProcurementGroup = { id: string; label: string; icon: LucideIcon; entries: ProcurementEntry[]; }; const readers = ['admin', 'procurement', 'finance', 'department_head']; const finance = ['admin', 'finance']; const inventory = [...readers, 'warehouse']; export function procurementNavigation( role: string, payables: boolean, ): ProcurementGroup[] { const groups: ProcurementGroup[] = [ { id: 'requests', label: 'Requisições', icon: ClipboardList, entries: [ { id: 'new_request', label: 'Nova requisição', path: '/requisicoes/criar', }, { id: 'my_requests', label: 'Minhas requisições', path: '/requisicoes?view=mine', }, { id: 'my_drafts', label: 'Os meus rascunhos', path: '/requisicoes?view=mine&status=draft', }, { id: 'all_requests', label: 'Todas as autorizadas', path: '/requisicoes?view=all', }, { id: 'planning', label: 'Planeamento', path: '/planeamento' }, ], }, { id: 'approvals', label: 'Aprovações', icon: BadgeCheck, entries: [ { id: 'pending_approvals', label: 'Pendentes para mim', path: '/requisicoes?view=approvals', roles: readers, }, { id: 'decisions', label: 'Minhas decisões', path: '/requisicoes?view=decided', roles: readers, }, ], }, { id: 'sourcing', label: 'Consultas e adjudicações', icon: Scale, entries: [ { id: 'quotations', label: 'Cotações e comparação', path: '/cotacoes', roles: readers, }, { id: 'orders', label: 'Adjudicações e ordens', path: '/ordens', roles: readers, }, { id: 'purchase_review', label: 'Revisão e cancelamento', path: '/revisao-compras', }, ], }, { id: 'suppliers', label: 'Fornecedores', icon: Users, entries: [ { id: 'suppliers', label: 'Cadastro e documentos', path: '/fornecedores', roles: readers, }, ], }, { id: 'receiving', label: 'Recepções e armazém', icon: Warehouse, entries: [ { id: 'receipts', label: 'Recepções e divergências', path: '/recepcoes', roles: inventory, }, { id: 'stock', label: 'Artigos e stock', path: '/stock', roles: ['admin', 'procurement', 'finance', 'warehouse'], }, { id: 'stock_operations', label: 'Saídas e inventários', path: '/stock/operacoes', roles: ['admin', 'procurement', 'finance', 'warehouse'], }, { id: 'equipment', label: 'Equipamentos e peças', path: '/equipamentos', roles: inventory, }, ], }, { id: 'finance', label: 'Finanças', icon: Wallet, entries: [ { id: 'invoices', label: 'Facturas e conferência', path: '/facturas', roles: finance, }, ...(payables ? [ { id: 'payables', label: 'Obrigações a fornecedores', path: '/obrigacoes-fornecedores', roles: finance, fullPage: true, }, ] : []), { id: 'payments', label: 'Pagamentos externos', path: '/pagamentos', roles: finance, }, { id: 'budgets', label: 'Orçamentos e reforços', path: '/orcamentos', roles: finance, }, { id: 'investment', label: 'Regras de investimento', path: '/regras-investimento', roles: ['admin', 'procurement', 'finance'], }, ], }, { id: 'administration', label: 'Administração e controlo', icon: ShieldCheck, entries: [ { id: 'company', label: 'Empresa, equipa e centros', path: '/empresa', roles: ['admin'], }, { id: 'admission_policy', label: 'Política de admissão', path: '/politica-admissao', roles: ['admin'], }, { id: 'recommendation_policy', label: 'Política de recomendação', path: '/politica-recomendacao', roles: ['admin'], }, { id: 'conflicts', label: 'Conflitos de interesses', path: '/conflitos', }, ], }, ]; return groups .map((group) => ({ ...group, entries: group.entries.filter( (entry) => !entry.roles || entry.roles.includes(role), ), })) .filter((group) => group.entries.length); } export function activeProcurementEntry( groups: ProcurementGroup[], url: string, ): string | undefined { const current = new URL(url, 'http://local'); if (/^\/ordens\/\d+\/recepcoes/.test(current.pathname)) return 'receipts'; if (/^\/requisicoes\/\d+\/adjudicacao(?:\/|$)/.test(current.pathname)) return 'orders'; if ( /^\/requisicoes\/\d+\/(cotacoes|abertura|qualificacao|admissao|recomendacao|relatorio)(?:\/|$)/.test( current.pathname, ) ) return 'quotations'; const matches = groups .flatMap((group) => group.entries) .filter((entry) => { const target = new URL(entry.path, 'http://local'); if ( current.pathname !== target.pathname && !current.pathname.startsWith(target.pathname + '/') ) return false; return [...target.searchParams].every( ([key, value]) => (current.searchParams.get(key) ?? (key === 'view' ? 'all' : null)) === value, ); }); const specificity = (path: string) => { const target = new URL(path, 'http://local'); return target.pathname.length * 100 + target.searchParams.size; }; matches.sort((a, b) => specificity(b.path) - specificity(a.path)); return matches[0]?.id; }