import { lazy, Suspense, useEffect, useRef } from "react"; import { Toaster } from "@/components/ui/toaster"; import { Toaster as Sonner } from "@/components/ui/sonner"; import { TooltipProvider } from "@/components/ui/tooltip"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom"; import { AuthProvider } from "@/hooks/useAuth"; import { AuthModalProvider } from "@/contexts/AuthModalContext"; import { MFAStepUpProvider } from "@/contexts/MFAStepUpContext"; import { APIConnectivityProvider, useAPIConnectivity } from "@/contexts/APIConnectivityContext"; import { LocationAutoDetectProvider } from "@/components/providers/LocationAutoDetectProvider"; import { AnalyticsWrapper } from "@/components/analytics/AnalyticsWrapper"; import { Footer } from "@/components/layout/Footer"; import { PageLoader } from "@/components/loading/PageSkeletons"; import { RouteErrorBoundary } from "@/components/error/RouteErrorBoundary"; import { AdminErrorBoundary } from "@/components/error/AdminErrorBoundary"; import { EntityErrorBoundary } from "@/components/error/EntityErrorBoundary"; import { breadcrumb } from "@/lib/errorBreadcrumbs"; import { handleError } from "@/lib/errorHandler"; import { RetryStatusIndicator } from "@/components/ui/retry-status-indicator"; import { APIStatusBanner } from "@/components/ui/api-status-banner"; import { ResilienceProvider } from "@/components/layout/ResilienceProvider"; import { useAdminRoutePreload } from "@/hooks/useAdminRoutePreload"; import { useVersionCheck } from "@/hooks/useVersionCheck"; import { cn } from "@/lib/utils"; // Core routes (eager-loaded for best UX) import Index from "./pages/Index"; import Parks from "./pages/Parks"; import Rides from "./pages/Rides"; import Search from "./pages/Search"; import Auth from "./pages/Auth"; // Temporary test component for error logging verification import { TestErrorLogging } from "./test-error-logging"; // Detail routes (lazy-loaded) const ParkDetail = lazy(() => import("./pages/ParkDetail")); const RideDetail = lazy(() => import("./pages/RideDetail")); const ParkRides = lazy(() => import("./pages/ParkRides")); const Manufacturers = lazy(() => import("./pages/Manufacturers")); const ManufacturerDetail = lazy(() => import("./pages/ManufacturerDetail")); const ManufacturerRides = lazy(() => import("./pages/ManufacturerRides")); const ManufacturerModels = lazy(() => import("./pages/ManufacturerModels")); const RideModelDetail = lazy(() => import("./pages/RideModelDetail")); const RideModelRides = lazy(() => import("./pages/RideModelRides")); const Designers = lazy(() => import("./pages/Designers")); const DesignerDetail = lazy(() => import("./pages/DesignerDetail")); const DesignerRides = lazy(() => import("./pages/DesignerRides")); const ParkOwners = lazy(() => import("./pages/ParkOwners")); const PropertyOwnerDetail = lazy(() => import("./pages/PropertyOwnerDetail")); const OwnerParks = lazy(() => import("./pages/OwnerParks")); const Operators = lazy(() => import("./pages/Operators")); const OperatorDetail = lazy(() => import("./pages/OperatorDetail")); const OperatorParks = lazy(() => import("./pages/OperatorParks")); const BlogIndex = lazy(() => import("./pages/BlogIndex")); const BlogPost = lazy(() => import("./pages/BlogPost")); const Terms = lazy(() => import("./pages/Terms")); const Privacy = lazy(() => import("./pages/Privacy")); const SubmissionGuidelines = lazy(() => import("./pages/SubmissionGuidelines")); const Contact = lazy(() => import("./pages/Contact")); // Admin routes (lazy-loaded - heavy bundle) const AdminDashboard = lazy(() => import("./pages/AdminDashboard")); const AdminModeration = lazy(() => import("./pages/AdminModeration")); const AdminReports = lazy(() => import("./pages/AdminReports")); const AdminSystemLog = lazy(() => import("./pages/AdminSystemLog")); const AdminUsers = lazy(() => import("./pages/AdminUsers")); const AdminBlog = lazy(() => import("./pages/AdminBlog")); const AdminSettings = lazy(() => import("./pages/AdminSettings")); const AdminContact = lazy(() => import("./pages/admin/AdminContact")); const AdminEmailSettings = lazy(() => import("./pages/admin/AdminEmailSettings")); const ErrorMonitoring = lazy(() => import("./pages/admin/ErrorMonitoring")); const ErrorLookup = lazy(() => import("./pages/admin/ErrorLookup")); // User routes (lazy-loaded) const Profile = lazy(() => import("./pages/Profile")); const UserSettings = lazy(() => import("./pages/UserSettings")); const AuthCallback = lazy(() => import("./pages/AuthCallback")); // Utility routes (lazy-loaded) const NotFound = lazy(() => import("./pages/NotFound")); const ForceLogout = lazy(() => import("./pages/ForceLogout")); const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false, // Disable automatic refetch on tab focus refetchOnMount: true, // Keep refetch on component mount refetchOnReconnect: true, // Keep refetch on network reconnect retry: 1, // Keep retry attempts staleTime: 30000, // 30 seconds - queries stay fresh for 30s gcTime: 5 * 60 * 1000, // 5 minutes - keep in cache for 5 mins }, mutations: { onError: (error: unknown, variables: unknown, context: unknown) => { // Track mutation errors with breadcrumbs const contextObj = context as { endpoint?: string } | undefined; const errorObj = error as { status?: number } | undefined; breadcrumb.apiCall( contextObj?.endpoint || 'mutation', 'MUTATION', errorObj?.status || 500 ); // Handle error with tracking handleError(error, { action: 'Mutation failed', metadata: { variables, context, }, }); }, }, }, }); // Navigation tracking component - must be inside Router context function NavigationTracker() { const location = useLocation(); const prevLocation = useRef(''); useEffect(() => { const from = prevLocation.current || undefined; breadcrumb.navigation(location.pathname, from); prevLocation.current = location.pathname; // Clear chunk load reload flag on successful navigation sessionStorage.removeItem('chunk-load-reload'); }, [location.pathname]); return null; } function AppContent(): React.JSX.Element { // Check if API status banner is visible to add padding const { isAPIReachable, isBannerDismissed } = useAPIConnectivity(); const showBanner = !isAPIReachable && !isBannerDismissed; // Preload admin routes for moderators/admins useAdminRoutePreload(); // Monitor for new deployments useVersionCheck(); return (
}> {/* Core routes - eager loaded */} } /> } /> } /> } /> } /> {/* Detail routes with entity error boundaries */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* User routes - lazy loaded */} } /> } /> } /> } /> {/* Admin routes with admin error boundaries */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* Utility routes - lazy loaded */} } /> {/* Temporary test route - DELETE AFTER TESTING */} } /> {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */} } />
); } const App = (): React.JSX.Element => { return ( {import.meta.env.DEV && } ); }; export default App;