feat(orchestrate): add stats panel and Execute button to Deploy tab

Orchestrate Center now shows 3 stat cards (total/ready/deployed),
timestamps on each agent row, and an Execute button for deployed agents.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jonas Pacheco 2026-03-27 16:59:03 -03:00
parent b0aca073ef
commit 1f9ef75bc5
1 changed files with 37 additions and 6 deletions

View File

@ -584,8 +584,27 @@ function AgentFactoryTabs() {
</Card>
</TabsContent>
{/* ---- TAB: DEPLOY ---- */}
{/* ---- TAB: DEPLOY / ORCHESTRATE CENTER ---- */}
<TabsContent value="deploy" className="space-y-4">
{/* Stats */}
<div className="grid grid-cols-3 gap-3">
{[
{ label: "Total de agentes", value: defs.length, icon: <Brain className="w-4 h-4 text-zinc-400" /> },
{ label: "Prontos p/ deploy", value: defs.filter(d => d.status === "ready").length, icon: <CheckCircle className="w-4 h-4 text-green-400" /> },
{ label: "Implantados", value: defs.filter(d => d.status === "deployed").length, icon: <Rocket className="w-4 h-4 text-purple-400" /> },
].map(s => (
<Card key={s.label} className="bg-zinc-900/50 border-zinc-800">
<CardContent className="p-4 flex items-center gap-3">
{s.icon}
<div>
<p className="text-xl font-bold leading-none">{s.value}</p>
<p className="text-[10px] text-zinc-500 mt-0.5">{s.label}</p>
</div>
</CardContent>
</Card>
))}
</div>
<Card>
<CardHeader className="border-b py-4 px-6">
<div className="flex items-center gap-3">
@ -612,7 +631,7 @@ function AgentFactoryTabs() {
) : (
<div className="divide-y">
{defs.filter(d => d.status === "ready" || d.status === "deployed").map(def => (
<div key={def.id} className="flex items-center gap-4 px-6 py-4 hover:bg-zinc-50">
<div key={def.id} className="flex items-center gap-4 px-6 py-4 hover:bg-zinc-50/5">
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2">
<span className="font-medium text-sm">{def.name}</span>
@ -622,11 +641,22 @@ function AgentFactoryTabs() {
<span className="text-[10px] text-zinc-400">v{def.version}</span>
</div>
{def.description && <p className="text-xs text-zinc-500 truncate mt-0.5">{def.description}</p>}
{def.lastTaskId && (
<p className="text-xs text-zinc-400 mt-0.5">Último artefato: Task #{def.lastTaskId}</p>
)}
<p className="text-[10px] text-zinc-600 mt-0.5">
Atualizado {new Date(def.updatedAt).toLocaleString("pt-BR", { dateStyle: "short", timeStyle: "short" })}
{def.lastTaskId ? ` · Task #${def.lastTaskId}` : ""}
</p>
</div>
<div className="flex gap-2 shrink-0">
{def.status === "deployed" && (
<Button
size="sm"
onClick={() => runMutation.mutate(def.id)}
disabled={runMutation.isPending}
className="text-xs h-8"
>
<Play className="w-3 h-3 mr-1" /> Executar
</Button>
)}
{def.status === "ready" && (
<Button
size="sm"
@ -643,8 +673,9 @@ function AgentFactoryTabs() {
onClick={() => redraftMutation.mutate(def.id)}
disabled={redraftMutation.isPending}
className="text-xs h-8"
title="Voltar para rascunho e remontar"
>
<RotateCcw className="w-3 h-3 mr-1" /> Re-montar
<RotateCcw className="w-3 h-3" />
</Button>
</div>
</div>