|
1 | 1 | import { useCallback, useEffect, useRef, useState } from "react"; |
2 | 2 | import { useRunStore } from "./store/useRunStore"; |
3 | 3 | import { useAuthStore } from "./store/useAuthStore"; |
| 4 | +import { useConfigStore } from "./store/useConfigStore"; |
4 | 5 | import { useWebSocket } from "./store/useWebSocket"; |
5 | 6 | import { listRuns, listEntrypoints, getRun } from "./api/client"; |
6 | 7 | import type { RunDetail } from "./types/run"; |
7 | 8 | import { useHashRoute } from "./hooks/useHashRoute"; |
8 | 9 | import { useIsMobile } from "./hooks/useIsMobile"; |
9 | 10 | import Sidebar from "./components/layout/Sidebar"; |
| 11 | +import StatusBar from "./components/layout/StatusBar"; |
10 | 12 | import NewRunPanel from "./components/runs/NewRunPanel"; |
11 | 13 | import SetupView from "./components/runs/SetupView"; |
12 | 14 | import RunDetailsPanel from "./components/runs/RunDetailsPanel"; |
@@ -40,15 +42,17 @@ export default function App() { |
40 | 42 | } |
41 | 43 | }, [view, routeRunId, selectedRunId, selectRun]); |
42 | 44 |
|
43 | | - // Load existing runs, entrypoints, and auth status on mount |
| 45 | + // Load existing runs, entrypoints, auth status, and config on mount |
44 | 46 | const initAuth = useAuthStore((s) => s.init); |
| 47 | + const initConfig = useConfigStore((s) => s.init); |
45 | 48 | useEffect(() => { |
46 | 49 | listRuns().then(setRuns).catch(console.error); |
47 | 50 | listEntrypoints() |
48 | 51 | .then((eps) => setEntrypoints(eps.map((e) => e.name))) |
49 | 52 | .catch(console.error); |
50 | 53 | initAuth(); |
51 | | - }, [setRuns, setEntrypoints, initAuth]); |
| 54 | + initConfig(); |
| 55 | + }, [setRuns, setEntrypoints, initAuth, initConfig]); |
52 | 56 |
|
53 | 57 | const selectedRun = selectedRunId ? runs[selectedRunId] : null; |
54 | 58 |
|
@@ -182,49 +186,52 @@ export default function App() { |
182 | 186 | }; |
183 | 187 |
|
184 | 188 | return ( |
185 | | - <div className="flex h-screen w-screen relative"> |
186 | | - {/* Mobile hamburger button */} |
187 | | - {isMobile && !sidebarOpen && ( |
188 | | - <button |
189 | | - onClick={() => setSidebarOpen(true)} |
190 | | - className="fixed top-2 left-2 z-40 w-9 h-9 flex items-center justify-center rounded-lg cursor-pointer" |
191 | | - style={{ background: "var(--bg-secondary)", border: "1px solid var(--border)" }} |
192 | | - > |
193 | | - <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"> |
194 | | - <line x1="3" y1="6" x2="21" y2="6" /> |
195 | | - <line x1="3" y1="12" x2="21" y2="12" /> |
196 | | - <line x1="3" y1="18" x2="21" y2="18" /> |
197 | | - </svg> |
198 | | - </button> |
199 | | - )} |
200 | | - <Sidebar |
201 | | - runs={Object.values(runs)} |
202 | | - selectedRunId={selectedRunId} |
203 | | - onSelectRun={handleSelectRun} |
204 | | - onNewRun={handleNewRun} |
205 | | - isMobile={isMobile} |
206 | | - isOpen={sidebarOpen} |
207 | | - onClose={() => setSidebarOpen(false)} |
208 | | - /> |
209 | | - <main className="flex-1 overflow-hidden bg-[var(--bg-primary)]"> |
210 | | - {view === "new" ? ( |
211 | | - <NewRunPanel /> |
212 | | - ) : view === "setup" && setupEntrypoint && setupMode ? ( |
213 | | - <SetupView |
214 | | - entrypoint={setupEntrypoint} |
215 | | - mode={setupMode} |
216 | | - ws={ws} |
217 | | - onRunCreated={handleRunCreated} |
218 | | - isMobile={isMobile} |
219 | | - /> |
220 | | - ) : selectedRun ? ( |
221 | | - <RunDetailsPanel run={selectedRun} ws={ws} isMobile={isMobile} /> |
222 | | - ) : ( |
223 | | - <div className="flex items-center justify-center h-full text-[var(--text-muted)]"> |
224 | | - Select a run or create a new one |
225 | | - </div> |
| 189 | + <div className="flex flex-col h-screen w-screen"> |
| 190 | + <div className="flex flex-1 overflow-hidden relative"> |
| 191 | + {/* Mobile hamburger button */} |
| 192 | + {isMobile && !sidebarOpen && ( |
| 193 | + <button |
| 194 | + onClick={() => setSidebarOpen(true)} |
| 195 | + className="fixed top-2 left-2 z-40 w-9 h-9 flex items-center justify-center rounded-lg cursor-pointer" |
| 196 | + style={{ background: "var(--bg-secondary)", border: "1px solid var(--border)" }} |
| 197 | + > |
| 198 | + <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"> |
| 199 | + <line x1="3" y1="6" x2="21" y2="6" /> |
| 200 | + <line x1="3" y1="12" x2="21" y2="12" /> |
| 201 | + <line x1="3" y1="18" x2="21" y2="18" /> |
| 202 | + </svg> |
| 203 | + </button> |
226 | 204 | )} |
227 | | - </main> |
| 205 | + <Sidebar |
| 206 | + runs={Object.values(runs)} |
| 207 | + selectedRunId={selectedRunId} |
| 208 | + onSelectRun={handleSelectRun} |
| 209 | + onNewRun={handleNewRun} |
| 210 | + isMobile={isMobile} |
| 211 | + isOpen={sidebarOpen} |
| 212 | + onClose={() => setSidebarOpen(false)} |
| 213 | + /> |
| 214 | + <main className="flex-1 overflow-hidden bg-[var(--bg-primary)]"> |
| 215 | + {view === "new" ? ( |
| 216 | + <NewRunPanel /> |
| 217 | + ) : view === "setup" && setupEntrypoint && setupMode ? ( |
| 218 | + <SetupView |
| 219 | + entrypoint={setupEntrypoint} |
| 220 | + mode={setupMode} |
| 221 | + ws={ws} |
| 222 | + onRunCreated={handleRunCreated} |
| 223 | + isMobile={isMobile} |
| 224 | + /> |
| 225 | + ) : selectedRun ? ( |
| 226 | + <RunDetailsPanel run={selectedRun} ws={ws} isMobile={isMobile} /> |
| 227 | + ) : ( |
| 228 | + <div className="flex items-center justify-center h-full text-[var(--text-muted)]"> |
| 229 | + Select a run or create a new one |
| 230 | + </div> |
| 231 | + )} |
| 232 | + </main> |
| 233 | + </div> |
| 234 | + <StatusBar /> |
228 | 235 | <ReloadToast /> |
229 | 236 | </div> |
230 | 237 | ); |
|
0 commit comments