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, condition?: () => boolean, middlewares?: Middleware[], } & RouteProps; export type Middleware = (next: () => any, ...args: TArgs) => TReturn; export function processMiddlewares(middleware: Middleware[], ...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: () => , middlewares: [ isReadyMiddleware ] }, // edition { name: "edition_register", path: "/edition/register", exact: true, content: () => , middlewares: [ isLoggedInMiddleware ] }, { name: "edition_register_exact", path: "/edition/register/:edition", exact: true, content: () => , middlewares: [ isLoggedInMiddleware ] }, { name: "edition_pick", path: "/edition/pick", exact: true, content: () => , middlewares: [ isLoggedInMiddleware ] }, // internship { name: "internship_proposal", path: "/internship/proposal", exact: true, content: () => , middlewares: [ isReadyMiddleware ] }, { name: "internship_proposal_preview", path: "/internship/preview/proposal", exact: true, content: () => , middlewares: [ isReadyMiddleware ] }, { name: "internship_plan", path: "/internship/plan", exact: true, content: () => , middlewares: [ isReadyMiddleware ] }, { name: "internship_report", path: "/internship/report", exact: true, content: () => , middlewares: [ isReadyMiddleware ] }, // user { name: "user_login", path: "/user/login", content: () => }, { name: "user_fill", path: "/user/data", content: () => , middlewares: [ isLoggedInMiddleware ] }, { name: "user_profile", path: "/user/profile", content: () => , middlewares: [ isLoggedInMiddleware ] }, ...managementRoutes, // fallback route for 404 pages { name: "fallback", path: "*", content: () => }, ].map(route => ({ tags: [], ...route })) const routeNameMap = new Map(routes.filter(({ name }) => !!name).map(({ name, path }) => [name, path instanceof Array ? path[0] : path])) as Map 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 { routes.map(({ name, content, middlewares = [], ...route }) => { const Next = () => processMiddlewares([ ...middlewares, (_, ...props) => content(...props) ], props) return } } /> ) } }