“vinit5112”
Add all code
deb090d
raw
history blame
7.08 kB
import React, { useState, useEffect } from 'react';
import { Toaster } from 'react-hot-toast';
import ChatInterface from './components/ChatInterface';
import Sidebar from './components/Sidebar';
import WelcomeScreen from './components/WelcomeScreen';
import { SunIcon, MoonIcon, HomeIcon } from '@heroicons/react/24/outline';
import ConversationStorage from './utils/conversationStorage';
function App() {
const [darkMode, setDarkMode] = useState(false);
const [sidebarOpen, setSidebarOpen] = useState(false);
const [chatStarted, setChatStarted] = useState(false);
const [conversations, setConversations] = useState([]);
const [activeConversationId, setActiveConversationId] = useState(null);
useEffect(() => {
// Check for saved theme preference or default to light mode
const savedTheme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
setDarkMode(true);
document.documentElement.classList.add('dark');
}
// Load conversations from localStorage
const savedConversations = ConversationStorage.loadConversations();
if (savedConversations.length > 0) {
setConversations(savedConversations);
setChatStarted(true);
// Set the most recent conversation as active
setActiveConversationId(savedConversations[0].id);
}
}, []);
const toggleDarkMode = () => {
setDarkMode(!darkMode);
if (darkMode) {
document.documentElement.classList.remove('dark');
localStorage.setItem('theme', 'light');
} else {
document.documentElement.classList.add('dark');
localStorage.setItem('theme', 'dark');
}
};
const startNewChat = () => {
const newConversation = {
id: Date.now().toString(),
title: 'New Conversation',
messages: [],
createdAt: new Date(),
updatedAt: new Date(),
};
// Save to localStorage
ConversationStorage.addConversation(newConversation);
setConversations(prev => [newConversation, ...prev]);
setActiveConversationId(newConversation.id);
setChatStarted(true);
setSidebarOpen(false);
};
const deleteConversation = (conversationId) => {
// Delete from localStorage
ConversationStorage.deleteConversation(conversationId);
setConversations(prev => prev.filter(conv => conv.id !== conversationId));
// If the deleted conversation was active, switch to another one
if (activeConversationId === conversationId) {
const remainingConversations = conversations.filter(conv => conv.id !== conversationId);
if (remainingConversations.length > 0) {
setActiveConversationId(remainingConversations[0].id);
} else {
setActiveConversationId(null);
setChatStarted(false);
}
}
};
const updateConversations = (updatedConversations) => {
setConversations(updatedConversations);
// Save to localStorage
ConversationStorage.saveConversations(updatedConversations);
};
const handleFirstMessage = (message) => {
if (!chatStarted) {
startNewChat();
}
};
const goBackToHome = () => {
setActiveConversationId(null);
setChatStarted(false);
setSidebarOpen(false);
};
return (
<div className={`min-h-screen transition-colors duration-200 ${
darkMode
? 'bg-gray-900 text-white'
: 'bg-gray-50 text-gray-900'
}`}>
{/* Header */}
<header className={`fixed top-0 left-0 right-0 z-50 ${
darkMode
? 'bg-gray-800/95 border-gray-700'
: 'bg-white/95 border-gray-200'
} backdrop-blur-sm border-b`}>
<div className="flex items-center justify-between px-4 py-3">
<div className="flex items-center space-x-4">
<button
onClick={() => setSidebarOpen(!sidebarOpen)}
className={`p-2 rounded-lg transition-colors ${
darkMode
? 'hover:bg-gray-700 text-gray-300'
: 'hover:bg-gray-100 text-gray-600'
}`}
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
<button
onClick={goBackToHome}
className="text-lg font-semibold gradient-text hover:opacity-80 transition-opacity"
>
CA Study Assistant
</button>
</div>
<div className="flex items-center space-x-2">
{chatStarted && (
<button
onClick={goBackToHome}
className={`p-2 rounded-lg transition-colors ${
darkMode
? 'hover:bg-gray-700 text-gray-300'
: 'hover:bg-gray-100 text-gray-600'
}`}
title="Back to Home"
>
<HomeIcon className="w-5 h-5" />
</button>
)}
<button
onClick={toggleDarkMode}
className={`p-2 rounded-lg transition-colors ${
darkMode
? 'hover:bg-gray-700 text-gray-300'
: 'hover:bg-gray-100 text-gray-600'
}`}
>
{darkMode ? (
<SunIcon className="w-5 h-5" />
) : (
<MoonIcon className="w-5 h-5" />
)}
</button>
</div>
</div>
</header>
{/* Sidebar */}
<Sidebar
open={sidebarOpen}
onClose={() => setSidebarOpen(false)}
conversations={conversations}
activeConversationId={activeConversationId}
onConversationSelect={setActiveConversationId}
onNewChat={startNewChat}
onDeleteConversation={deleteConversation}
onBackToHome={goBackToHome}
darkMode={darkMode}
/>
{/* Main Content */}
<main className={`transition-all duration-200 ${
sidebarOpen ? 'md:ml-64' : 'ml-0'
} pt-16`}>
{chatStarted ? (
<ChatInterface
conversationId={activeConversationId}
conversations={conversations}
setConversations={updateConversations}
darkMode={darkMode}
/>
) : (
<WelcomeScreen
onStartChat={handleFirstMessage}
onNewChat={startNewChat}
darkMode={darkMode}
/>
)}
</main>
{/* Toast notifications */}
<Toaster
position="top-right"
toastOptions={{
duration: 4000,
style: {
background: darkMode ? '#374151' : '#ffffff',
color: darkMode ? '#f9fafb' : '#111827',
border: darkMode ? '1px solid #4b5563' : '1px solid #e5e7eb',
},
}}
/>
</div>
);
}
export default App;