Jaita's picture
Update src/App.jsx
c24f5d5 verified
import React, { useState, useEffect } from 'react';
import { FaPaperPlane } from "react-icons/fa";
import { FiMenu } from 'react-icons/fi';
import { SunIcon, MoonIcon } from '@heroicons/react/24/outline';
import chatbotIcon from './assets/chatbot-icon.png';
import './App.css';
import logo from './assets/chatbot-icon.png';
import ReactMarkdown from "react-markdown";
function App() {
const [userInput, setUserInput] = useState('');
const [chatLog, setChatLog] = useState([]);
const [loading, setLoading] = useState(false);
const [darkMode, setDarkMode] = useState(false);
// Generate a sessionId for this browser session
const [sessionId] = useState(() => `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
//console.log(sessionId);
// Load theme from localStorage on mount
useEffect(() => {
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
setDarkMode(true);
document.documentElement.classList.add('dark');
}
}, []);
// On mount, start with an empty chat window (do NOT load previous messages)
useEffect(() => {
//localStorage.removeItem('chatLog'); // Optional: ensures no old data
setChatLog([]);
}, []);
// Toggle theme and persist
const toggleTheme = () => {
const newTheme = darkMode ? 'light' : 'dark';
setDarkMode(!darkMode);
localStorage.setItem('theme', newTheme);
document.documentElement.classList.toggle('dark', newTheme === 'dark');
};
const handleSubmit = async (event) => {
event.preventDefault();
if (!userInput.trim()) return; // Don't send empty messages
const userMessage = { type: 'user', text: userInput, ts: Date.now(), sessionId };
const newChatLog = [...chatLog, userMessage];
setChatLog(newChatLog);
setUserInput('');
setLoading(true);
try {
// The API call to our FastAPI backend
const response = await fetch('https://nova-chatbot-chatbot-backend.hf.space/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ user_message: userInput }),
});
//console.log("response",response);
//console.log("response.json()",response.json())
//if (!response.ok) {
// Read raw text so HTML errors don’t crash JSON parsing
// const text = await response.text();
// throw new Error(`Backend ${response.status}: ${text}`);
//} else {
// data = await response.json(); // safe now
//}
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
//consoloe.log("data",data)
const botMessage = { type: 'bot', text: data.bot_response, ts: Date.now(), sessionId };
// Update the chat log with the bot's response
const finalChatLog = [...newChatLog, botMessage];
setChatLog(finalChatLog);
// Save both messages to history (not loaded on refresh)
const history = JSON.parse(localStorage.getItem('chatHistory') || '[]');
const updatedHistory = [...history, userMessage, botMessage];
localStorage.setItem('chatHistory', JSON.stringify(updatedHistory));
} catch (error) {
console.error('Error fetching chat response:', error);
const errorMessage = { type: 'error', text: 'Sorry, something went wrong. Please try again.' };
setChatLog(prev => [...prev, errorMessage]);
// Save error to history if needed
const history = JSON.parse(localStorage.getItem('chatHistory') || '[]');
localStorage.setItem('chatHistory', JSON.stringify([...history, errorMessage]));
} finally {
setLoading(false);
}
};
return (
<div className="App">
<div className="header">
<img src={logo} alt="Logo" className="logo" />
<h1>NOVA</h1>
</div>
<div className="chat-window">
{chatLog.map((message, index) => (
<div key={index} className={`message ${message.type}`}>
<ReactMarkdown>{message.text}</ReactMarkdown>
</div>
))}
{loading && <div className="message bot">Loading...</div>}
</div>
<form onSubmit={handleSubmit} className="chat-form">
<input
type="text"
value={userInput}
onChange={(e) => setUserInput(e.target.value)}
placeholder="Type your message..."
disabled={loading}
/>
{/*<button type="submit" disabled={loading}>Send</button>*/}
<button
onClick={handleSubmit}
className="send-button"
aria-label="Send"
style={{
backgroundColor: "#007bff",
color: "#fff",
padding: "10px 15px",
borderRadius: "8px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<FaPaperPlane size={18} />
</button>
</form>
</div>
);
}
export default App;