100 lines
4.5 KiB
TypeScript
100 lines
4.5 KiB
TypeScript
import React, { ReactComponentElement } from "react";
|
|
import { MainPage } from "@/pages/main";
|
|
import { RouteProps, Switch, Route as RouteComponent } from "react-router-dom";
|
|
import { InternshipProposalFormPage, InternshipProposalPreviewPage } from "@/pages/internship/proposal";
|
|
import { FallbackPage } from "@/pages/fallback";
|
|
import SubmitPlanPage from "@/pages/internship/plan";
|
|
import { UserLoginPage } from "@/pages/user/login";
|
|
import { RegisterEditionPage } from "@/pages/edition/register";
|
|
import PickEditionPage from "@/pages/edition/pick";
|
|
import { isLoggedInMiddleware, isReadyMiddleware } from "@/middleware";
|
|
import UserFillPage from "@/pages/user/fill";
|
|
import UserProfilePage from "@/pages/user/profile";
|
|
import { managementRoutes } from "@/management/routing";
|
|
import SubmitReportPage from "@/pages/internship/report";
|
|
|
|
export type Route = {
|
|
name?: string;
|
|
tags?: string[];
|
|
content: (props?: any) => ReactComponentElement<any>,
|
|
condition?: () => boolean,
|
|
middlewares?: Middleware<any, any>[],
|
|
} & RouteProps;
|
|
|
|
export type Middleware<TReturn, TArgs extends any[]> = (next: () => any, ...args: TArgs) => TReturn;
|
|
|
|
export function processMiddlewares<TArgs extends any[]>(middleware: Middleware<any, TArgs>[], ...args: TArgs): any {
|
|
if (middleware.length == 0) {
|
|
return null;
|
|
}
|
|
|
|
const current = middleware.slice(0, 1)[0];
|
|
const left = middleware.slice(1);
|
|
|
|
return current(() => processMiddlewares(left, ...args), ...args);
|
|
}
|
|
|
|
export const routes: Route[] = [
|
|
{ name: "home", path: "/", exact: true, content: () => <MainPage/>, middlewares: [ isReadyMiddleware ] },
|
|
|
|
// edition
|
|
{ name: "edition_register", path: "/edition/register", exact: true, content: () => <RegisterEditionPage/>, middlewares: [ isLoggedInMiddleware ] },
|
|
{ name: "edition_register_exact", path: "/edition/register/:edition", exact: true, content: () => <RegisterEditionPage/>, middlewares: [ isLoggedInMiddleware ] },
|
|
{ name: "edition_pick", path: "/edition/pick", exact: true, content: () => <PickEditionPage/>, middlewares: [ isLoggedInMiddleware ] },
|
|
|
|
// internship
|
|
{ name: "internship_proposal", path: "/internship/proposal", exact: true, content: () => <InternshipProposalFormPage/>, middlewares: [ isReadyMiddleware ] },
|
|
{ name: "internship_proposal_preview", path: "/internship/preview/proposal", exact: true, content: () => <InternshipProposalPreviewPage/>, middlewares: [ isReadyMiddleware ] },
|
|
{ name: "internship_plan", path: "/internship/plan", exact: true, content: () => <SubmitPlanPage/>, middlewares: [ isReadyMiddleware ] },
|
|
{ name: "internship_report", path: "/internship/report", exact: true, content: () => <SubmitReportPage/>, middlewares: [ isReadyMiddleware ] },
|
|
|
|
// user
|
|
{ name: "user_login", path: "/user/login", content: () => <UserLoginPage/> },
|
|
{ name: "user_fill", path: "/user/data", content: () => <UserFillPage/>, middlewares: [ isLoggedInMiddleware ] },
|
|
{ name: "user_profile", path: "/user/profile", content: () => <UserProfilePage/>, middlewares: [ isLoggedInMiddleware ] },
|
|
|
|
...managementRoutes,
|
|
|
|
// fallback route for 404 pages
|
|
{ name: "fallback", path: "*", content: () => <FallbackPage/> },
|
|
].map(route => ({ tags: [], ...route }))
|
|
|
|
const routeNameMap = new Map(routes.filter(({ name }) => !!name).map(({ name, path }) => [name, path instanceof Array ? path[0] : path])) as Map<string, string>
|
|
|
|
export type URLParams = { [param: string]: string };
|
|
|
|
export const prepare = (url: string, params: URLParams) => Object
|
|
.entries(params)
|
|
.reduce((url, [name, value]) => url.replace(`:${ name }`, value), url)
|
|
|
|
export function route(name: string, params: URLParams = {}) {
|
|
const url = routeNameMap.get(name) || "";
|
|
|
|
return prepare(url, params)
|
|
}
|
|
|
|
export const query = (url: string, params: URLParams) => {
|
|
const query = Object.entries(params)
|
|
.filter(([_, value]) => !!value)
|
|
.map(([name, value]) => `${ name }=${ encodeURIComponent(value) }`)
|
|
.join("&");
|
|
|
|
return url + (query.length > 0 ? `?${ query }` : '');
|
|
}
|
|
|
|
export type RoutesProps = {
|
|
routes: Route[];
|
|
[prop: string]: any;
|
|
};
|
|
|
|
export function Routes({ routes, ...props }: RoutesProps) {
|
|
return <Switch>
|
|
{ routes.map(({ name, content, middlewares = [], ...route }) =>
|
|
<RouteComponent { ...route } key={ name } render={ () => {
|
|
const Next = () => processMiddlewares([ ...middlewares, (_, ...props) => content(...props) ], props)
|
|
return <Next />
|
|
} } />
|
|
) }
|
|
</Switch>
|
|
}
|