import { createRoute, redirect, useRouteContext } from "@tanstack/react-router"; import type { AnyRoute } from "@tanstack/react-router"; import { can } from "../../api.js"; import { moduleOn, type RootRoute, type WebModule } from "../../lib/modules.js"; import type { RouterContext } from "../../router.js"; import { CarWashSetup } from "./CarWashSetup.js"; import { WashDesk } from "./WashDesk.js"; // Car Wash — the pilot venue module, web side (wiki/decisions/venue-modules.md). // Two screens: the wash desk (/wash, carwash:read) and Setup → Car wash // (/setup/carwash, site:read; editing needs site:update). Both gate on the module // being effective at this site AND the permission; the server enforces the same. function gate(perm: string) { return ({ context }: { context: unknown }) => { const ctx = context as RouterContext; // Bounce to the landing resolver, never straight to the booth (a wash-only role // has no booth to land on). if (!moduleOn(ctx.user, "carwash") || !can(ctx.user, perm)) throw redirect({ to: "/" }); }; } export const carwashModule: WebModule = { id: "carwash", nav: [{ to: "/wash", labelKey: "nav.wash", perm: "carwash:read" }], landing: { to: "/wash", labelKey: "nav.wash", perm: "carwash:read" }, routes(root: RootRoute) { const washRoute = createRoute({ getParentRoute: () => root, path: "/wash", beforeLoad: gate("carwash:read"), component: WashDesk, }); return [washRoute]; }, setupNav: [{ to: "/setup/carwash", labelKey: "nav.carwash", perm: "site:read" }], setupRoutes(setup: AnyRoute) { const setupCarwashRoute = createRoute({ getParentRoute: () => setup, path: "/carwash", beforeLoad: gate("site:read"), component: function CarWashSetupRoute() { const { user } = useRouteContext({ strict: false }) as RouterContext; return ; }, }); return [setupCarwashRoute]; }, };