import React from "react" import { Route, Routes, useLocation, useNavigate, useParams } from "react-router-dom" import { Skeleton, Button, Result } from "antd" import config from "config" import loadable from "@loadable/component" import routesDeclaration from "schemas/routes" const DefaultNotFoundRender = () => { return
Not found
} const DefaultLoadingRender = () => { return } const paths = { ...import.meta.glob("/src/pages/**/[a-z[]*.jsx"), ...import.meta.glob("/src/pages/**/[a-z[]*.tsx"), } const pathsMobile = { ...import.meta.glob("/src/pages/**/[a-z[]*.mobile.jsx"), ...import.meta.glob("/src/pages/**/[a-z[]*.mobile.tsx"), } const routes = Object.keys(paths).map((route) => { const path = route .replace(/\/src\/pages|index|\.jsx$/g, "") .replace(/\/src\/pages|index|\.tsx$/g, "") .replace(/\[\.{3}.+\]/, "*") .replace(/\[(.+)\]/, ":$1") return { path, element: paths[route] } }) const mobileRoutes = Object.keys(pathsMobile).map((route) => { const path = route .replace(/\/src\/pages|index|\.mobile|\.jsx$/g, "") .replace(/\/src\/pages|index|\.mobile|\.tsx$/g, "") .replace(/\[\.{3}.+\]/, "*") .replace(/\[(.+)\]/, ":$1") return { path, element: pathsMobile[path] } }) function generatePageElementWrapper(route, element, bindProps) { return React.createElement((props) => { const params = useParams() const url = new URL(window.location) const query = new Proxy(url, { get: (target, prop) => target.searchParams.get(prop), }) const routeDeclaration = routesDeclaration.find((layout) => { const routePath = layout.path.replace(/\*/g, ".*").replace(/!/g, "^") return new RegExp(routePath).test(route) }) ?? { path: route, useLayout: "default", } route = route.replace(/\?.+$/, "").replace(/\/{2,}/g, "/") route = route.replace(/\/$/, "") if (routeDeclaration) { if (!bindProps.user && (window.location.pathname !== config.app?.authPath)) { if (!routeDeclaration.public) { if (typeof window.app.setLocation === "function") { window.app.setLocation(config.app?.authPath ?? "/login") return
} window.location.href = config.app?.authPath ?? "/login" return
} } if (typeof routeDeclaration.requiredRoles !== "undefined") { const isAdmin = bindProps.user?.roles?.includes("admin") ?? false if (!isAdmin && !routeDeclaration.requiredRoles.some((role) => bindProps.user?.roles?.includes(role))) { return window.app.setLocation("/")}>Back Home} /> } } if (routeDeclaration.useLayout) { app.layout.set(routeDeclaration.useLayout) } // if (routeDeclaration.useHeader === true) { // app.layout.header?.toggle(true) // } else { // app.layout.header?.toggle(false) // } if (typeof routeDeclaration.useTitle !== "undefined") { if (typeof routeDeclaration.useTitle === "function") { routeDeclaration.useTitle = routeDeclaration.useTitle(route, params) } document.title = `${routeDeclaration.useTitle} - ${config.app.siteName}` } else { document.title = config.app.siteName } if (routeDeclaration.centeredContent) { app.layout.toogleCenteredContent(true) } else { app.layout.toogleCenteredContent(false) } } return React.createElement( loadable(element, { fallback: React.createElement(bindProps.staticRenders?.PageLoad || DefaultLoadingRender), }), { ...props, ...bindProps, url: url, params: params, query: query, }) }) } export const PageRender = React.memo((props) => { const navigate = useNavigate() app.location = useLocation() React.useEffect(() => { app.setLocation = async (to, state = {}) => { // clean double slashes to = to.replace(/\/{2,}/g, "/") // if state is a number, it's a delay if (typeof state !== "object") { state = {} } const transitionDuration = app.cores.style.getValue("page-transition-duration") ?? "250ms" state.transitionDelay = Number(transitionDuration.replace("ms", "")) app.eventBus.emit("router.navigate", to, { state, }) app.location.lastPathname = app.location.pathname if (state.transitionDelay >= 100) { await new Promise((resolve) => { setTimeout(() => { resolve() }, state.transitionDelay) }) } return navigate(to, { state }) } app.backLocation = (state = {}) => { let to = app.location.lastPathname if (!to || to === app.location.pathname) { console.warn("No last location found, redirecting to /") to = "/" } return navigate(to, { state }) } }, []) return { routes.map((route, index) => { let Element = route.element if (window.isMobile) { const mobileElement = mobileRoutes.find((r) => r.path === route.path) if (mobileElement) { Element = mobileElement } } return }) } })