feat(frontend): app do tenant, dashboard ao vivo, fluxo de login multi-tenant
Corrige um gap real: o login sempre mandava pra /platform mesmo pra usuarios sem role de plataforma, sem nunca chamar /auth/tenants ou select-tenant. Agora POST /api/post-login decide o destino server-side (plataforma / tenant unico / seletor com >1 tenant) antes de redirecionar, trocando o access token quando necessario sem nunca expor token ao client. Adiciona GET /reports/dashboard (secao 162) e a tela /app correspondente — chamadas/agentes/TME/TMA/rates ao vivo, "consumo do plano" e "valor estimado" seguindo a mesma disciplina de honestidade (null > numero inventado) do dashboard de plataforma. Shell (sidebar/topbar/drawer mobile) extraido pra components/shell, compartilhado entre os menus Platform e Tenant (secao 168-169) via wrappers client-only por area — corrige de quebra um erro real de serializacao RSC (passar NavSection[] com icones como prop de Server Component pra Client Component quebra: "Functions cannot be passed directly to Client Components"). Testado ponta a ponta com um tenant semeado (Acme Call Center): login → /app direto, platform admin barrado de /app e vice-versa, dashboard com numeros reais (zeros honestos), drawer mobile, dark mode. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWHKmcVJtstQFErbZ1AanY
This commit is contained in:
70
apps/frontend/src/components/tenant-shell/nav-data.ts
Normal file
70
apps/frontend/src/components/tenant-shell/nav-data.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
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) — "Dashboard" tem página
|
||||
* construída até agora (PHASE 23), 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" },
|
||||
{ label: "Leads" },
|
||||
{ label: "Importações" },
|
||||
{ label: "Callbacks" },
|
||||
{ label: "Lista de Bloqueio" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Call Center",
|
||||
icon: Headset,
|
||||
children: [{ label: "Agentes" }, { label: "Filas" }, { label: "Pausas" }, { label: "Disposições" }],
|
||||
},
|
||||
{
|
||||
label: "Telefonia",
|
||||
icon: Router,
|
||||
children: [{ label: "Ramais" }, { label: "Troncos" }, { label: "Dialplan" }],
|
||||
},
|
||||
{
|
||||
label: "Monitoramento",
|
||||
icon: Radar,
|
||||
children: [{ label: "Campanhas" }, { label: "Filas" }, { label: "Agentes" }, { label: "Ramais" }, { label: "Troncos" }],
|
||||
},
|
||||
{ label: "Gravações", icon: Mic },
|
||||
{
|
||||
label: "IA",
|
||||
icon: Sparkles,
|
||||
children: [{ label: "Análises" }, { label: "Scorecards" }, { label: "Prompts" }, { label: "Configurações" }],
|
||||
},
|
||||
{
|
||||
label: "Relatórios",
|
||||
icon: BarChart3,
|
||||
children: [{ label: "Chamadas" }, { label: "Agentes" }, { label: "Filas" }, { label: "Campanhas" }, { label: "Consumo" }],
|
||||
},
|
||||
{
|
||||
label: "Administração",
|
||||
icon: ShieldCheck,
|
||||
children: [{ label: "Usuários" }, { label: "Perfis" }, { label: "Configurações" }],
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user