121 lines
4.3 KiB
TypeScript
121 lines
4.3 KiB
TypeScript
import { lazy, Suspense, type LazyExoticComponent } from 'react';
|
|
import {
|
|
type RouteObject,
|
|
createBrowserRouter,
|
|
redirect,
|
|
useRouteError,
|
|
} from 'react-router-dom';
|
|
|
|
import Layout from '../components/Layout';
|
|
import { hasActiveSession } from '../features/auth/session';
|
|
|
|
const DashboardPage = lazy(() => import('../pages/dashboard/Dashboard'));
|
|
const ButtonsPage = lazy(() => import('../pages/buttons/Buttons'));
|
|
const ChartsPage = lazy(() => import('../pages/charts/Charts'));
|
|
const MapsPage = lazy(() => import('../pages/google/Google'));
|
|
const IconsPage = lazy(() => import('../pages/icons/Icons'));
|
|
const NotificationsPage = lazy(() => import('../pages/notifications/Notifications'));
|
|
const TablesPage = lazy(() => import('../pages/tables/Tables'));
|
|
const TypographyPage = lazy(() => import('../pages/typography/Typography'));
|
|
const LoginPage = lazy(() => import('../pages/login/Login'));
|
|
const RegisterPage = lazy(() => import('../pages/register/Register'));
|
|
const ProfilePage = lazy(() => import('../pages/profile/Profile'));
|
|
const PrivacyPage = lazy(() => import('../pages/privacy/Privacy'));
|
|
const PostListPage = lazy(() => import('../pages/posts/list/PostList'));
|
|
const PostNewPage = lazy(() => import('../pages/posts/new/PostNew'));
|
|
const NotFoundPage = lazy(() => import('../pages/notFound/NotFound'));
|
|
const TermsPage = lazy(() => import('../pages/terms/Terms'));
|
|
|
|
const routeLoader =
|
|
(predicate: () => boolean, targetPath: string) =>
|
|
async () => {
|
|
if (predicate()) {
|
|
return redirect(targetPath);
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
const rootRedirectLoader = async () => redirect(hasActiveSession() ? '/app/main' : '/login');
|
|
|
|
const PageFallback = () => (
|
|
<div className="d-flex min-vh-100 align-items-center justify-content-center">
|
|
<div className="text-center">
|
|
<div className="spinner-border text-danger" role="status" />
|
|
<p className="mt-3 mb-0 text-muted">Loading dashboard module...</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
const renderLazyPage = (Page: LazyExoticComponent<() => React.JSX.Element>) => (
|
|
<Suspense fallback={<PageFallback />}>
|
|
<Page />
|
|
</Suspense>
|
|
);
|
|
|
|
const RouteErrorBoundary = () => {
|
|
const routeError = useRouteError();
|
|
const message =
|
|
routeError instanceof Error ? routeError.message : 'Unexpected routing error';
|
|
|
|
return (
|
|
<div className="d-flex min-vh-100 align-items-center justify-content-center p-4">
|
|
<div className="text-center">
|
|
<h1 className="display-6 mb-3">Something broke</h1>
|
|
<p className="text-muted mb-4">{message}</p>
|
|
<a className="btn btn-danger" href={`${import.meta.env.BASE_URL}app/main`}>
|
|
Go back to the dashboard
|
|
</a>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const routes: RouteObject[] = [
|
|
{
|
|
path: '/',
|
|
loader: rootRedirectLoader,
|
|
},
|
|
{
|
|
path: '/login',
|
|
loader: routeLoader(hasActiveSession, '/app/main'),
|
|
element: renderLazyPage(LoginPage),
|
|
},
|
|
{
|
|
path: '/register',
|
|
loader: routeLoader(hasActiveSession, '/app/main'),
|
|
element: renderLazyPage(RegisterPage),
|
|
},
|
|
{
|
|
path: '/app',
|
|
loader: routeLoader(() => !hasActiveSession(), '/login'),
|
|
element: <Layout />,
|
|
errorElement: <RouteErrorBoundary />,
|
|
children: [
|
|
{ index: true, loader: async () => redirect('/app/main') },
|
|
{ path: 'main', element: renderLazyPage(DashboardPage) },
|
|
{ path: 'typography', element: renderLazyPage(TypographyPage) },
|
|
{ path: 'tables', element: renderLazyPage(TablesPage) },
|
|
{ path: 'notifications', element: renderLazyPage(NotificationsPage) },
|
|
{ path: 'components/buttons', element: renderLazyPage(ButtonsPage) },
|
|
{ path: 'components/charts', element: renderLazyPage(ChartsPage) },
|
|
{ path: 'components/icons', element: renderLazyPage(IconsPage) },
|
|
{ path: 'components/maps', element: renderLazyPage(MapsPage) },
|
|
{ path: 'posts', element: renderLazyPage(PostListPage) },
|
|
{ path: 'posts/new', element: renderLazyPage(PostNewPage) },
|
|
{ path: 'profile', element: renderLazyPage(ProfilePage) },
|
|
{ path: 'privacy', element: renderLazyPage(PrivacyPage) },
|
|
{ path: 'tos', element: renderLazyPage(TermsPage) },
|
|
{ path: '*', element: renderLazyPage(NotFoundPage) },
|
|
],
|
|
},
|
|
{
|
|
path: '*',
|
|
element: renderLazyPage(NotFoundPage),
|
|
},
|
|
];
|
|
|
|
export const router = createBrowserRouter(routes, {
|
|
basename: import.meta.env.BASE_URL,
|
|
});
|