2026-06-19 19:14:27 +03:00
|
|
|
import { useEffect } from "react";
|
2026-06-19 11:28:04 +03:00
|
|
|
import { Routes, Route, Navigate } from "react-router-dom";
|
|
|
|
|
import { useAuthStore } from "@/store/auth";
|
2026-06-19 19:14:27 +03:00
|
|
|
import { useUiStore } from "@/store/ui";
|
2026-06-19 11:28:04 +03:00
|
|
|
import { Navbar } from "@/components/ui/Navbar";
|
|
|
|
|
import { HomePage } from "@/pages/HomePage";
|
|
|
|
|
import { LoginPage } from "@/pages/LoginPage";
|
|
|
|
|
import { RegisterPage } from "@/pages/RegisterPage";
|
|
|
|
|
import { AdminSetupPage } from "@/pages/AdminSetupPage";
|
|
|
|
|
import { DashboardPage } from "@/pages/DashboardPage";
|
|
|
|
|
import { WorldCreatePage } from "@/pages/WorldCreatePage";
|
|
|
|
|
import { WorldBuilderPage } from "@/pages/WorldBuilderPage";
|
|
|
|
|
import { WorldEditPage } from "@/pages/WorldEditPage";
|
|
|
|
|
import { SessionPage } from "@/pages/SessionPage";
|
|
|
|
|
import { AdminPanelPage } from "@/pages/AdminPanelPage";
|
|
|
|
|
|
|
|
|
|
function PrivateRoute({ children }: { children: JSX.Element }) {
|
|
|
|
|
const token = useAuthStore((s) => s.token);
|
|
|
|
|
if (!token) return <Navigate to="/login" replace />;
|
|
|
|
|
return children;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function AdminRoute({ children }: { children: JSX.Element }) {
|
|
|
|
|
const { token, user } = useAuthStore();
|
|
|
|
|
if (!token) return <Navigate to="/login" replace />;
|
|
|
|
|
if (!user?.is_admin) return <Navigate to="/dashboard" replace />;
|
|
|
|
|
return children;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function App() {
|
2026-06-19 19:14:27 +03:00
|
|
|
// Load public UI settings (logo URL, etc.) once on app boot. These are
|
|
|
|
|
// unauthenticated and cached by the api layer, so subsequent navigations
|
|
|
|
|
// do not re-fetch. The admin panel calls load(true) after saving to
|
|
|
|
|
// pick up a new logo URL without a full page reload.
|
|
|
|
|
const loadUi = useUiStore((s) => s.load);
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
loadUi();
|
|
|
|
|
}, [loadUi]);
|
|
|
|
|
|
2026-06-19 11:28:04 +03:00
|
|
|
return (
|
|
|
|
|
<div className="min-h-screen flex flex-col">
|
|
|
|
|
<Navbar />
|
|
|
|
|
<main className="flex-1">
|
|
|
|
|
<Routes>
|
|
|
|
|
<Route path="/" element={<HomePage />} />
|
|
|
|
|
<Route path="/login" element={<LoginPage />} />
|
|
|
|
|
<Route path="/register" element={<RegisterPage />} />
|
|
|
|
|
<Route path="/admin/setup" element={<AdminSetupPage />} />
|
|
|
|
|
<Route
|
|
|
|
|
path="/dashboard"
|
|
|
|
|
element={
|
|
|
|
|
<PrivateRoute>
|
|
|
|
|
<DashboardPage />
|
|
|
|
|
</PrivateRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/worlds/new"
|
|
|
|
|
element={
|
|
|
|
|
<PrivateRoute>
|
|
|
|
|
<WorldCreatePage />
|
|
|
|
|
</PrivateRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/worlds/:id/edit"
|
|
|
|
|
element={
|
|
|
|
|
<PrivateRoute>
|
|
|
|
|
<WorldEditPage />
|
|
|
|
|
</PrivateRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/worlds/builder"
|
|
|
|
|
element={
|
|
|
|
|
<PrivateRoute>
|
|
|
|
|
<WorldBuilderPage />
|
|
|
|
|
</PrivateRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/sessions/:id"
|
|
|
|
|
element={
|
|
|
|
|
<PrivateRoute>
|
|
|
|
|
<SessionPage />
|
|
|
|
|
</PrivateRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route
|
|
|
|
|
path="/admin"
|
|
|
|
|
element={
|
|
|
|
|
<AdminRoute>
|
|
|
|
|
<AdminPanelPage />
|
|
|
|
|
</AdminRoute>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Route path="*" element={<Navigate to="/" replace />} />
|
|
|
|
|
</Routes>
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|