From 52a89bfa569267532af4ab6a88a19d6fd7798ea0 Mon Sep 17 00:00:00 2001 From: Julian Cuni Date: Sun, 5 Jul 2026 14:31:32 +0200 Subject: [PATCH] feat(web): move tariff lab under /setup/tariff as a sub-tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lab lived at /subscriptions/tariff-lab — the wrong neighborhood for a tool that tests the rate card. /setup/tariff is now a small layout with two sub-tabs (composer at the index, lab at /setup/tariff/lab) behind the existing tariff:read gate. Old URLs (/subscriptions/tariff-lab and the original /setup/tariff-lab) redirect, and the tariff-read-only redirect branch on /subscriptions is gone with the tab. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V --- apps/web/src/router.tsx | 50 +++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/apps/web/src/router.tsx b/apps/web/src/router.tsx index 384d1b0..24728ef 100644 --- a/apps/web/src/router.tsx +++ b/apps/web/src/router.tsx @@ -117,9 +117,10 @@ function SetupLayout() { } /** Subscriptions layout — a standalone top-level section (its own header nav entry), - * with tabs for the subscriber catalog, the plan catalog, and the tariff lab. Each - * tab is a gated child route; an operator with only subscription:read sees just the - * first tab. */ + * with tabs for the subscriber catalog and the plan catalog. Each tab is a gated + * child route; an operator with only subscription:read sees just the first tab. + * (The tariff lab moved to /setup/tariff/lab, 2026-07-05 — it tests the tariff, so + * it lives with the tariff.) */ function SubscriptionsLayout() { const { user } = rootRoute.useRouteContext(); const { t } = useTranslation(); @@ -129,7 +130,21 @@ function SubscriptionsLayout() { + + + ); +} + +/** Tariff layout — the rate-card hub under Setup: the composer (index) and the + * pricing LAB as sub-tabs. One tariff:read gate on the parent covers both. */ +function TariffLayout() { + const { t } = useTranslation(); + return ( +
+
@@ -519,7 +534,10 @@ const legacyRedirects = ( ["/shift", "/shifts"], ["/setup/subscriptions", "/subscriptions"], ["/setup/plans", "/subscriptions/plans"], - ["/setup/tariff-lab", "/subscriptions/tariff-lab"], + // The tariff lab bounced twice: /setup/tariff-lab → /subscriptions/tariff-lab + // (2026-06-21) → /setup/tariff/lab (2026-07-05, back with the tariff it tests). + ["/setup/tariff-lab", "/setup/tariff/lab"], + ["/subscriptions/tariff-lab", "/setup/tariff/lab"], ["/setup/shifts", "/shifts"], ["/setup/reports", "/reports"], ] as const @@ -633,8 +651,20 @@ const tariffRoute = createRoute({ getParentRoute: () => setupRoute, path: "tariff", beforeLoad: ({ context }) => requirePerm("tariff:read")(context), + component: TariffLayout, +}); +const tariffComposerRoute = createRoute({ + getParentRoute: () => tariffRoute, + path: "/", component: () => , }); +// The tariff LAB — lives with the tariff it tests (moved from /subscriptions, +// 2026-07-05). The parent's tariff:read gate covers it. +const tariffLabRoute = createRoute({ + getParentRoute: () => tariffRoute, + path: "lab", + component: () => , +}); // --- /subscriptions — a standalone top-level section with its own tabs. The catalog // (index), the plan catalog, and the tariff lab live here, not under /setup. --- @@ -651,7 +681,6 @@ const subscriptionsIndexRoute = createRoute({ beforeLoad: ({ context }) => { if (can(context.user, "subscription:read")) return; if (can(context.user, "subscription:plan")) throw redirect({ to: "/subscriptions/plans" }); - if (can(context.user, "tariff:read")) throw redirect({ to: "/subscriptions/tariff-lab" }); throw redirect({ to: "/booth" }); }, component: function SubscriptionsRoute() { @@ -665,12 +694,6 @@ const subscriptionPlansRoute = createRoute({ beforeLoad: ({ context }) => requirePerm("subscription:plan")(context), component: () => , }); -const tariffLabRoute = createRoute({ - getParentRoute: () => subscriptionsRoute, - path: "tariff-lab", - beforeLoad: ({ context }) => requirePerm("tariff:read")(context), - component: () => , -}); const siteRoute = createRoute({ getParentRoute: () => setupRoute, path: "site", @@ -751,11 +774,10 @@ const routeTree = rootRoute.addChildren([ subscriptionsRoute.addChildren([ subscriptionsIndexRoute, subscriptionPlansRoute, - tariffLabRoute, ]), setupRoute.addChildren([ setupDevicesRoute, - tariffRoute, + tariffRoute.addChildren([tariffComposerRoute, tariffLabRoute]), siteRoute, usersRoute, rolesRoute,