Primeiro commit do frontend Next.js (agente.md secao 161-176): login split-brand, dashboard "Visão Geral da Plataforma" com instrumentos ao vivo, e a tela Billing > Tarifas (price books + rate decks) completa — listagem com busca/ordenacao, criacao com itens/entradas dinamicos via Server Actions, detalhe — ponta a ponta contra a API real de billing (fase 22). Corrige de quebra 2 bugs reais achados construindo Tarifas: a topbar tinha o titulo fixo "Visao Geral" em toda pagina, e a sidebar fixa de 256px nao tinha nenhuma versao mobile (conteudo espremido em ~130px) — agora vira drawer via Radix Dialog abaixo de lg, com titulo/descricao da topbar resolvidos dinamicamente por rota. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWHKmcVJtstQFErbZ1AanY
96 lines
3.1 KiB
TypeScript
96 lines
3.1 KiB
TypeScript
import type { LucideIcon } from "lucide-react";
|
|
import {
|
|
LayoutDashboard,
|
|
Building2,
|
|
CreditCard,
|
|
ServerCog,
|
|
Sparkles,
|
|
Settings2,
|
|
} from "lucide-react";
|
|
|
|
export interface NavLeaf {
|
|
label: string;
|
|
href?: string;
|
|
/** Subtítulo mostrado na topbar quando esta rota está ativa. */
|
|
description?: string;
|
|
}
|
|
|
|
export interface NavSection {
|
|
label: string;
|
|
icon: LucideIcon;
|
|
href?: string;
|
|
description?: string;
|
|
children?: NavLeaf[];
|
|
}
|
|
|
|
/** IA fixa do menu Platform (agente.md secao 168) — "Visão Geral" e
|
|
* "Billing > Tarifas" têm página construída até agora, o resto existe pra
|
|
* provar a arquitetura completa (Product Principle #5 em PRODUCT.md: esta
|
|
* é a implementação de referência do design system pras próximas telas),
|
|
* renderizado como indisponível em vez de virar link morto. Os outros 3
|
|
* itens de Billing (Consumo/Fechamentos/Relatórios) esperam um seletor de
|
|
* tenant real — não existe endpoint de listagem de tenants ainda (ver
|
|
* docs/BILLING.md), então ficam "em breve" até essa peça existir. */
|
|
export const PLATFORM_NAV: NavSection[] = [
|
|
{
|
|
label: "Visão Geral",
|
|
icon: LayoutDashboard,
|
|
href: "/platform",
|
|
description: "Estado agregado de todos os tenants, agora",
|
|
},
|
|
{
|
|
label: "Clientes",
|
|
icon: Building2,
|
|
children: [{ label: "Tenants" }, { label: "Planos" }, { label: "Assinaturas" }, { label: "Quotas" }],
|
|
},
|
|
{
|
|
label: "Billing",
|
|
icon: CreditCard,
|
|
children: [
|
|
{ label: "Consumo" },
|
|
{
|
|
label: "Tarifas",
|
|
href: "/platform/billing/tarifas",
|
|
description: "Price books e rate decks — catálogos globais de preço",
|
|
},
|
|
{ label: "Fechamentos" },
|
|
{ label: "Relatórios" },
|
|
],
|
|
},
|
|
{
|
|
label: "Infraestrutura",
|
|
icon: ServerCog,
|
|
children: [{ label: "FreeSWITCH" }, { label: "SIP Profiles" }, { label: "Nodes" }, { label: "Saúde" }],
|
|
},
|
|
{
|
|
label: "IA",
|
|
icon: Sparkles,
|
|
children: [{ label: "Providers" }, { label: "Modelos" }, { label: "Uso" }, { label: "Custos" }],
|
|
},
|
|
{
|
|
label: "Sistema",
|
|
icon: Settings2,
|
|
children: [{ label: "Usuários" }, { label: "Permissões" }, { label: "Auditoria" }, { label: "Configurações" }],
|
|
},
|
|
];
|
|
|
|
/** Título+descrição da topbar pra rota atual — casa pelo `href` mais longo
|
|
* (uma subrota como `/platform/billing/tarifas/price-books/123` ainda
|
|
* resolve pro item de menu "Tarifas"), nunca deixa a topbar com um título
|
|
* de outra página (bug real encontrado construindo a tela de Tarifas). */
|
|
export function getPageMeta(pathname: string): { title: string; description?: string } {
|
|
let best: { href: string; title: string; description?: string } | null = null;
|
|
|
|
for (const section of PLATFORM_NAV) {
|
|
const candidates: Array<{ href?: string; label: string; description?: string }> = [section, ...(section.children ?? [])];
|
|
for (const candidate of candidates) {
|
|
if (!candidate.href || !pathname.startsWith(candidate.href)) continue;
|
|
if (!best || candidate.href.length > best.href.length) {
|
|
best = { href: candidate.href, title: candidate.label, description: candidate.description };
|
|
}
|
|
}
|
|
}
|
|
|
|
return best ?? { title: "Platform" };
|
|
}
|