Refactor: Transform prompt test page into chat interface

This commit is contained in:
gpt-engineer-app[bot]
2025-10-29 13:44:55 +00:00
parent b42f94ecab
commit 2df00b1124
+122 -64
View File
@@ -1,9 +1,10 @@
import { useState } from "react";
import { useState, useRef, useEffect } from "react";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { ThumbsUp, ThumbsDown, Send, Sparkles } from "lucide-react";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Send, Bot, User } from "lucide-react";
import {
Select,
SelectContent,
@@ -12,36 +13,73 @@ import {
SelectValue,
} from "@/components/ui/select";
type Message = {
id: string;
role: "user" | "assistant";
content: string;
};
export default function TestPrompt() {
const [input, setInput] = useState("");
const [output, setOutput] = useState("");
const [messages, setMessages] = useState<Message[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [selectedPrompt, setSelectedPrompt] = useState("");
const scrollRef = useRef<HTMLDivElement>(null);
const handleTest = () => {
useEffect(() => {
if (scrollRef.current) {
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
}
}, [messages]);
const handleSend = () => {
if (!input.trim() || !selectedPrompt) return;
const userMessage: Message = {
id: Date.now().toString(),
role: "user",
content: input,
};
setMessages((prev) => [...prev, userMessage]);
setInput("");
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."
);
const aiMessage: Message = {
id: (Date.now() + 1).toString(),
role: "assistant",
content:
"Esta é uma resposta simulada do agente de IA. Em produção, esta resposta seria gerada pelo modelo de IA configurado com o prompt selecionado. A conversa continua naturalmente.",
};
setMessages((prev) => [...prev, aiMessage]);
setIsLoading(false);
}, 1500);
};
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
handleSend();
}
};
return (
<div className="animate-fade-in max-w-5xl mx-auto">
<div className="mb-8">
<div className="animate-fade-in h-full flex flex-col max-w-5xl mx-auto">
<div className="mb-6">
<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
Converse com a IA para testar como o prompt se comporta
</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>
<Card className="flex-1 flex flex-col overflow-hidden">
{/* Selector de Prompt */}
<div className="p-4 border-b border-border">
<Label htmlFor="prompt-select" className="mb-2 block">
Selecione o Prompt
</Label>
<Select value={selectedPrompt} onValueChange={setSelectedPrompt}>
<SelectTrigger id="prompt-select">
<SelectValue placeholder="Escolha um prompt" />
</SelectTrigger>
@@ -53,61 +91,81 @@ export default function TestPrompt() {
</Select>
</div>
<div>
<Label htmlFor="input">Entrada de Teste</Label>
<Textarea
id="input"
placeholder="Digite sua mensagem de teste aqui..."
{/* Chat Area */}
<ScrollArea className="flex-1 p-4" ref={scrollRef}>
<div className="space-y-4">
{messages.length === 0 ? (
<div className="flex items-center justify-center h-full text-muted-foreground">
<p>Selecione um prompt e comece a conversar</p>
</div>
) : (
messages.map((message) => (
<div
key={message.id}
className={`flex gap-3 ${
message.role === "user" ? "justify-end" : "justify-start"
}`}
>
{message.role === "assistant" && (
<div className="w-8 h-8 rounded-full bg-primary flex items-center justify-center flex-shrink-0">
<Bot className="w-5 h-5 text-primary-foreground" />
</div>
)}
<div
className={`max-w-[70%] rounded-lg p-3 ${
message.role === "user"
? "bg-primary text-primary-foreground"
: "bg-muted text-foreground"
}`}
>
<p className="text-sm whitespace-pre-wrap">{message.content}</p>
</div>
{message.role === "user" && (
<div className="w-8 h-8 rounded-full bg-secondary flex items-center justify-center flex-shrink-0">
<User className="w-5 h-5 text-secondary-foreground" />
</div>
)}
</div>
))
)}
{isLoading && (
<div className="flex gap-3 justify-start">
<div className="w-8 h-8 rounded-full bg-primary flex items-center justify-center flex-shrink-0">
<Bot className="w-5 h-5 text-primary-foreground" />
</div>
<div className="bg-muted rounded-lg p-3">
<div className="flex gap-1">
<div className="w-2 h-2 rounded-full bg-foreground/50 animate-bounce" />
<div className="w-2 h-2 rounded-full bg-foreground/50 animate-bounce" style={{ animationDelay: "0.1s" }} />
<div className="w-2 h-2 rounded-full bg-foreground/50 animate-bounce" style={{ animationDelay: "0.2s" }} />
</div>
</div>
</div>
)}
</div>
</ScrollArea>
{/* Input Area */}
<div className="p-4 border-t border-border">
<div className="flex gap-2">
<Input
placeholder="Digite sua mensagem..."
value={input}
onChange={(e) => setInput(e.target.value)}
rows={4}
className="resize-none"
onKeyPress={handleKeyPress}
disabled={isLoading || !selectedPrompt}
className="flex-1"
/>
</div>
<Button onClick={handleTest} disabled={!input || isLoading} className="w-full gap-2">
{isLoading ? (
<>
<Sparkles className="h-4 w-4 animate-spin" />
Processando...
</>
) : (
<>
<Button
onClick={handleSend}
disabled={!input.trim() || isLoading || !selectedPrompt}
size="icon"
>
<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>
);
}