bananas-commerce-admin
Version:
What's this, an admin for apes?
92 lines • 3.77 kB
JavaScript
import React, { useMemo, useState } from "react";
import { matchPath, useNavigate } from "react-router-dom";
import { useSnackbar } from "notistack";
import { getPage, getPath, getTitle, isNavigation, parseOperationId, stripPathPrefix, } from "../router/routes";
import { useApi } from "./ApiContext";
const RouterContext = React.createContext({
routes: [],
getCurrent: () => void 0,
getRoute: (reverse) => void reverse,
setCustomRoutes: (routes) => void routes,
navigate: (route, options) => void [route, options],
});
export const useRouter = () => React.useContext(RouterContext);
export const RouterContextProvider = ({ children, ...props }) => {
const api = useApi();
const [customRoutes, setCustomRoutes] = useState([]);
const apiRoutes = useMemo(() => {
const routes = [];
for (const operation of Object.values(api.operations)) {
const parsedOperationId = parseOperationId(operation.id);
if (!parsedOperationId) {
throw new TypeError(`Could not parse operation id ${operation.id}`);
}
const { app, view, action } = parsedOperationId;
const title = getTitle(view, operation.summary);
const navigation = isNavigation(operation.tags);
const path = stripPathPrefix(getPath(operation.endpoint, operation.method, action), props.stripPathPrefix);
const page = getPage(path, action);
routes.push({
id: operation.id,
app,
view,
action,
title,
navigation,
path,
page,
});
}
return routes;
}, [api]);
const routes = useMemo(() => customRoutes.concat(apiRoutes), [customRoutes, apiRoutes]);
const routerNavigate = useNavigate();
const { enqueueSnackbar } = useSnackbar();
const getCurrent = () => {
let currentPath = stripPathPrefix(location.pathname, props.basename);
if (!currentPath.startsWith("/")) {
currentPath = `/${currentPath}`;
}
for (const route of routes) {
const match = matchPath(route.path, currentPath);
if (match !== null) {
return { route, match };
}
}
return undefined;
};
const getRoute = (reverse) => {
return routes.find(({ id }) => reverse === id);
};
const navigate = (route, options) => {
// Relative history, e.g. go back or forward x steps
if (typeof route === "number") {
routerNavigate(route);
return;
}
// Direct operation id routes, requires reversing the operation id
if (typeof route === "string") {
const routeInfo = getRoute(route);
if (routeInfo == null) {
enqueueSnackbar("Failed to navigate, view console for more info", {
variant: "error",
});
throw new Error(`Could not find route with reverse: ${route}`);
}
route = routeInfo;
}
let pathname = route?.path;
if (pathname != null) {
for (const [key, value] of Object.entries(options?.params ?? {})) {
pathname = pathname.replace(`:${key}`, encodeURIComponent(value));
}
}
routerNavigate({
pathname,
search: new URLSearchParams(options?.query).toString(),
}, { replace: options?.replace });
};
return (React.createElement(RouterContext.Provider, { value: { routes, getCurrent, getRoute, setCustomRoutes, navigate } }, children));
};
export default RouterContext;
//# sourceMappingURL=RouterContext.js.map