Create HGTX PromptLab UI
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user