feat(frontend): IA > Scorecards, Prompts, Configurações

Três telas novas fecham quase todo o menu IA: Scorecards (critérios
ponderados, array dinâmico como no Dialplan), Prompts (templates com
versionamento — editar = criar versão + ativar numa ação só, já que não
existe endpoint pra listar histórico), e Configurações (providers BYOK +
modelos). Chave de API nunca é reexibida em texto puro, nem uma vez — só
preview mascarado, mesmo na resposta de criação.

Novo componente Textarea em components/ui/input.tsx (mesmo estilo de
Input/Select) — primeira tela que precisa de texto longo.

Testado ponta a ponta contra a API real: scorecard, template de prompt
(v1 -> editar -> v2 ativada), provider BYOK + modelo referenciando ele.
Smoke test de regressão nas 16 telas anteriores do tenant + platform,
todas 200. Typecheck limpo no monorepo inteiro.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
This commit is contained in:
2026-08-29 16:30:33 -03:00
parent 4d112fcea0
commit 75212cafe6
23 changed files with 1150 additions and 3 deletions

View File

@@ -114,9 +114,21 @@ export const TENANT_NAV: NavSection[] = [
href: "/app/relatorios/ia",
description: "Dashboard de IA — score, sentimento, assuntos, compliance",
},
{ label: "Scorecards" },
{ label: "Prompts" },
{ label: "Configurações" },
{
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",
},
],
},
{

View File

@@ -15,6 +15,20 @@ export const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttribute
);
Input.displayName = "Input";
export const Textarea = React.forwardRef<HTMLTextAreaElement, React.TextareaHTMLAttributes<HTMLTextAreaElement>>(
({ className, ...props }, ref) => (
<textarea
ref={ref}
className={cn(
"w-full rounded-md border border-input bg-surface px-3 py-2 text-sm text-foreground outline-none ring-offset-background placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
/>
),
);
Textarea.displayName = "Textarea";
export const Select = React.forwardRef<HTMLSelectElement, React.SelectHTMLAttributes<HTMLSelectElement>>(
({ className, children, ...props }, ref) => (
<select