- 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
204 lines
7.9 KiB
TypeScript
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 />,
|
|
},
|
|
]);
|