Spaces:
Sleeping
Sleeping
| 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; |