Skip to content

Commit a39ae8c

Browse files
authored
feat: simple app router with protected admin route (#30)
1 parent 2f42fa3 commit a39ae8c

10 files changed

Lines changed: 113 additions & 10 deletions

File tree

webapp/package-lock.json

Lines changed: 59 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webapp/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"react-chartjs-2": "^5.3.1",
3232
"react-dom": "^19.2.0",
3333
"react-resizable-panels": "^3.0.6",
34+
"react-router-dom": "^7.13.0",
3435
"recharts": "^2.15.4"
3536
},
3637
"devDependencies": {
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
1-
import { MainPage } from '@pages';
1+
import { MainPage } from "@/pages";
2+
import { lazy } from "react";
3+
import { BrowserRouter, Route, Routes } from "react-router-dom";
4+
import { AdminRoute } from "./lib/ProtectedRoute";
5+
6+
const AdminPage = lazy(() => import("@/pages/admin"));
7+
const LoginPage = lazy(() => import("@/pages/login"));
28

39
export function AppRouter() {
4-
return <MainPage />;
10+
return (
11+
<BrowserRouter>
12+
<Routes>
13+
<Route path="" element={<MainPage />} />
14+
<Route path="login" element={<LoginPage />} />
15+
<Route element={<AdminRoute />}>
16+
<Route path="admin" element={<AdminPage />} />
17+
</Route>
18+
</Routes>
19+
</BrowserRouter>
20+
);
521
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { useAuth } from "@/app/providers/AuthProvider";
2+
import { Navigate, Outlet, useLocation } from "react-router-dom";
3+
4+
/**
5+
* Route guard for admin routes.
6+
* Redirect to login page if not authenticated.
7+
*/
8+
export function AdminRoute() {
9+
const { isAuthenticated } = useAuth();
10+
const location = useLocation();
11+
12+
if (!isAuthenticated) {
13+
return <Navigate to="/login" state={{ from: location }} replace />;
14+
}
15+
16+
return <Outlet />;
17+
}

webapp/src/pages/MainPage.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
import { useApi } from "@providers";
1+
import { DashboardPopover, Map, MapSidebar } from "@/widgets";
22
import { Header } from "@components";
3+
import { useApi } from "@providers";
34
import { SidebarProvider } from "@ui/sidebar";
4-
import { DashboardPopover, MapSidebar, Map } from "@/widgets";
55
import { useEffect, useState } from "react";
66

77
import {
88
ResizableHandle,
99
ResizablePanel,
1010
ResizablePanelGroup,
11-
} from "@/components/ui/resizable"
11+
} from "@/components/ui/resizable";
12+
import { useNavigate } from "react-router-dom";
1213

1314
export interface MainPageProps {
1415
userData?: unknown;
1516
}
1617

1718
export function MainPage() {
19+
const navigate = useNavigate();
1820
const client = useApi();
1921
const [data, setData] = useState<unknown | null>(null);
2022

@@ -23,10 +25,11 @@ export function MainPage() {
2325
.then((json) => setData(json.data))
2426
.catch((err) => console.error("fetchData error", err));
2527
}, []);
28+
2629
return (
2730
<div className="flex flex-col h-screen">
2831
<Header
29-
onLogin={() => console.log("Login clicked")}
32+
onLogin={() => navigate('/login')}
3033
onLogout={() => console.log("Logout clicked")}
3134
isLogin={false} />
3235

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function AdminPage() {
2+
return (
3+
<div className="flex flex-col h-screen bg-background items-center justify-center">
4+
<h1>Admin Page</h1>
5+
</div>
6+
);
7+
}

webapp/src/pages/admin/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { AdminPage as default } from "./AdminPage";

webapp/src/pages/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
export { LoginPage } from './LoginPage';
2-
export { MainPage } from './MainPage';
1+
export { MainPage } from "./MainPage";
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export function LoginPage() {
22
return (
3-
<div>
3+
<div className="flex flex-col h-screen bg-background items-center justify-center">
44
<h1>Login Page</h1>
55
</div>
66
);

webapp/src/pages/login/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { LoginPage as default } from "./LoginPage";

0 commit comments

Comments
 (0)