| import React, { useState } from 'react'; |
| import './ChatPage.css'; |
| import { useNavigate } from 'react-router-dom'; |
|
|
| |
| interface Message { |
| sender: 'user' | 'ai'; |
| text: string; |
| } |
|
|
| |
| interface AskResponse { |
| answer: string; |
| source_documents: string[]; |
| } |
|
|
| const ChatPage: React.FC = () => { |
| const [messages, setMessages] = useState<Message[]>([]); |
| const [input, setInput] = useState(''); |
| const [loading, setLoading] = useState(false); |
| const navigate = useNavigate(); |
|
|
| const handleSend = async () => { |
| if (input.trim() === '') return; |
|
|
| const userMessage: Message = { sender: 'user', text: input }; |
| setMessages((prev) => [...prev, userMessage]); |
| setInput(''); |
| setLoading(true); |
|
|
| try { |
|
|
| const res = await fetch('/ask', { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ query: input }), |
| }); |
|
|
|
|
| if (!res.ok) throw new Error('Backend error'); |
|
|
| const data: AskResponse = await res.json(); |
| |
| let aiText = data.answer; |
| if (aiText.includes("π Source Snippets")) { |
| aiText = aiText.split("π Source Snippets")[0].trim(); |
| } |
|
|
| const aiMessage: Message = { sender: 'ai', text: aiText }; |
| setMessages((prev) => [...prev, aiMessage]); |
|
|
| |
| |
|
|
| setMessages((prev) => [...prev, aiMessage]); |
| } catch (err) { |
| console.error('Fetch error:', err); |
| const errorMessage: Message = { sender: 'ai', text: 'β Unable to get a response, please try again later.' }; |
| setMessages((prev) => [...prev, errorMessage]); |
| } finally { |
| setLoading(false); |
| } |
| }; |
|
|
| return ( |
| <div className="chat-container"> |
| <div className="back-button-container"> |
| <button className="back-button" onClick={() => navigate('/')}> |
| π Back to Home Page |
| </button> |
| </div> |
| <header className="chat-header">LabAid AI Chat</header> |
| <div className="chat-messages"> |
| {messages.map((msg, idx) => ( |
| <div key={idx} className={`chat-bubble ${msg.sender}`}> |
| {msg.text} |
| </div> |
| ))} |
| {loading && <div className="chat-bubble ai loading">π¬ thinking...</div>} |
| </div> |
| |
| <div className="chat-input-area"> |
| <input |
| type="text" |
| value={input} |
| onChange={(e) => setInput(e.target.value)} |
| onKeyDown={(e) => { |
| if (e.key === 'Enter') handleSend(); |
| }} |
| placeholder="please enter your question..." |
| /> |
| <button onClick={handleSend} disabled={loading}>send</button> |
| </div> |
| </div> |
| ); |
| }; |
|
|
| export default ChatPage; |