POST /users (convidar) fecha uma lacuna real: até aqui só dava pra adicionar alguém a um tenant criando o tenant inteiro ou via script. Se o e-mail já existe na plataforma, só adiciona membership+role (sem tocar na senha); se não existe, cria a conta com senha gerada e revelada uma única vez. PATCH /users/:id/role troca o papel (substitui, 1 papel por tenant). GET /roles novo (tenant-facing) — versão de /platform/roles filtrada só pras roles de escopo TENANT, sem expor que platform_super_admin existe. Frontend: /app/administracao/usuarios (convidar com papel, trocar papel de qualquer membro exceto o próprio usuário logado) e /perfis (o que cada papel pode fazer, só leitura). Testado ponta a ponta contra a API real: convidada conta nova com senha revelada, convidado usuário com papel Agente, trocado pra Supervisor via PATCH, confirmado persistido. Perfis mostra as 3 roles de tenant certas. Smoke test nas 19 telas do tenant + 10 telas platform, todas 200. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
180 lines
5.0 KiB
TypeScript
180 lines
5.0 KiB
TypeScript
import {
|
|
LayoutDashboard,
|
|
PhoneOutgoing,
|
|
Headset,
|
|
Router,
|
|
Radar,
|
|
Mic,
|
|
Sparkles,
|
|
BarChart3,
|
|
ShieldCheck,
|
|
} from "lucide-react";
|
|
import type { NavSection } from "../shell/nav-types";
|
|
|
|
/** IA fixa do menu Tenant (agente.md secao 169). Páginas construídas até
|
|
* agora: Dashboard (PHASE 23), Telefonia > Ramais (PHASE 25), Discador >
|
|
* Campanhas (PHASE 26), Call Center > Filas/Pausas/Disposições, Telefonia
|
|
* > Troncos e Discador > Lista de Bloqueio (PHASE 27) — o resto existe pra
|
|
* provar a arquitetura completa (Product Principle #5 em PRODUCT.md),
|
|
* renderizado como indisponível em vez de virar link morto. "Itens sem
|
|
* permissão não aparecem" (secao 169) ainda não é aplicado aqui — este
|
|
* primeiro corte mostra a IA inteira pra qualquer usuário tenant
|
|
* autenticado; filtrar por permission real fica pra quando mais telas
|
|
* existirem pra testar contra. */
|
|
export const TENANT_NAV: NavSection[] = [
|
|
{
|
|
label: "Dashboard",
|
|
icon: LayoutDashboard,
|
|
href: "/app",
|
|
description: "Chamadas, agentes e filas agora",
|
|
},
|
|
{
|
|
label: "Discador",
|
|
icon: PhoneOutgoing,
|
|
children: [
|
|
{
|
|
label: "Campanhas",
|
|
href: "/app/discador/campanhas",
|
|
description: "Discador preditivo — campanhas deste tenant",
|
|
},
|
|
{ label: "Leads" },
|
|
{ label: "Importações" },
|
|
{ label: "Callbacks" },
|
|
{
|
|
label: "Lista de Bloqueio",
|
|
href: "/app/discador/bloqueio",
|
|
description: "Números que o discador nunca chama",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "Call Center",
|
|
icon: Headset,
|
|
children: [
|
|
{
|
|
label: "Agentes",
|
|
href: "/app/callcenter/agentes",
|
|
description: "Identidade de call center — liga um usuário a um agente e a um ramal",
|
|
},
|
|
{
|
|
label: "Filas",
|
|
href: "/app/callcenter/filas",
|
|
description: "Filas de atendimento deste tenant",
|
|
},
|
|
{
|
|
label: "Pausas",
|
|
href: "/app/callcenter/pausas",
|
|
description: "Motivos de pausa que o agente pode escolher",
|
|
},
|
|
{
|
|
label: "Disposições",
|
|
href: "/app/callcenter/disposicoes",
|
|
description: "Motivos de encerramento de chamada",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "Telefonia",
|
|
icon: Router,
|
|
children: [
|
|
{
|
|
label: "Ramais",
|
|
href: "/app/telefonia/ramais",
|
|
description: "Ramais SIP deste tenant — números, senha, caller ID",
|
|
},
|
|
{
|
|
label: "Troncos",
|
|
href: "/app/telefonia/troncos",
|
|
description: "Troncos SIP deste tenant",
|
|
},
|
|
{
|
|
label: "Dialplan",
|
|
href: "/app/telefonia/dialplan",
|
|
description: "Editor de regras do contexto default — condição, ações, versões",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "Monitoramento",
|
|
icon: Radar,
|
|
href: "/app/monitoramento",
|
|
description: "Eventos ao vivo — filas, agentes e chamadas em tempo real",
|
|
},
|
|
{
|
|
label: "Gravações",
|
|
icon: Mic,
|
|
href: "/app/gravacoes",
|
|
description: "Chamadas gravadas deste tenant — player autenticado, sem URL direta pro storage",
|
|
},
|
|
{
|
|
label: "IA",
|
|
icon: Sparkles,
|
|
children: [
|
|
{
|
|
label: "Análises",
|
|
href: "/app/relatorios/ia",
|
|
description: "Dashboard de IA — score, sentimento, assuntos, compliance",
|
|
},
|
|
{
|
|
label: "Scorecards",
|
|
href: "/app/ia/scorecards",
|
|
description: "Critérios ponderados que a IA avalia em toda chamada analisada",
|
|
},
|
|
{
|
|
label: "Prompts",
|
|
href: "/app/ia/prompts",
|
|
description: "Templates de prompt usados na análise e no scorecard",
|
|
},
|
|
{
|
|
label: "Configurações",
|
|
href: "/app/ia/configuracoes",
|
|
description: "Providers e modelos de IA — BYOK deste tenant",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "Relatórios",
|
|
icon: BarChart3,
|
|
children: [
|
|
{
|
|
label: "Chamadas",
|
|
href: "/app/relatorios/chamadas",
|
|
description: "Lista de chamadas — direção, fila, agente, duração, encerramento",
|
|
},
|
|
{
|
|
label: "Agentes",
|
|
href: "/app/relatorios/agentes",
|
|
description: "Tempo logado/pausado/em chamada e TMA por agente",
|
|
},
|
|
{
|
|
label: "Filas",
|
|
href: "/app/relatorios/filas",
|
|
description: "Recebidas/atendidas/abandonadas, TME/TMA, Service Level",
|
|
},
|
|
{
|
|
label: "Campanhas",
|
|
href: "/app/relatorios/campanhas",
|
|
description: "Leads, tentativas, taxas de atendimento e contato",
|
|
},
|
|
{ label: "Consumo" },
|
|
],
|
|
},
|
|
{
|
|
label: "Administração",
|
|
icon: ShieldCheck,
|
|
children: [
|
|
{
|
|
label: "Usuários",
|
|
href: "/app/administracao/usuarios",
|
|
description: "Quem tem acesso a este tenant — convidar e trocar papel",
|
|
},
|
|
{
|
|
label: "Perfis",
|
|
href: "/app/administracao/perfis",
|
|
description: "O que cada papel pode fazer neste tenant",
|
|
},
|
|
{ label: "Configurações" },
|
|
],
|
|
},
|
|
];
|