Add Group type with id, name, description, members array and optional user_ids field. Add name field to policy targets for display. Add groups API client methods for list, create, update and delete operations. Add GroupsPage component with create form, edit modal, member selection and table view. Add groups route and navigation item to Layout. Add reusable Modal component with title, subtitle and close handler. Update
55 lines
2.2 KiB
TypeScript
55 lines
2.2 KiB
TypeScript
import { useEffect, useMemo, useState } from "react";
|
|
import { Navigate, Route, Routes } from "react-router-dom";
|
|
|
|
import { AUTH_EXPIRED_EVENT } from "../api/client";
|
|
import { Layout } from "../components/Layout";
|
|
import { AuditPage } from "../features/audit/AuditPage";
|
|
import { LoginPage } from "../features/auth/LoginPage";
|
|
import { DashboardPage } from "../features/dashboard/DashboardPage";
|
|
import { DevicesPage } from "../features/devices/DevicesPage";
|
|
import { GatewaysPage } from "../features/gateways/GatewaysPage";
|
|
import { GroupsPage } from "../features/groups/GroupsPage";
|
|
import { PoliciesPage } from "../features/policies/PoliciesPage";
|
|
import { SettingsPage } from "../features/settings/SettingsPage";
|
|
import { UsersPage } from "../features/users/UsersPage";
|
|
|
|
export function App() {
|
|
const [token, setToken] = useState(() => localStorage.getItem("nexavpn_admin_token") ?? "");
|
|
const authenticated = useMemo(() => token.length > 0, [token]);
|
|
|
|
function handleAuthenticated(accessToken: string) {
|
|
localStorage.setItem("nexavpn_admin_token", accessToken);
|
|
setToken(accessToken);
|
|
}
|
|
|
|
function handleLogout() {
|
|
localStorage.removeItem("nexavpn_admin_token");
|
|
setToken("");
|
|
}
|
|
|
|
useEffect(() => {
|
|
const onExpired = () => handleLogout();
|
|
window.addEventListener(AUTH_EXPIRED_EVENT, onExpired);
|
|
return () => window.removeEventListener(AUTH_EXPIRED_EVENT, onExpired);
|
|
}, []);
|
|
|
|
return (
|
|
<Routes>
|
|
<Route
|
|
path="/login"
|
|
element={authenticated ? <Navigate to="/" replace /> : <LoginPage onAuthenticated={handleAuthenticated} />}
|
|
/>
|
|
<Route element={authenticated ? <Layout onLogout={handleLogout} /> : <Navigate to="/login" replace />}>
|
|
<Route path="/" element={<DashboardPage />} />
|
|
<Route path="/users" element={<UsersPage />} />
|
|
<Route path="/groups" element={<GroupsPage />} />
|
|
<Route path="/devices" element={<DevicesPage />} />
|
|
<Route path="/policies" element={<PoliciesPage />} />
|
|
<Route path="/gateways" element={<GatewaysPage />} />
|
|
<Route path="/audit" element={<AuditPage />} />
|
|
<Route path="/settings" element={<SettingsPage />} />
|
|
</Route>
|
|
</Routes>
|
|
);
|
|
}
|