feat(secretaria): botão "Usar este modelo" nos modelos de ajuda

Cada modelo do modal de ajuda ganha um botão que cria o nó correspondente no
Cérebro (persona/knowledge/rules/calendar/escalation) já preenchido com o
conteúdo de exemplo. Desabilitado se nenhum agente estiver selecionado.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Deploy Agent
2026-06-28 06:59:57 +02:00
parent 7d191c0cf7
commit 36405a46f0
@@ -1410,9 +1410,9 @@ function NewSlotModal({
// ─── Modal de Ajuda ─────────────────────────────────────────────────────────
const HELP_MODELOS: { titulo: string; icon: React.ElementType; cor: string; descricao: string; exemplo: string }[] = [
const HELP_MODELOS: { titulo: string; type: BrainNodeType; icon: React.ElementType; cor: string; descricao: string; exemplo: string }[] = [
{
titulo: 'Persona', icon: Sparkles, cor: 'text-purple-400',
titulo: 'Persona', type: 'persona', icon: Sparkles, cor: 'text-purple-400',
descricao: 'Identidade, tom de voz e personalidade da secretária — a base de como ela se comunica.',
exemplo: `Você é a Ana, atendente da Clínica X. Seu jeito: calorosa, paciente e direta — nunca robótica.
Adapte o tom ao do cliente. Use o nome dele com naturalidade, não em toda mensagem.
@@ -1420,7 +1420,7 @@ Quando o cliente estiver frustrado, reconheça o sentimento antes de resolver.
Nunca use linguagem corporativa ("prezado", "informamos que"). Varie as respostas.`,
},
{
titulo: 'Conhecimento', icon: BookOpen, cor: 'text-blue-400',
titulo: 'Conhecimento', type: 'knowledge', icon: BookOpen, cor: 'text-blue-400',
descricao: 'Fatos que a secretária precisa saber: horários, serviços, preços, endereço, políticas.',
exemplo: `Horário: Seg a Sex, 08h18h. Sáb 08h12h.
Endereço: Rua X, 123 — Centro. Estacionamento gratuito.
@@ -1429,7 +1429,7 @@ Convênios: Unimed, Bradesco Saúde. Não atendemos outros convênios.
Política: remarcação com 24h de antecedência.`,
},
{
titulo: 'Regras', icon: ShieldCheck, cor: 'text-orange-400',
titulo: 'Regras', type: 'rules', icon: ShieldCheck, cor: 'text-orange-400',
descricao: 'Comportamentos obrigatórios e proibições. Numere para a IA seguir à risca.',
exemplo: `1. Sempre confirme nome completo e telefone antes de agendar.
2. Nunca invente preços ou horários — se não souber, diga que vai verificar.
@@ -1438,7 +1438,7 @@ Política: remarcação com 24h de antecedência.`,
5. Para cobrança/estorno, encaminhe para um humano.`,
},
{
titulo: 'Agenda', icon: Calendar, cor: 'text-green-400',
titulo: 'Agenda', type: 'calendar', icon: Calendar, cor: 'text-green-400',
descricao: 'Autoriza consultar horários e agendar. Cadastre os horários na aba "Agenda".',
exemplo: `Você pode consultar a agenda e oferecer horários livres.
Ao agendar, confirme data, horário e nome, e repita o resumo:
@@ -1446,7 +1446,7 @@ Ao agendar, confirme data, horário e nome, e repita o resumo:
Ofereça opções concretas ("tenho 14h ou 16h"), não pergunte de forma vaga.`,
},
{
titulo: 'Escalada', icon: AlertTriangle, cor: 'text-red-400',
titulo: 'Escalada', type: 'escalation', icon: AlertTriangle, cor: 'text-red-400',
descricao: 'Quando e como passar o atendimento para um humano.',
exemplo: `Transfira para humano quando:
- O cliente pedir explicitamente.
@@ -1456,7 +1456,11 @@ Como: "Vou chamar a equipe que resolve isso melhor pra você, um momento."`,
},
]
function HelpModal({ onClose }: { onClose: () => void }) {
function HelpModal({ onClose, onUseModel, canUse }: {
onClose: () => void
onUseModel: (type: BrainNodeType, title: string, content: string) => void
canUse: boolean
}) {
return (
<div className="fixed inset-0 z-[100] bg-black/70 flex items-center justify-center p-4" onClick={onClose}>
<div
@@ -1498,6 +1502,14 @@ function HelpModal({ onClose }: { onClose: () => void }) {
</div>
<p className="text-xs text-slate-400 mb-2">{m.descricao}</p>
<pre className="text-xs text-slate-300 bg-black/40 rounded-lg p-3 whitespace-pre-wrap font-mono leading-relaxed">{m.exemplo}</pre>
<button
onClick={() => onUseModel(m.type, m.titulo, m.exemplo)}
disabled={!canUse}
title={canUse ? 'Cria um nó no Cérebro já preenchido com este modelo' : 'Selecione um agente primeiro'}
className="mt-3 inline-flex items-center gap-1.5 text-xs font-semibold rounded-lg bg-brand-500/20 hover:bg-brand-500/30 text-brand-300 px-3 py-1.5 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
>
<Plus size={13} /> Usar este modelo
</button>
</div>
)
})}
@@ -1591,7 +1603,18 @@ export default function SecretariaPage() {
{/* Thin Nav */}
<ThinNav active={activeTab} onChange={handleTabChange} onHelp={() => setShowHelp(true)} />
{showHelp && <HelpModal onClose={() => setShowHelp(false)} />}
{showHelp && (
<HelpModal
onClose={() => setShowHelp(false)}
canUse={!!store.selectedAgent}
onUseModel={async (type, title, content) => {
if (!store.selectedAgent) return
await store.createNode(store.selectedAgent.id, { type, title, content, sort_order: store.nodes.length })
setShowHelp(false)
setActiveTab('brain')
}}
/>
)}
{/* Left Panel */}
<div className="w-[280px] h-full bg-[#0a0d15] border-r border-white/5 flex flex-col shrink-0">