From 07510bb115c0b8d10078ee469f6fe8aec8a6ca57 Mon Sep 17 00:00:00 2001 From: phact Date: Fri, 11 Jul 2025 12:14:44 -0400 Subject: [PATCH] chat page in the ui --- frontend/components/navigation.tsx | 8 +- frontend/src/app/chat/page.tsx | 199 +++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 frontend/src/app/chat/page.tsx diff --git a/frontend/components/navigation.tsx b/frontend/components/navigation.tsx index f43df5b7..183107ee 100644 --- a/frontend/components/navigation.tsx +++ b/frontend/components/navigation.tsx @@ -2,7 +2,7 @@ import Link from "next/link" import { usePathname } from "next/navigation" -import { Search, Settings } from "lucide-react" +import { Search, Settings, MessageCircle } from "lucide-react" import { cn } from "@/lib/utils" export function Navigation() { @@ -15,6 +15,12 @@ export function Navigation() { href: "/", active: pathname === "/", }, + { + label: "Chat", + icon: MessageCircle, + href: "/chat", + active: pathname === "/chat", + }, { label: "Admin", icon: Settings, diff --git a/frontend/src/app/chat/page.tsx b/frontend/src/app/chat/page.tsx new file mode 100644 index 00000000..e6b0002c --- /dev/null +++ b/frontend/src/app/chat/page.tsx @@ -0,0 +1,199 @@ +"use client" + +import { useState, useRef, useEffect } from "react" +import { Button } from "@/components/ui/button" +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" +import { Input } from "@/components/ui/input" +import { MessageCircle, Send, Loader2, User, Bot } from "lucide-react" +import { cn } from "@/lib/utils" + +interface Message { + role: "user" | "assistant" + content: string + timestamp: Date +} + +export default function ChatPage() { + const [messages, setMessages] = useState([]) + const [input, setInput] = useState("") + const [loading, setLoading] = useState(false) + const messagesEndRef = useRef(null) + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }) + } + + useEffect(() => { + scrollToBottom() + }, [messages]) + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + if (!input.trim() || loading) return + + const userMessage: Message = { + role: "user", + content: input.trim(), + timestamp: new Date() + } + + setMessages(prev => [...prev, userMessage]) + setInput("") + setLoading(true) + + try { + const response = await fetch("/api/chat", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ prompt: userMessage.content }), + }) + + const result = await response.json() + + if (response.ok) { + const assistantMessage: Message = { + role: "assistant", + content: result.response, + timestamp: new Date() + } + setMessages(prev => [...prev, assistantMessage]) + } else { + console.error("Chat failed:", result.error) + const errorMessage: Message = { + role: "assistant", + content: "Sorry, I encountered an error. Please try again.", + timestamp: new Date() + } + setMessages(prev => [...prev, errorMessage]) + } + } catch (error) { + console.error("Chat error:", error) + const errorMessage: Message = { + role: "assistant", + content: "Sorry, I couldn't connect to the chat service. Please try again.", + timestamp: new Date() + } + setMessages(prev => [...prev, errorMessage]) + } finally { + setLoading(false) + } + } + + return ( +
+
+

Chat Assistant

+

Ask questions about your documents and get AI-powered answers

+
+ + + + + + Chat + + + Chat with AI about your indexed documents + + + + {/* Messages Area */} +
+ {messages.length === 0 ? ( +
+
+ +

Start a conversation by asking a question!

+

I can help you find information in your documents.

+
+
+ ) : ( + <> + {messages.map((message, index) => ( +
+
+
+ {message.role === "user" ? ( + + ) : ( + + )} +
+
+

{message.content}

+

+ {message.timestamp.toLocaleTimeString()} +

+
+
+
+ ))} + {loading && ( +
+
+
+ +
+
+
+ + Thinking... +
+
+
+
+ )} +
+ + )} +
+ + {/* Input Area */} +
+ setInput(e.target.value)} + placeholder="Ask a question about your documents..." + disabled={loading} + className="flex-1" + /> + +
+ + +
+ ) +} \ No newline at end of file