|
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; |