ca-grow-ops-manager/frontend/src/router.tsx
fullsizemalt eb5ebc610f
Some checks are pending
Deploy to Production / deploy (push) Waiting to run
Test / backend-test (push) Waiting to run
Test / frontend-test (push) Waiting to run
feat: room cards with color-coded headers + room detail page
- Room cards now have colored header backgrounds per type (VEG=green, FLOWER=purple, DRY=amber, CURE=orange, etc.)
- Cards are clickable, linking to /rooms/:id
- New RoomDetailPage with gradient header, sensor metrics with sparklines, active batches list
- Backend: GET /rooms/:id endpoint returns room with batches
2025-12-12 19:33:07 -08:00

204 lines
7.9 KiB
TypeScript

import { createBrowserRouter } from 'react-router-dom';
import { lazy, Suspense } from 'react';
import Layout from './components/Layout';
import ProtectedRoute from './components/ProtectedRoute';
import LoginPage from './pages/LoginPage';
import { RouterErrorPage, NotFoundPage } from './pages/ErrorPages';
// Core pages - loaded immediately
import DashboardPage from './pages/DashboardPage';
// Lazy load all other pages to reduce initial bundle
const DailyWalkthroughPage = lazy(() => import('./pages/DailyWalkthroughPage'));
const RoomsPage = lazy(() => import('./pages/RoomsPage'));
const RoomDetailPage = lazy(() => import('./pages/RoomDetailPage'));
const BatchesPage = lazy(() => import('./pages/BatchesPage'));
const BatchDetailPage = lazy(() => import('./pages/BatchDetailPage'));
const TimeclockPage = lazy(() => import('./pages/TimeclockPage'));
const SuppliesPage = lazy(() => import('./pages/SuppliesPage'));
const TasksPage = lazy(() => import('./pages/TasksPage'));
const TaskTemplatesPage = lazy(() => import('./pages/TaskTemplatesPage'));
const WalkthroughSettingsPage = lazy(() => import('./pages/WalkthroughSettingsPage'));
const RolesPage = lazy(() => import('./pages/RolesPage'));
const TouchPointPage = lazy(() => import('./pages/TouchPointPage'));
const IPMDashboardPage = lazy(() => import('./pages/IPMDashboardPage'));
const SettingsPage = lazy(() => import('./pages/SettingsPage'));
const ReportsPage = lazy(() => import('./pages/ReportsPage'));
// Heavy components
const LayoutDesignerPage = lazy(() => import('./features/layout-designer/LayoutDesignerPage'));
const VisitorKioskPage = lazy(() => import('./pages/VisitorKioskPage'));
const VisitorManagementPage = lazy(() => import('./pages/VisitorManagementPage'));
const BadgePage = lazy(() => import('./pages/BadgePage'));
// Phase 10: Compliance & Audit
const AuditLogPage = lazy(() => import('./pages/AuditLogPage'));
const DocumentsPage = lazy(() => import('./pages/DocumentsPage'));
// Phase 13: Advanced Features
const EnvironmentDashboard = lazy(() => import('./pages/EnvironmentDashboard'));
const FinancialDashboard = lazy(() => import('./pages/FinancialDashboard'));
const InsightsDashboard = lazy(() => import('./pages/InsightsDashboard'));
// Loading spinner component for Suspense fallbacks
const PageLoader = () => (
<div className="flex items-center justify-center p-8">
<div className="animate-spin w-6 h-6 border-2 border-emerald-500 border-t-transparent rounded-full" />
</div>
);
export const router = createBrowserRouter([
{
path: '/login',
element: <LoginPage />,
},
// Visitor Kiosk - Public, no auth required
{
path: '/kiosk',
element: (
<Suspense fallback={
<div className="h-screen w-screen bg-slate-900 flex items-center justify-center">
<div className="animate-spin w-8 h-8 border-2 border-emerald-500 border-t-transparent rounded-full" />
</div>
}>
<VisitorKioskPage />
</Suspense>
),
errorElement: <RouterErrorPage />,
},
{
path: '/badges/:id',
element: (
<Suspense fallback={
<div className="h-screen w-screen bg-slate-900 flex items-center justify-center">
<div className="animate-spin w-8 h-8 border-2 border-emerald-500 border-t-transparent rounded-full" />
</div>
}>
<BadgePage />
</Suspense>
),
errorElement: <RouterErrorPage />,
},
{
path: '/',
element: (
<ProtectedRoute>
<Layout />
</ProtectedRoute>
),
errorElement: <RouterErrorPage />,
children: [
{
index: true,
element: <DashboardPage />,
},
{
path: 'walkthrough',
element: <Suspense fallback={<PageLoader />}><DailyWalkthroughPage /></Suspense>,
},
{
path: 'touch-points',
element: <Suspense fallback={<PageLoader />}><TouchPointPage /></Suspense>,
},
{
path: 'ipm',
element: <Suspense fallback={<PageLoader />}><IPMDashboardPage /></Suspense>,
},
{
path: 'rooms',
element: <Suspense fallback={<PageLoader />}><RoomsPage /></Suspense>,
},
{
path: 'rooms/:id',
element: <Suspense fallback={<PageLoader />}><RoomDetailPage /></Suspense>,
},
{
path: 'batches',
element: <Suspense fallback={<PageLoader />}><BatchesPage /></Suspense>,
},
{
path: 'batches/:id',
element: <Suspense fallback={<PageLoader />}><BatchDetailPage /></Suspense>,
},
{
path: 'timeclock',
element: <Suspense fallback={<PageLoader />}><TimeclockPage /></Suspense>,
},
{
path: 'supplies',
element: <Suspense fallback={<PageLoader />}><SuppliesPage /></Suspense>,
},
{
path: 'tasks',
element: <Suspense fallback={<PageLoader />}><TasksPage /></Suspense>,
},
{
path: 'tasks/templates',
element: <Suspense fallback={<PageLoader />}><TaskTemplatesPage /></Suspense>,
},
{
path: 'reports',
element: <Suspense fallback={<PageLoader />}><ReportsPage /></Suspense>,
},
{
path: 'roles',
element: <Suspense fallback={<PageLoader />}><RolesPage /></Suspense>,
},
{
path: 'visitors',
element: <Suspense fallback={<PageLoader />}><VisitorManagementPage /></Suspense>,
},
{
path: 'settings',
element: <Suspense fallback={<PageLoader />}><SettingsPage /></Suspense>,
},
{
path: 'settings/walkthrough',
element: <Suspense fallback={<PageLoader />}><WalkthroughSettingsPage /></Suspense>,
},
// Phase 10: Compliance & Audit
{
path: 'compliance/audit',
element: <Suspense fallback={<PageLoader />}><AuditLogPage /></Suspense>,
},
{
path: 'compliance/documents',
element: <Suspense fallback={<PageLoader />}><DocumentsPage /></Suspense>,
},
// Phase 13: Advanced Features
{
path: 'environment',
element: <Suspense fallback={<PageLoader />}><EnvironmentDashboard /></Suspense>,
},
{
path: 'financial',
element: <Suspense fallback={<PageLoader />}><FinancialDashboard /></Suspense>,
},
{
path: 'insights',
element: <Suspense fallback={<PageLoader />}><InsightsDashboard /></Suspense>,
},
// 404 catch-all
{
path: '*',
element: <NotFoundPage />,
},
],
},
// Layout Designer - Full screen, outside main layout
{
path: '/layout-designer',
element: (
<ProtectedRoute>
<Suspense fallback={
<div className="h-screen w-screen bg-slate-950 flex items-center justify-center">
<div className="animate-spin w-8 h-8 border-2 border-emerald-500 border-t-transparent rounded-full" />
</div>
}>
<LayoutDesignerPage />
</Suspense>
</ProtectedRoute>
),
errorElement: <RouterErrorPage />,
},
]);