summaryrefslogtreecommitdiff
path: root/frontend/src/App.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/App.jsx')
-rw-r--r--frontend/src/App.jsx120
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;