node-ui / src /components /ChatBox.js
srijan9994's picture
initial commit
0d3ffc3
import React, { useState, useEffect } from "react";
const ChatBox = ({ activeThread }) => {
const [messages, setMessages] = useState([]);
const [userInput, setUserInput] = useState("");
const [isStreaming, setIsStreaming] = useState(false);
const FLASK_API_URL = process.env.FLASK_API_URL;
// useEffect(() => {
// // Fetch existing messages for the active thread
// fetch(`http://127.0.0.1:5000/api/chat/${activeThread}`)
// .then((response) => response.json())
// .then((data) => setMessages(data));
// }, [activeThread]);
const sendMessage = async () => {
if (!userInput.trim()) return;
const newMessage = { sender: "user", message: userInput };
setMessages((prevMessages) => [...prevMessages, newMessage]);
setUserInput("");
try {
setIsStreaming(true);
const response = await fetch(FLASK_API_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ thread_id: activeThread, prompt: userInput }),
});
if (!response.ok) {
console.error("Failed to stream response");
setIsStreaming(false);
return;
}
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
let streamingMessage = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
streamingMessage += chunk;
setMessages((prevMessages) => {
const updatedMessages = [...prevMessages];
const lastMessage = updatedMessages[updatedMessages.length - 1];
if (lastMessage && lastMessage.sender === "bot") {
lastMessage.message = streamingMessage;
} else {
updatedMessages.push({ sender: "bot", message: streamingMessage });
}
return updatedMessages;
});
}
setIsStreaming(false);
} catch (error) {
console.error("Error during streaming:", error);
setIsStreaming(false);
}
};
const renderMessage = (message) => {
if (message.message.includes("```")) {
// Handle code block
const parts = message.message.split(/```/g);
return parts.map((part, index) => (
<div key={index}>
{index % 2 === 0 ? (
<p style={{ whiteSpace: "pre-wrap", margin: "5px 0" }}>{part}</p>
) : (
<pre
style={{
backgroundColor: "#333",
color: "#f5f5f5",
padding: "10px",
borderRadius: "5px",
margin: "5px 0",
overflowX: "auto",
}}
>
<code>{part}</code>
</pre>
)}
</div>
));
}
// Plain text message
return <p style={{ whiteSpace: "pre-wrap", margin: "5px 0" }}>{message.message}</p>;
};
const handleKeyDown = (event) => {
if (event.key === "Enter") {
sendMessage();
}
};
return (
<div
style={{
width: "80%",
display: "flex",
flexDirection: "column",
padding: "10px",
backgroundColor: "#1e1e1e",
color: "#f5f5f5",
}}
>
<div
style={{
flex: 1,
overflowY: "auto",
border: "1px solid #333",
borderRadius: "5px",
marginBottom: "10px",
padding: "10px",
backgroundColor: "#121212",
}}
>
{messages.map((msg, index) => (
<div
key={index}
style={{
display: "flex",
justifyContent: msg.sender === "user" ? "flex-end" : "flex-start",
marginBottom: "10px",
}}
>
<div
style={{
maxWidth: "70%",
padding: "10px",
backgroundColor: msg.sender === "user" ? "#333" : "#444",
color: msg.sender === "user" ? "#ffa726" : "#f5f5f5",
borderRadius: "10px",
textAlign: "left",
}}
>
{renderMessage(msg)}
</div>
</div>
))}
{isStreaming && (
<div style={{ color: "#64b5f6" }}>
<em>Bot is typing...</em>
</div>
)}
</div>
<div style={{ display: "flex" }}>
<input
type="text"
value={userInput}
onChange={(e) => setUserInput(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Type your message..."
style={{
flex: 1,
padding: "10px",
border: "1px solid #333",
borderRadius: "5px",
backgroundColor: "#333",
color: "#f5f5f5",
}}
/>
<button
onClick={sendMessage}
style={{
marginLeft: "10px",
padding: "10px",
backgroundColor: "#333",
color: "#f5f5f5",
border: "none",
borderRadius: "5px",
cursor: "pointer",
}}
>
Send
</button>
</div>
</div>
);
};
export default ChatBox;