Add Agents screen to sidebar
This commit is contained in:
@@ -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 />} />
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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 },
|
||||
];
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user