source-gamepanel/apps/web/src/App.tsx

138 lines
5.3 KiB
TypeScript

import { useEffect } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter, Routes, Route, Navigate, Outlet } from 'react-router';
import { Toaster } from 'sonner';
import { TooltipProvider } from '@/components/ui/tooltip';
import { useAuthStore } from '@/stores/auth';
import { ErrorBoundary } from '@/components/error-boundary';
// Layouts
import { AppLayout } from '@/components/layout/app-layout';
import { ServerLayout } from '@/components/layout/server-layout';
// Auth pages
import { LoginPage } from '@/pages/auth/login';
import { RegisterPage } from '@/pages/auth/register';
// App pages
import { OrganizationsPage } from '@/pages/organizations/index';
import { DashboardPage } from '@/pages/dashboard/index';
import { ServersPage } from '@/pages/servers/index';
import { CreateServerPage } from '@/pages/servers/create';
import { NodesPage } from '@/pages/nodes/index';
import { NodeDetailPage } from '@/pages/nodes/detail';
import { MembersPage } from '@/pages/settings/members';
// Server pages
import { ConsolePage } from '@/pages/server/console';
import { FilesPage } from '@/pages/server/files';
import { BackupsPage } from '@/pages/server/backups';
import { SchedulesPage } from '@/pages/server/schedules';
import { ConfigPage } from '@/pages/server/config';
import { PluginsPage } from '@/pages/server/plugins';
import { PlayersPage } from '@/pages/server/players';
import { DatabasesPage } from '@/pages/server/databases';
import { ServerSettingsPage } from '@/pages/server/settings';
// Admin pages
import { AdminUsersPage } from '@/pages/admin/users';
import { AdminGamesPage } from '@/pages/admin/games';
import { AdminPluginsPage } from '@/pages/admin/plugins';
import { AdminNodesPage } from '@/pages/admin/nodes';
import { AdminAuditLogsPage } from '@/pages/admin/audit-logs';
import { AccountSecurityPage } from '@/pages/account/security';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 1000,
retry: 1,
},
},
});
function AuthGuard() {
const { isAuthenticated, isLoading, fetchUser } = useAuthStore();
useEffect(() => {
fetchUser();
}, [fetchUser]);
if (isLoading) {
return (
<div className="flex min-h-screen items-center justify-center">
<div className="h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" />
</div>
);
}
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
return <Outlet />;
}
export function App() {
return (
<ErrorBoundary>
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<BrowserRouter>
<Routes>
{/* Public routes */}
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
{/* Protected routes */}
<Route element={<AuthGuard />}>
<Route element={<AppLayout />}>
{/* Organizations */}
<Route path="/" element={<OrganizationsPage />} />
{/* Org-scoped routes */}
<Route path="/org/:orgId/dashboard" element={<DashboardPage />} />
<Route path="/org/:orgId/servers" element={<ServersPage />} />
<Route path="/org/:orgId/servers/new" element={<CreateServerPage />} />
<Route path="/org/:orgId/nodes" element={<NodesPage />} />
<Route path="/org/:orgId/nodes/:nodeId" element={<NodeDetailPage />} />
<Route path="/org/:orgId/settings" element={<Navigate to="members" replace />} />
<Route path="/org/:orgId/settings/members" element={<MembersPage />} />
{/* Account */}
<Route path="/account/security" element={<AccountSecurityPage />} />
{/* Server detail */}
<Route path="/org/:orgId/servers/:serverId" element={<ServerLayout />}>
<Route index element={<Navigate to="console" replace />} />
<Route path="console" element={<ConsolePage />} />
<Route path="files" element={<FilesPage />} />
<Route path="config" element={<ConfigPage />} />
<Route path="databases" element={<DatabasesPage />} />
<Route path="plugins" element={<PluginsPage />} />
<Route path="backups" element={<BackupsPage />} />
<Route path="schedules" element={<SchedulesPage />} />
<Route path="players" element={<PlayersPage />} />
<Route path="settings" element={<ServerSettingsPage />} />
</Route>
{/* Admin */}
<Route path="/admin/users" element={<AdminUsersPage />} />
<Route path="/admin/games" element={<AdminGamesPage />} />
<Route path="/admin/plugins" element={<AdminPluginsPage />} />
<Route path="/admin/nodes" element={<AdminNodesPage />} />
<Route path="/admin/audit-logs" element={<AdminAuditLogsPage />} />
</Route>
</Route>
{/* Fallback */}
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</BrowserRouter>
<Toaster position="bottom-right" richColors />
</TooltipProvider>
</QueryClientProvider>
</ErrorBoundary>
);
}