"use client"; import { useState, useRef, useEffect } from "react"; interface Message { id: string; role: string; content: string; created_at: string; } interface Chat { id: string; title: string; model_alias: string; } const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || "http://127.0.0.1:18000"; export default function ChatView({ chat, initialMessages }: { chat: Chat, initialMessages: Message[] }) { const [messages, setMessages] = useState(initialMessages); const [input, setInput] = useState(""); const [isSending, setIsSending] = useState(false); const [isGenerating, setIsGenerating] = useState(false); const scrollRef = useRef(null); useEffect(() => { if (scrollRef.current) { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } }, [messages, isGenerating]); // Also scroll when isGenerating changes const handleSend = async (e: React.FormEvent) => { e.preventDefault(); if (!input.trim() || isSending || isGenerating) return; setIsSending(true); const content = input; setInput(""); // Eagerly show user message map const tempUserMsg: Message = { id: "temp-" + Date.now(), role: "user", content: content, created_at: new Date().toISOString() }; setMessages(prev => [...prev, tempUserMsg]); setIsGenerating(true); try { const res = await fetch(`${API_BASE_URL}/api/chats/${chat.id}/messages`, { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify({ content, role: "user" }), }); if (!res.ok) throw new Error("Failed to send message"); const data = await res.json(); if (!Array.isArray(data) || data.length < 2) { throw new Error("Invalid response format from server"); } const [userMsg, assistantMsg] = data; // Replace the temp user msg and append the actual user and assistant messages from backend setMessages(prev => [...prev.filter(m => m.id !== tempUserMsg.id), userMsg, assistantMsg]); } catch (err) { console.error(err); alert("Failed to send message: " + err); setInput(content); // restore input setMessages(prev => prev.filter(m => m.id !== tempUserMsg.id)); // Remove failed message } finally { setIsSending(false); setIsGenerating(false); } }; return (
{/* Dynamic Chat Header */}

{chat.title}

Модель: {chat.model_alias}
{/* Messages Scroll Area */}
{messages.length === 0 ? (
Напишите первое сообщение, чтобы начать диалог.
) : (
{messages.map(msg => { const isUser = msg.role === 'user'; return (
{isUser ? 'Вы' : 'AI Помощник'} {new Date(msg.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
{msg.content}
); })} {/* Loading Indicator for AI Response */} {isGenerating && (
AI Помощник
Печатает...
)}
)}
{/* Composer */}
setInput(e.target.value)} placeholder="Спросите о чем-нибудь..." style={{ flex: 1, padding: '14px 110px 14px 20px', borderRadius: 24, border: "1px solid var(--border-color)", backgroundColor: "var(--bg-color)", fontSize: 15, outline: "none", transition: "border-color 0.2s" }} disabled={isSending} onFocus={e => e.target.style.borderColor = 'var(--primary)'} onBlur={e => e.target.style.borderColor = 'var(--border-color)'} />
); }