Implements the full SPA UI: - App.tsx with BrowserRouter, ProtectedRoute, and all page routes - Sidebar with NavLink active state and logout - Login page with JWT auth flow - Dashboard with parallel data fetching and status tiles - MqttBrokers: CRUD with test-connection button and Topics link - MqttTopics: discovery, filter, json_path inline edit, ignore - PgSources: CRUD form with all required fields - Datapoints: table with inline label/unit editing via onBlur - Displays: layout dropdown, refresh interval, last-seen timestamp - Layouts: left panel list + right panel element editor - EpaperPreview: scaled e-paper simulation with live data support - StatusBadge: color-coded status chip Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.7 KiB
TypeScript
42 lines
1.7 KiB
TypeScript
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
|
import { isLoggedIn } from './api/client';
|
|
import Sidebar from './components/Sidebar';
|
|
import Login from './pages/Login';
|
|
import Dashboard from './pages/Dashboard';
|
|
import MqttBrokers from './pages/MqttBrokers';
|
|
import MqttTopics from './pages/MqttTopics';
|
|
import PgSources from './pages/PgSources';
|
|
import Datapoints from './pages/Datapoints';
|
|
import Displays from './pages/Displays';
|
|
import Layouts from './pages/Layouts';
|
|
|
|
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
|
if (!isLoggedIn()) return <Navigate to="/login" replace />;
|
|
return (
|
|
<div className="flex min-h-screen bg-gray-100">
|
|
<Sidebar />
|
|
<main className="ml-56 flex-1 p-6 overflow-auto">
|
|
{children}
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function App() {
|
|
return (
|
|
<BrowserRouter>
|
|
<Routes>
|
|
<Route path="/login" element={<Login />} />
|
|
<Route path="/" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />
|
|
<Route path="/mqtt/brokers" element={<ProtectedRoute><MqttBrokers /></ProtectedRoute>} />
|
|
<Route path="/mqtt/topics/:brokerId" element={<ProtectedRoute><MqttTopics /></ProtectedRoute>} />
|
|
<Route path="/pg/sources" element={<ProtectedRoute><PgSources /></ProtectedRoute>} />
|
|
<Route path="/datapoints" element={<ProtectedRoute><Datapoints /></ProtectedRoute>} />
|
|
<Route path="/displays" element={<ProtectedRoute><Displays /></ProtectedRoute>} />
|
|
<Route path="/layouts" element={<ProtectedRoute><Layouts /></ProtectedRoute>} />
|
|
<Route path="*" element={<Navigate to="/" replace />} />
|
|
</Routes>
|
|
</BrowserRouter>
|
|
);
|
|
}
|