diff options
Diffstat (limited to 'frontend/src/App.jsx')
| -rw-r--r-- | frontend/src/App.jsx | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx new file mode 100644 index 0000000..0396e3a --- /dev/null +++ b/frontend/src/App.jsx @@ -0,0 +1,120 @@ +import { useState, useEffect } from 'react'; +import Sidebar from './components/Sidebar'; +import ChatInterface from './components/ChatInterface'; +import { api } from './api'; +import './App.css'; + +function App() { + const [conversations, setConversations] = useState([]); + const [currentConversationId, setCurrentConversationId] = useState(null); + const [currentConversation, setCurrentConversation] = useState(null); + const [isLoading, setIsLoading] = useState(false); + + // Load conversations on mount + useEffect(() => { + loadConversations(); + }, []); + + // Load conversation details when selected + useEffect(() => { + if (currentConversationId) { + loadConversation(currentConversationId); + } + }, [currentConversationId]); + + const loadConversations = async () => { + try { + const convs = await api.listConversations(); + setConversations(convs); + } catch (error) { + console.error('Failed to load conversations:', error); + } + }; + + const loadConversation = async (id) => { + try { + const conv = await api.getConversation(id); + setCurrentConversation(conv); + } catch (error) { + console.error('Failed to load conversation:', error); + } + }; + + const handleNewConversation = async () => { + try { + const newConv = await api.createConversation(); + setConversations([ + { id: newConv.id, created_at: newConv.created_at, message_count: 0 }, + ...conversations, + ]); + setCurrentConversationId(newConv.id); + } catch (error) { + console.error('Failed to create conversation:', error); + } + }; + + const handleSelectConversation = (id) => { + setCurrentConversationId(id); + }; + + const handleSendMessage = async (content) => { + if (!currentConversationId) return; + + setIsLoading(true); + try { + // Optimistically add user message to UI + const userMessage = { role: 'user', content }; + setCurrentConversation((prev) => ({ + ...prev, + messages: [...prev.messages, userMessage], + })); + + // Send message and get council response + const response = await api.sendMessage(currentConversationId, content); + + // Add assistant message to UI + const assistantMessage = { + role: 'assistant', + stage1: response.stage1, + stage2: response.stage2, + stage3: response.stage3, + metadata: response.metadata, + }; + + setCurrentConversation((prev) => ({ + ...prev, + messages: [...prev.messages, assistantMessage], + })); + + // Reload conversations list to update message count + await loadConversations(); + } catch (error) { + console.error('Failed to send message:', error); + // Remove optimistic user message on error + setCurrentConversation((prev) => ({ + ...prev, + messages: prev.messages.slice(0, -1), + })); + } finally { + setIsLoading(false); + } + }; + + return ( + <div className="app"> + <Sidebar + conversations={conversations} + currentConversationId={currentConversationId} + onSelectConversation={handleSelectConversation} + onNewConversation={handleNewConversation} + /> + <ChatInterface + conversation={currentConversation} + onSendMessage={handleSendMessage} + isLoading={isLoading} + /> + </div> + ); +} + +export default App; |
