From d0561be6a1665f0b97440d6c239596b37e31e8e2 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Thu, 28 May 2026 14:03:26 -0400 Subject: [PATCH] feat(l1): register /l1/* routes + L1RouteGuard + page stubs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit L1RouteGuard wraps the new routes and redirects users without canUseL1Surface back to /. Page components are stubs in this task (real UI in T21-T24): L1Dashboard, L1WalkPage, L1DraftsPage, L1TicketsPage. Routes: /l1, /l1/walk/:sessionId, /l1/drafts, /l1/tickets — all gated. Co-Authored-By: Claude Opus 4.7 --- frontend/src/components/layout/L1RouteGuard.tsx | 10 ++++++++++ frontend/src/pages/l1/L1Dashboard.tsx | 13 +++++++++++++ frontend/src/pages/l1/L1DraftsPage.tsx | 13 +++++++++++++ frontend/src/pages/l1/L1TicketsPage.tsx | 13 +++++++++++++ frontend/src/pages/l1/L1WalkPage.tsx | 13 +++++++++++++ frontend/src/router.tsx | 12 ++++++++++++ 6 files changed, 74 insertions(+) create mode 100644 frontend/src/components/layout/L1RouteGuard.tsx create mode 100644 frontend/src/pages/l1/L1Dashboard.tsx create mode 100644 frontend/src/pages/l1/L1DraftsPage.tsx create mode 100644 frontend/src/pages/l1/L1TicketsPage.tsx create mode 100644 frontend/src/pages/l1/L1WalkPage.tsx diff --git a/frontend/src/components/layout/L1RouteGuard.tsx b/frontend/src/components/layout/L1RouteGuard.tsx new file mode 100644 index 00000000..b613dc26 --- /dev/null +++ b/frontend/src/components/layout/L1RouteGuard.tsx @@ -0,0 +1,10 @@ +import { Navigate } from 'react-router-dom' +import { usePermissions } from '@/hooks/usePermissions' + +export function L1RouteGuard({ children }: { children: React.ReactNode }) { + const { canUseL1Surface } = usePermissions() + if (!canUseL1Surface) { + return + } + return <>{children} +} diff --git a/frontend/src/pages/l1/L1Dashboard.tsx b/frontend/src/pages/l1/L1Dashboard.tsx new file mode 100644 index 00000000..e7de2fbe --- /dev/null +++ b/frontend/src/pages/l1/L1Dashboard.tsx @@ -0,0 +1,13 @@ +import { PageMeta } from '@/components/common/PageMeta' + +export default function L1Dashboard() { + return ( +
+ +
+

L1 Workspace

+

Loading…

+
+
+ ) +} diff --git a/frontend/src/pages/l1/L1DraftsPage.tsx b/frontend/src/pages/l1/L1DraftsPage.tsx new file mode 100644 index 00000000..7fd02a22 --- /dev/null +++ b/frontend/src/pages/l1/L1DraftsPage.tsx @@ -0,0 +1,13 @@ +import { PageMeta } from '@/components/common/PageMeta' + +export default function L1DraftsPage() { + return ( +
+ +
+

My Drafts

+

Loading…

+
+
+ ) +} diff --git a/frontend/src/pages/l1/L1TicketsPage.tsx b/frontend/src/pages/l1/L1TicketsPage.tsx new file mode 100644 index 00000000..b4c1b01f --- /dev/null +++ b/frontend/src/pages/l1/L1TicketsPage.tsx @@ -0,0 +1,13 @@ +import { PageMeta } from '@/components/common/PageMeta' + +export default function L1TicketsPage() { + return ( +
+ +
+

L1 Tickets

+

Loading…

+
+
+ ) +} diff --git a/frontend/src/pages/l1/L1WalkPage.tsx b/frontend/src/pages/l1/L1WalkPage.tsx new file mode 100644 index 00000000..24007ec7 --- /dev/null +++ b/frontend/src/pages/l1/L1WalkPage.tsx @@ -0,0 +1,13 @@ +import { PageMeta } from '@/components/common/PageMeta' + +export default function L1WalkPage() { + return ( +
+ +
+

L1 Walk

+

Loading…

+
+
+ ) +} diff --git a/frontend/src/router.tsx b/frontend/src/router.tsx index cadd0032..c57664f4 100644 --- a/frontend/src/router.tsx +++ b/frontend/src/router.tsx @@ -7,6 +7,7 @@ import { RouteError } from '@/components/common/RouteError' import { ErrorBoundary } from '@/components/common/ErrorBoundary' import { PageLoader } from '@/components/common/PageLoader' import { lazyWithRetry } from '@/lib/lazyWithRetry' +import { L1RouteGuard } from '@/components/layout/L1RouteGuard' const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV7(createBrowserRouter) import { @@ -95,6 +96,12 @@ const AdminSurveyInvitesPage = lazyWithRetry(() => import('@/pages/admin/SurveyI const AdminSurveyResponsesPage = lazyWithRetry(() => import('@/pages/admin/SurveyResponsesPage')) const AdminGalleryManagementPage = lazyWithRetry(() => import('@/pages/admin/GalleryManagementPage')) +// L1 workspace pages +const L1Dashboard = lazyWithRetry(() => import('@/pages/l1/L1Dashboard')) +const L1WalkPage = lazyWithRetry(() => import('@/pages/l1/L1WalkPage')) +const L1DraftsPage = lazyWithRetry(() => import('@/pages/l1/L1DraftsPage')) +const L1TicketsPage = lazyWithRetry(() => import('@/pages/l1/L1TicketsPage')) + // Account pages const AccountLayout = lazyWithRetry(() => import('@/components/account/AccountLayout')) const ProfileSettingsPage = lazyWithRetry(() => import('@/pages/account/ProfileSettingsPage')) @@ -284,6 +291,11 @@ export const router = sentryCreateBrowserRouter([ { path: 'welcome/step-1', element: page(WelcomeStep1) }, { path: 'welcome/step-2', element: page(WelcomeStep2) }, { path: 'welcome/step-3', element: page(WelcomeStep3) }, + // L1 workspace routes — gated by canUseL1Surface + { path: 'l1', element: {page(L1Dashboard)} }, + { path: 'l1/walk/:sessionId', element: {page(L1WalkPage)} }, + { path: 'l1/drafts', element: {page(L1DraftsPage)} }, + { path: 'l1/tickets', element: {page(L1TicketsPage)} }, // Admin routes { path: 'admin',