feat: Call Center > Agentes + Telefonia > Dialplan (novo endpoint GET /users)
Fecha a lacuna de backend que travava Agentes: POST /agents exigia um userId de um usuário já existente do tenant, mas não havia nenhum endpoint pra listar usuários. Novo GET /users (gated por users.manage, não agents.manage — listar identidade de login é administração de usuário) via TenantMembership, mesmo padrão de RLS já usado em listUserTenants. Duas telas novas: Call Center > Agentes (criar/listar/remover, seletor de usuário só mostra quem ainda não é agente) e Telefonia > Dialplan (editor estruturado do contexto default — regras com condição/ações dinâmicas, painel de Versões com gerar/ativar, reativar versão antiga = rollback). Testado ponta a ponta contra a API real do tenant Acme, incluindo o ciclo completo de dialplan (criar regra -> gerar v1 -> ativar -> badge "Ativa"). Smoke test de regressão nas 13 telas anteriores do tenant + platform. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
This commit is contained in:
@@ -51,7 +51,11 @@ export const TENANT_NAV: NavSection[] = [
|
||||
label: "Call Center",
|
||||
icon: Headset,
|
||||
children: [
|
||||
{ label: "Agentes" },
|
||||
{
|
||||
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",
|
||||
@@ -83,7 +87,11 @@ export const TENANT_NAV: NavSection[] = [
|
||||
href: "/app/telefonia/troncos",
|
||||
description: "Troncos SIP deste tenant",
|
||||
},
|
||||
{ label: "Dialplan" },
|
||||
{
|
||||
label: "Dialplan",
|
||||
href: "/app/telefonia/dialplan",
|
||||
description: "Editor de regras do contexto default — condição, ações, versões",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -26,6 +26,12 @@ const STATUS_CONFIG: Record<string, { label: string; color: string; shape: "dot"
|
||||
FAILED: { label: "Falhou", color: "status-red", shape: "square" },
|
||||
UNREGISTERED: { label: "Não registrado", color: "status-gray", shape: "ring" },
|
||||
UNKNOWN: { label: "Desconhecido", color: "status-gray", shape: "ring" },
|
||||
|
||||
// DialplanVersionStatus (agente.md secao 44) — DRAFT reusa o rótulo já
|
||||
// existente pra campanha ("Rascunho", mesmo conceito); ACTIVE/SUPERSEDED
|
||||
// são novos, sem colisão.
|
||||
ACTIVE: { label: "Ativa", color: "status-green", shape: "dot" },
|
||||
SUPERSEDED: { label: "Substituída", color: "status-gray", shape: "ring" },
|
||||
};
|
||||
|
||||
const SHAPE_CLASS: Record<string, string> = {
|
||||
|
||||
Reference in New Issue
Block a user