Create HGTX PromptLab UI

This commit is contained in:
gpt-engineer-app[bot]
2025-10-29 12:06:30 +00:00
parent d712cc7bb5
commit 6efb71b59b
13 changed files with 784 additions and 59 deletions
+59
View File
@@ -0,0 +1,59 @@
import { useState } from "react";
import { AgentCard } from "@/components/agents/AgentCard";
import { Button } from "@/components/ui/button";
import { Plus } from "lucide-react";
export default function Agents() {
const [agents] = useState([
{
id: 1,
name: "Agente de Suporte",
description: "Responde dúvidas de clientes sobre produtos e serviços da empresa",
promptName: "Prompt de Atendimento v2.1",
status: "active" as const,
},
{
id: 2,
name: "Agente de Vendas",
description: "Qualifica leads e apresenta produtos de forma personalizada",
promptName: "Prompt de Vendas v1.5",
status: "active" as const,
},
{
id: 3,
name: "Agente de Análise",
description: "Analisa dados e gera insights para tomada de decisão",
status: "inactive" as const,
},
]);
return (
<div className="animate-fade-in">
<div className="flex items-center justify-between mb-8">
<div>
<h1 className="text-3xl font-bold text-foreground mb-2">Agentes de IA</h1>
<p className="text-muted-foreground">
Gerencie os agentes de IA e seus prompts vinculados
</p>
</div>
<Button className="gap-2">
<Plus className="h-4 w-4" />
Novo Agente
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{agents.map((agent) => (
<AgentCard
key={agent.id}
name={agent.name}
description={agent.description}
promptName={agent.promptName}
status={agent.status}
onLinkPrompt={() => console.log("Link prompt", agent.id)}
/>
))}
</div>
</div>
);
}
+124
View File
@@ -0,0 +1,124 @@
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { RotateCcw, GitBranch } from "lucide-react";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
export default function History() {
const versions = [
{
id: 1,
version: "v2.1",
author: "João Silva",
date: "2 dias atrás",
summary: "Melhorias na formatação de respostas e tom mais amigável",
current: true,
},
{
id: 2,
version: "v2.0",
author: "João Silva",
date: "1 semana atrás",
summary: "Adicionado contexto sobre produtos lançados em 2024",
current: false,
},
{
id: 3,
version: "v1.9",
author: "Maria Santos",
date: "2 semanas atrás",
summary: "Ajustes no limite de caracteres da resposta",
current: false,
},
{
id: 4,
version: "v1.8",
author: "Pedro Costa",
date: "3 semanas atrás",
summary: "Versão inicial com estrutura básica do prompt",
current: false,
},
];
return (
<div className="animate-fade-in max-w-4xl mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground mb-2">Histórico de Versões</h1>
<p className="text-muted-foreground">
Visualize e restaure versões anteriores dos seus prompts
</p>
</div>
<Card className="p-6 mb-6">
<div className="flex items-center gap-4">
<div className="flex-1">
<label className="text-sm font-medium text-foreground mb-2 block">
Selecione o Prompt
</label>
<Select defaultValue="atendimento">
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="atendimento">Prompt de Atendimento</SelectItem>
<SelectItem value="vendas">Prompt de Vendas</SelectItem>
<SelectItem value="analise">Prompt de Análise</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</Card>
<div className="relative">
<div className="absolute left-8 top-0 bottom-0 w-0.5 bg-border" />
<div className="space-y-6">
{versions.map((version) => (
<div key={version.id} className="relative pl-16 animate-fade-in">
<div
className={`absolute left-6 w-5 h-5 rounded-full border-2 ${
version.current
? "bg-primary border-primary"
: "bg-background border-border"
}`}
/>
<Card className="p-5 hover:shadow-hover transition-shadow">
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-3">
<Badge variant={version.current ? "default" : "secondary"}>
{version.version}
</Badge>
{version.current && (
<Badge variant="outline" className="gap-1">
<GitBranch className="h-3 w-3" />
Atual
</Badge>
)}
</div>
{!version.current && (
<Button variant="outline" size="sm" className="gap-2">
<RotateCcw className="h-4 w-4" />
Restaurar
</Button>
)}
</div>
<p className="text-foreground font-medium mb-2">{version.summary}</p>
<p className="text-sm text-muted-foreground">
por {version.author} {version.date}
</p>
</Card>
</div>
))}
</div>
</div>
</div>
);
}
+117
View File
@@ -0,0 +1,117 @@
import { useState } from "react";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Link as LinkIcon, Check } from "lucide-react";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useToast } from "@/hooks/use-toast";
export default function LinkPrompt() {
const [selectedAgent, setSelectedAgent] = useState("");
const [selectedPrompt, setSelectedPrompt] = useState("");
const { toast } = useToast();
const handleLink = () => {
if (selectedAgent && selectedPrompt) {
toast({
title: "Prompt vinculado com sucesso!",
description: "O agente já está usando o novo prompt.",
});
}
};
return (
<div className="animate-fade-in max-w-3xl mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground mb-2">
Vincular Prompt ao Agente
</h1>
<p className="text-muted-foreground">
Associe um prompt específico a um agente de IA
</p>
</div>
<Card className="p-8">
<div className="space-y-6">
<div>
<Label htmlFor="agent-select">Selecione o Agente</Label>
<Select value={selectedAgent} onValueChange={setSelectedAgent}>
<SelectTrigger id="agent-select">
<SelectValue placeholder="Escolha um agente" />
</SelectTrigger>
<SelectContent>
<SelectItem value="suporte">Agente de Suporte</SelectItem>
<SelectItem value="vendas">Agente de Vendas</SelectItem>
<SelectItem value="analise">Agente de Análise</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="prompt-select">Selecione o Prompt</Label>
<Select value={selectedPrompt} onValueChange={setSelectedPrompt}>
<SelectTrigger id="prompt-select">
<SelectValue placeholder="Escolha 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>
</SelectContent>
</Select>
</div>
{selectedAgent && selectedPrompt && (
<Card className="p-4 bg-muted animate-scale-in">
<h3 className="font-medium text-foreground mb-2">Resumo da Vinculação</h3>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-muted-foreground">Agente:</span>
<span className="text-foreground font-medium">
{selectedAgent === "suporte" && "Agente de Suporte"}
{selectedAgent === "vendas" && "Agente de Vendas"}
{selectedAgent === "analise" && "Agente de Análise"}
</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Prompt:</span>
<span className="text-foreground font-medium">
{selectedPrompt === "atendimento" && "Prompt de Atendimento v2.1"}
{selectedPrompt === "vendas" && "Prompt de Vendas v1.5"}
{selectedPrompt === "analise" && "Prompt de Análise"}
{selectedPrompt === "marketing" && "Prompt de Marketing"}
</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Data:</span>
<span className="text-foreground font-medium">
{new Date().toLocaleDateString("pt-BR")}
</span>
</div>
</div>
</Card>
)}
<Button
onClick={handleLink}
disabled={!selectedAgent || !selectedPrompt}
className="w-full gap-2"
size="lg"
>
<LinkIcon className="h-4 w-4" />
Vincular Prompt
</Button>
</div>
</Card>
</div>
);
}
+70
View File
@@ -0,0 +1,70 @@
import { useState } from "react";
import { PromptCard } from "@/components/prompts/PromptCard";
import { Button } from "@/components/ui/button";
import { Plus } from "lucide-react";
export default function Prompts() {
const [prompts] = useState([
{
id: 1,
title: "Prompt de Atendimento v2.1",
creator: "João Silva",
lastModified: "2 dias atrás",
status: "published" as const,
},
{
id: 2,
title: "Prompt de Vendas v1.5",
creator: "Maria Santos",
lastModified: "5 dias atrás",
status: "published" as const,
},
{
id: 3,
title: "Prompt de Análise",
creator: "Pedro Costa",
lastModified: "1 semana atrás",
status: "draft" as const,
},
{
id: 4,
title: "Prompt de Marketing",
creator: "Ana Lima",
lastModified: "3 dias atrás",
status: "published" as const,
},
]);
return (
<div className="animate-fade-in">
<div className="flex items-center justify-between mb-8">
<div>
<h1 className="text-3xl font-bold text-foreground mb-2">Gestão de Prompts</h1>
<p className="text-muted-foreground">
Crie, edite e gerencie os prompts dos seus agentes de IA
</p>
</div>
<Button className="gap-2">
<Plus className="h-4 w-4" />
Criar Prompt
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{prompts.map((prompt) => (
<PromptCard
key={prompt.id}
title={prompt.title}
creator={prompt.creator}
lastModified={prompt.lastModified}
status={prompt.status}
onEdit={() => console.log("Edit", prompt.id)}
onHistory={() => console.log("History", prompt.id)}
onTest={() => console.log("Test", prompt.id)}
onDuplicate={() => console.log("Duplicate", prompt.id)}
/>
))}
</div>
</div>
);
}
+113
View File
@@ -0,0 +1,113 @@
import { useState } from "react";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { ThumbsUp, ThumbsDown, Send, Sparkles } from "lucide-react";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
export default function TestPrompt() {
const [input, setInput] = useState("");
const [output, setOutput] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleTest = () => {
setIsLoading(true);
setTimeout(() => {
setOutput(
"Esta é uma resposta simulada do agente de IA. Em produção, esta resposta seria gerada pelo modelo de IA configurado com o prompt selecionado."
);
setIsLoading(false);
}, 1500);
};
return (
<div className="animate-fade-in max-w-5xl mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground mb-2">Teste de Prompt</h1>
<p className="text-muted-foreground">
Teste seus prompts em tempo real e avalie as respostas geradas
</p>
</div>
<div className="grid grid-cols-1 gap-6">
<Card className="p-6">
<div className="space-y-4">
<div>
<Label htmlFor="prompt-select">Selecione o Prompt</Label>
<Select>
<SelectTrigger id="prompt-select">
<SelectValue placeholder="Escolha 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>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="input">Entrada de Teste</Label>
<Textarea
id="input"
placeholder="Digite sua mensagem de teste aqui..."
value={input}
onChange={(e) => setInput(e.target.value)}
rows={4}
className="resize-none"
/>
</div>
<Button onClick={handleTest} disabled={!input || isLoading} className="w-full gap-2">
{isLoading ? (
<>
<Sparkles className="h-4 w-4 animate-spin" />
Processando...
</>
) : (
<>
<Send className="h-4 w-4" />
Testar Prompt
</>
)}
</Button>
</div>
</Card>
{output && (
<Card className="p-6 animate-scale-in">
<div className="space-y-4">
<div>
<Label>Resposta Gerada</Label>
<div className="mt-2 p-4 bg-muted rounded-lg">
<p className="text-foreground">{output}</p>
</div>
</div>
<div>
<Label className="mb-2 block">Avaliar Resposta</Label>
<div className="flex gap-2">
<Button variant="outline" className="flex-1 gap-2">
<ThumbsUp className="h-4 w-4" />
Boa Resposta
</Button>
<Button variant="outline" className="flex-1 gap-2">
<ThumbsDown className="h-4 w-4" />
Precisa Melhorar
</Button>
</div>
</div>
</div>
</Card>
)}
</div>
</div>
);
}