Spaces:
Sleeping
Sleeping
| import React, { useEffect } from "react"; | |
| import { Routes, Route, Navigate, useLocation } from "react-router-dom"; | |
| import { useStore } from "./state/store"; | |
| import { Sidebar } from "./components/Sidebar"; | |
| import { Topbar } from "./components/Topbar"; | |
| import { Orbit } from "./components/Orbit"; | |
| // Pages | |
| import Login from "./pages/user/Login"; | |
| import Signup from "./pages/user/Signup"; | |
| import Main from "./pages/user/Main"; | |
| import Chat from "./pages/user/Chat"; | |
| import History from "./pages/user/History"; | |
| import ApiKeys from "./pages/user/ApiKeys"; | |
| import HowTo from "./pages/user/HowTo"; | |
| import About from "./pages/user/About"; | |
| import Settings from "./pages/user/Settings"; | |
| // Admin pages | |
| import Monitor from "./pages/admin/Monitor"; | |
| import Knowledge from "./pages/admin/Knowledge"; | |
| import Skills from "./pages/admin/Skills"; | |
| import VFS from "./pages/admin/VFS"; | |
| import Verify from "./pages/admin/Verify"; | |
| import Logs from "./pages/admin/Logs"; | |
| import Users from "./pages/admin/Users"; | |
| import Connections from "./pages/admin/Connections"; | |
| // Landing | |
| import Landing from "./pages/Landing"; | |
| // Backend API | |
| const API_BASE = "https://princeaka-multimodal-module.hf.space"; | |
| export async function apiFetch(endpoint, method = "GET", body = null, token = null) { | |
| const headers = { "Content-Type": "application/json" }; | |
| if (token) headers["Authorization"] = `Bearer ${token}`; | |
| const res = await fetch(`${API_BASE}${endpoint}`, { | |
| method, | |
| headers, | |
| body: body ? JSON.stringify(body) : undefined, | |
| }); | |
| if (!res.ok) { | |
| const errText = await res.text(); | |
| throw new Error(`API ${res.status}: ${errText}`); | |
| } | |
| return res.json(); | |
| } | |
| // β Protected route wrapper | |
| function Protected({ children, role }) { | |
| const { auth } = useStore(); | |
| if (!auth.token) return <Navigate to="/login" replace />; | |
| if (role && auth.role !== role) return <Navigate to="/" replace />; | |
| return children; | |
| } | |
| export default function App() { | |
| const { ui, setUi } = useStore(); | |
| const loc = useLocation(); | |
| const isAuthPage = loc.pathname === "/login" || loc.pathname === "/signup"; | |
| // β Auto-clear toast after 4s | |
| useEffect(() => { | |
| if (ui.toast) { | |
| const timer = setTimeout(() => setUi(u => ({ ...u, toast: null })), 4000); | |
| return () => clearTimeout(timer); | |
| } | |
| }, [ui.toast, setUi]); | |
| return ( | |
| <div style={{ height: "100%" }}> | |
| <Routes> | |
| {/* Landing page */} | |
| <Route path="/landing" element={<Landing />} /> | |
| {/* Auth pages */} | |
| <Route path="/login" element={<Login />} /> | |
| <Route path="/signup" element={<Signup />} /> | |
| {/* Protected app pages */} | |
| <Route | |
| path="/*" | |
| element={ | |
| !isAuthPage ? ( | |
| <div className="app"> | |
| <Sidebar /> | |
| <div className="main"> | |
| <header className="topbar"> | |
| <Topbar /> | |
| </header> | |
| <div className="content"> | |
| <Routes> | |
| <Route path="/" element={<Protected><Main /></Protected>} /> | |
| <Route path="/chat" element={<Protected><Chat /></Protected>} /> | |
| <Route path="/history" element={<Protected><History /></Protected>} /> | |
| <Route path="/apikeys" element={<Protected><ApiKeys /></Protected>} /> | |
| <Route path="/howto" element={<Protected><HowTo /></Protected>} /> | |
| <Route path="/about" element={<Protected><About /></Protected>} /> | |
| <Route path="/settings" element={<Protected><Settings /></Protected>} /> | |
| {/* Admin routes */} | |
| <Route path="/admin/monitor" element={<Protected role="admin"><Monitor /></Protected>} /> | |
| <Route path="/admin/knowledge" element={<Protected role="admin"><Knowledge /></Protected>} /> | |
| <Route path="/admin/skills" element={<Protected role="admin"><Skills /></Protected>} /> | |
| <Route path="/admin/vfs" element={<Protected role="admin"><VFS /></Protected>} /> | |
| <Route path="/admin/verify" element={<Protected role="admin"><Verify /></Protected>} /> | |
| <Route path="/admin/logs" element={<Protected role="admin"><Logs /></Protected>} /> | |
| <Route path="/admin/users" element={<Protected role="admin"><Users /></Protected>} /> | |
| <Route path="/admin/connections" element={<Protected role="admin"><Connections /></Protected>} /> | |
| </Routes> | |
| </div> | |
| </div> | |
| <Orbit /> | |
| </div> | |
| ) : ( | |
| <Navigate to="/landing" replace /> | |
| ) | |
| } | |
| /> | |
| {/* Default redirect */} | |
| <Route path="*" element={<Navigate to="/landing" replace />} /> | |
| </Routes> | |
| {/* β Toast */} | |
| {ui.toast && ( | |
| <div className="toast fixed bottom-4 right-4 bg-black text-white px-4 py-2 rounded shadow-lg z-50"> | |
| {ui.toast} | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |