Add Agents screen to sidebar

This commit is contained in:
gpt-engineer-app[bot]
2025-10-29 14:57:43 +00:00
parent 6ef80b9726
commit b9d7db533c
4 changed files with 287 additions and 0 deletions
+2
View File
@@ -5,6 +5,7 @@ import { ThemeProvider } from "next-themes";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { AppLayout } from "./components/layout/AppLayout";
import Agents from "./pages/Agents";
import Prompts from "./pages/Prompts";
import TestPrompt from "./pages/TestPrompt";
import History from "./pages/History";
@@ -21,6 +22,7 @@ const App = () => (
<BrowserRouter>
<Routes>
<Route element={<AppLayout />}>
<Route path="/agents" element={<Agents />} />
<Route path="/" element={<Prompts />} />
<Route path="/test" element={<TestPrompt />} />
<Route path="/history" element={<History />} />
+125
View File
@@ -0,0 +1,125 @@
import { useState } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
interface CreateAgentDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
export function CreateAgentDialog({ open, onOpenChange }: CreateAgentDialogProps) {
const [name, setName] = useState("");
const [status, setStatus] = useState<"active" | "inactive">("active");
const [selectedPrompt, setSelectedPrompt] = useState("");
const [selectedModel, setSelectedModel] = useState("");
const handleSave = () => {
console.log("Salvando agente:", { name, status, selectedPrompt, selectedModel });
// Implementar lógica de salvar no backend
onOpenChange(false);
// Reset form
setName("");
setStatus("active");
setSelectedPrompt("");
setSelectedModel("");
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Criar Novo Agente</DialogTitle>
<DialogDescription>
Configure o agente selecionando um prompt e modelo de IA
</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Nome do Agente</Label>
<Input
id="name"
placeholder="Ex: Agente de Atendimento"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="status">Status</Label>
<Select value={status} onValueChange={(v) => setStatus(v as "active" | "inactive")}>
<SelectTrigger id="status">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="active">Ativo</SelectItem>
<SelectItem value="inactive">Inativo</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="prompt">Prompt</Label>
<Select value={selectedPrompt} onValueChange={setSelectedPrompt}>
<SelectTrigger id="prompt">
<SelectValue placeholder="Selecione um prompt" />
</SelectTrigger>
<SelectContent>
<SelectItem value="atendimento">Prompt de Atendimento v2.1</SelectItem>
<SelectItem value="vendas">Prompt de Vendas v1.5</SelectItem>
<SelectItem value="analise">Prompt de Análise</SelectItem>
<SelectItem value="marketing">Prompt de Marketing</SelectItem>
<SelectItem value="suporte">Prompt de Suporte Técnico</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="model">Modelo de IA</Label>
<Select value={selectedModel} onValueChange={setSelectedModel}>
<SelectTrigger id="model">
<SelectValue placeholder="Selecione um modelo" />
</SelectTrigger>
<SelectContent>
<SelectItem value="gemini-2.5-flash">Google Gemini 2.5 Flash</SelectItem>
<SelectItem value="gemini-2.5-pro">Google Gemini 2.5 Pro</SelectItem>
<SelectItem value="gpt-5">OpenAI GPT-5</SelectItem>
<SelectItem value="gpt-5-mini">OpenAI GPT-5 Mini</SelectItem>
<SelectItem value="gpt-4.1">OpenAI GPT-4.1</SelectItem>
<SelectItem value="claude-sonnet-4-5">Anthropic Claude Sonnet 4.5</SelectItem>
<SelectItem value="claude-opus-4-1">Anthropic Claude Opus 4.1</SelectItem>
</SelectContent>
</Select>
</div>
<div className="flex justify-end gap-2 pt-4 border-t">
<Button variant="outline" onClick={() => onOpenChange(false)}>
Cancelar
</Button>
<Button
onClick={handleSave}
disabled={!name || !selectedPrompt || !selectedModel}
>
Criar Agente
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}
+2
View File
@@ -1,6 +1,7 @@
import { useState } from "react";
import { NavLink } from "react-router-dom";
import {
Bot,
FileText,
TestTube,
ArrowLeft,
@@ -12,6 +13,7 @@ import { Separator } from "@/components/ui/separator";
import { ThemeToggle } from "./ThemeToggle";
const menuItems = [
{ title: "Agentes", url: "/agents", icon: Bot },
{ title: "Prompts", url: "/", icon: FileText },
{ title: "Testar Prompt", url: "/test", icon: TestTube },
];
+158
View File
@@ -0,0 +1,158 @@
import { useState } from "react";
import { CreateAgentDialog } from "@/components/agents/CreateAgentDialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Plus, Search, MoreVertical, Edit, Trash2 } from "lucide-react";
export default function Agents() {
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const [agents] = useState([
{
id: 1,
name: "Agente de Atendimento",
status: "active" as const,
prompt: "Prompt de Atendimento v2.1",
model: "Google Gemini 2.5 Flash",
createdAt: "2 dias atrás",
},
{
id: 2,
name: "Agente de Vendas",
status: "active" as const,
prompt: "Prompt de Vendas v1.5",
model: "OpenAI GPT-5",
createdAt: "5 dias atrás",
},
{
id: 3,
name: "Agente de Análise",
status: "inactive" as const,
prompt: "Prompt de Análise",
model: "Anthropic Claude Sonnet 4.5",
createdAt: "1 semana atrás",
},
]);
const filteredAgents = agents.filter(agent =>
agent.name.toLowerCase().includes(searchQuery.toLowerCase())
);
return (
<div className="animate-fade-in">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-3xl font-bold text-foreground mb-2">Gestão de Agentes</h1>
<p className="text-muted-foreground">
Crie e gerencie agentes de IA com prompts e modelos específicos
</p>
</div>
<Button className="gap-2" onClick={() => setIsCreateDialogOpen(true)}>
<Plus className="h-4 w-4" />
Criar Agente
</Button>
</div>
<div className="mb-6">
<div className="relative max-w-md">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4" />
<Input
placeholder="Pesquisar agentes..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10"
/>
</div>
<p className="text-sm text-muted-foreground mt-2">
{filteredAgents.length} {filteredAgents.length === 1 ? 'agente encontrado' : 'agentes encontrados'}
</p>
</div>
{filteredAgents.length === 0 ? (
<div className="text-center py-12">
<p className="text-muted-foreground">Nenhum agente encontrado.</p>
</div>
) : (
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Nome</TableHead>
<TableHead>Prompt</TableHead>
<TableHead>Modelo</TableHead>
<TableHead>Criado</TableHead>
<TableHead>Status</TableHead>
<TableHead className="text-right">Ações</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filteredAgents.map((agent) => (
<TableRow key={agent.id}>
<TableCell className="font-medium">{agent.name}</TableCell>
<TableCell>{agent.prompt}</TableCell>
<TableCell>
<code className="text-xs bg-muted px-2 py-1 rounded">
{agent.model}
</code>
</TableCell>
<TableCell>{agent.createdAt}</TableCell>
<TableCell>
<Badge
variant={agent.status === "active" ? "default" : "secondary"}
className={agent.status === "active" ? "bg-green-600 hover:bg-green-700" : "bg-muted text-muted-foreground hover:bg-muted"}
>
{agent.status === "active" ? "Ativo" : "Inativo"}
</Badge>
</TableCell>
<TableCell className="text-right">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => console.log("Edit", agent.id)}>
<Edit className="h-4 w-4 mr-2" />
Editar
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => console.log("Delete", agent.id)}
className="text-destructive"
>
<Trash2 className="h-4 w-4 mr-2" />
Excluir
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
)}
<CreateAgentDialog
open={isCreateDialogOpen}
onOpenChange={setIsCreateDialogOpen}
/>
</div>
);
}