import { Suspense, lazy } from 'react'; import AppToaster from '@/components/third-party/AppToaster'; import { QueryClientProvider } from '@tanstack/react-query'; import { queryClientInstance } from '@/lib/query-client'; import { Navigate, BrowserRouter as Router, Route, Routes } from 'react-router-dom'; import PageNotFound from './lib/PageNotFound'; import { AuthProvider, useAuth } from '@/lib/AuthContext'; import { ZoneProvider } from '@/lib/ZoneContext'; import ScrollToTop from './components/ScrollToTop'; import ProtectedRoute from '@/components/ProtectedRoute'; import AdminLayout from '@/layouts/AdminLayout'; import Login from '@/pages/Login'; /* Every console page is code-split. The Dispatch board alone pulls the map, the solver payload builders and the comparison panels; loading that on the way to the Hubs table would make every first paint pay for it. */ /* Doormile-only pages. A client login is sent home rather than shown a page whose every request the server refuses. */ function StaffOnly({ children }) { const { isClient } = useAuth(); return isClient ? : children; } const Dispatch = lazy(() => import('@/pages/doormile/dispatch/Dispatch.jsx')); const DispatchPreview = lazy(() => import('@/pages/doormile/dispatch/Preview.jsx')); const Home = lazy(() => import('@/pages/doormile/home/Home.jsx')); const Orders = lazy(() => import('@/pages/doormile/orders/Orders')); const Bookings = lazy(() => import('@/pages/doormile/bookings/Bookings')); const OrdersPreview = lazy(() => import('@/pages/doormile/orders/OrdersPreview')); const CreateOrder = lazy(() => import('@/pages/doormile/orders/CreateOrder')); const MultipleOrders = lazy(() => import('@/pages/doormile/orders/MultipleOrders')); const Deliveries = lazy(() => import('@/pages/doormile/deliveries/Deliveries')); const Returns = lazy(() => import('@/pages/doormile/returns/Returns')); const Tenants = lazy(() => import('@/pages/doormile/clients/Tenants')); const CreateClient = lazy(() => import('@/pages/doormile/clients/CreateClient')); const ClientOnboarding = lazy(() => import('@/pages/doormile/clients/ClientOnboarding')); const CreateCustomer = lazy(() => import('@/pages/doormile/clients/CreateCustomer')); const Pricing = lazy(() => import('@/pages/doormile/pricing/Pricing')); const Riders = lazy(() => import('@/pages/doormile/riders/Riders')); const CreateRider = lazy(() => import('@/pages/doormile/riders/CreateRider')); const EditRider = lazy(() => import('@/pages/doormile/riders/EditRider')); const Customers = lazy(() => import('@/pages/doormile/customers/Customers')); const Hubs = lazy(() => import('@/pages/doormile/hubs/Hubs')); const Vehicles = lazy(() => import('@/pages/doormile/vehicles/Vehicles')); const AppUsers = lazy(() => import('@/pages/doormile/appUsers/AppUsers')); const Tripsheets = lazy(() => import('@/pages/doormile/tripsheets/Tripsheets')); const Exceptions = lazy(() => import('@/pages/doormile/exceptions/Exceptions')); const CompetitiveIntel = lazy(() => import('@/pages/doormile/competitiveIntel/CompetitiveIntel')); const OrdersSummary = lazy(() => import('@/pages/doormile/reports/OrdersSummary')); const OrdersDetails = lazy(() => import('@/pages/doormile/reports/OrdersDetails')); const RidersSummary = lazy(() => import('@/pages/doormile/reports/RidersSummary')); const Profitability = lazy(() => import('@/pages/doormile/reports/Profitability')); const ViewProfile = lazy(() => import('@/pages/doormile/ViewProfile')); const Settings = lazy(() => import('@/pages/doormile/settings/Settings')); const Agents = lazy(() => import('@/pages/doormile/agents/Agents')); const PageFallback = () => (
); const AuthenticatedApp = () => { const { isLoadingAuth, isLoadingPublicSettings } = useAuth(); if (isLoadingPublicSettings || isLoadingAuth) { return (
); } return ( }> {/* Sign-in — outside the protected boundary. */} } /> }> {/* Dispatch is the console's home: it is the board operators sit on all day, and the one page that answers "what is happening right now" without a filter being set first. */} } /> } /> } /> } /> }> } /> } /> {/* Control X — the board formerly routed at /doormile/dispatch. The directory, the component and the .dispatch-container CSS namespace keep their old names on purpose: they are internal, and renaming a 5,800-line stylesheet's root class is a large diff with no user-visible benefit and real risk of missing a selector. Only what an operator sees and types changes. */} } /> } /> {/* The old paths keep working. This board is the page operators sit on all day, so it is the one most likely to be bookmarked, pinned in a browser tab group, or pasted into a message. Renaming the route without this would turn every one of those into a 404 — a support problem with no upside, avoided by two lines. `replace` so the dead path does not linger in history behind a Back press. */} } /> } /> {/* Static before dynamic, so `orders/create` cannot be read as an order whose id is "create". */} } /> } /> } /> } /> } /> } /> } /> {/* Reverse logistics: parcels going back to the sender (RTO). */} } /> } /> } /> {/* Owner-only (admin@doormile.com); the page and the server both check. */} } /> } /> } /> } /> } /> } /> {/* Backwards-compatible aliases */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* The AI_engine swarm. Read-only: it reports what the agents are and what they last did, and has no control surface, because every autonomy gate lives in that repository's own env. */} } /> } /> ); }; function App() { return ( {/* Every toast in the app (OpenToast, the design system's `toast`, direct react-hot-toast calls) renders here: top-right, one card design. Without a mounted renderer every toast fires into nothing — including the data layer's failure notices. */} ); } export default App;