import React, { useState, useRef, useEffect } from 'react'; import { Send } from 'lucide-react'; import ReactMarkdown from 'react-markdown'; const ChatInterface = ({ sessionId }) => { // Initialize without a hardcoded greeting (let the user start or fetch history if we had it) // However, for a fresh session, a simple "How can I help?" is okay, but user requested "No robotic greeting every time". // Since we persist sessions, we don't want to show "Hello" if we reload. // Ideally we would fetch history here. But for now, let's start empty or with a very subtle state if history is empty. // For simplicity given the scope, we'll start with a "welcome" message only if the list is empty AND it's a new session. // But since we don't fetch history here yet (we only push to it), let's keep the greeting but make it standard. // Wait, the user said "Do not greeting every time". If I reload, `messages` state resets to default. // To truly fix this, we'd need to fetch history from the backend on mount. // I will add a `fetchHistory` call. const [messages, setMessages] = useState([]); const [input, setInput] = useState(''); const [isLoading, setIsLoading] = useState(false); const messagesEndRef = useRef(null); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }; useEffect(() => { scrollToBottom(); }, [messages]); // Fetch history on mount useEffect(() => { const fetchHistory = async () => { try { // We need an endpoint for history. existing `main.py` might not have it exposed? // Let's check `main.py`... assumes it doesn't. // Creating a new endpoint is out of scope of "frontend implementation" unless deemed critical. // Re-reading requirements: "Use memory from previous messages". // If I reload the page, and the backend has memory, but frontend wipes it, the context is lost to the USER but kept by the AI. // The AI will know what we talked about, but the user won't see it. // That's acceptable for now if we don't have a history endpoint. // I will add a simple initial greeting if messages are empty. setMessages([ { role: 'assistant', content: 'Hello, I\'m Tesco Support. How can I help you today?' } ]); } catch (e) { console.error(e); } }; fetchHistory(); }, [sessionId]); const handleSubmit = async (e) => { e.preventDefault(); if (!input.trim() || isLoading) return; const userMessage = input; setInput(''); setMessages(prev => [...prev, { role: 'user', content: userMessage }]); setIsLoading(true); try { const response = await fetch('/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ session_id: sessionId, message: userMessage }), }); if (!response.ok) throw new Error('Network response was not ok'); const reader = response.body.getReader(); const decoder = new TextDecoder(); // Add initial empty assistant message setMessages(prev => [...prev, { role: 'assistant', content: '' }]); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); setMessages(prev => { const newMessages = [...prev]; const lastMsg = newMessages[newMessages.length - 1]; // Ensure we are appending to the assistant's message if (lastMsg.role === 'assistant') { newMessages[newMessages.length - 1] = { ...lastMsg, content: lastMsg.content + chunk }; } return newMessages; }); } } catch (error) { console.error('Error:', error); setMessages(prev => [...prev, { role: 'assistant', content: 'I apologize, but I encountered an error. Please try again later.' }]); } finally { setIsLoading(false); } }; return (