import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import { AlertContext, type AlertContextProps, type AlertParams, LanguageContext, type LanguageContextProps } from '@ifrc-go/ui/contexts'; import { useCallback, useMemo, useState, lazy, Suspense, useEffect, Component } from 'react'; import type { ReactNode } from 'react'; import { unique } from '@togglecorp/fujs'; import RootLayout from './layouts/RootLayout'; import UploadPage from './pages/UploadPage'; import HelpPage from './pages/HelpPage'; // Lazy load heavy pages with prefetching const AnalyticsPage = lazy(() => import('./pages/AnalyticsPage')); const ExplorePage = lazy(() => import('./pages/ExplorePage')); const AdminPage = lazy(() => import('./pages/AdminPage/AdminPage')); const MapDetailPage = lazy(() => import('./pages/MapDetailsPage')); import { FilterProvider } from './contexts/FilterContext'; import { AdminProvider } from './contexts/AdminContext'; // Simple Error Boundary Component class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean }> { constructor(props: { children: ReactNode }) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError() { return { hasError: true }; } componentDidCatch(error: Error, errorInfo: any) { console.error('Error caught by boundary:', error, errorInfo); } render() { if (this.state.hasError) { return (

Something went wrong

Please refresh the page to try again.

); } return this.props.children; } } // Prefetch function for better performance const prefetchPage = (importFn: () => Promise) => { // Start prefetching immediately const prefetchPromise = importFn(); // Store the promise so we can reuse it prefetchPromise.catch(() => { // Silently handle prefetch errors }); return prefetchPromise; }; // Prefetch all pages on idle const prefetchAllPages = () => { if ('requestIdleCallback' in window) { requestIdleCallback(() => { prefetchPage(() => import('./pages/AnalyticsPage')); prefetchPage(() => import('./pages/ExplorePage')); prefetchPage(() => import('./pages/AdminPage/AdminPage')); prefetchPage(() => import('./pages/MapDetailsPage')); }); } else { // Fallback for browsers without requestIdleCallback setTimeout(() => { prefetchPage(() => import('./pages/AnalyticsPage')); prefetchPage(() => import('./pages/ExplorePage')); prefetchPage(() => import('./pages/AdminPage/AdminPage')); prefetchPage(() => import('./pages/MapDetailsPage')); }, 1000); } }; const router = createBrowserRouter([ { element: , children: [ { path: '/', element: }, { path: '/upload', element: }, { path: '/analytics', element: ( Loading Analytics...}> ) }, { path: '/explore', element: ( Loading Explore...}> ) }, { path: '/help', element: }, { path: '/admin', element: ( Loading Admin...}> ) }, { path: '/map/:mapId', element: ( Loading Map Details...}> ) }, ], }, ], { basename: import.meta.env.BASE_URL, // This will be '/' from Vite }); function Application() { const [alerts, setAlerts] = useState([]); // Prefetch pages on mount useEffect(() => { prefetchAllPages(); }, []); const addAlert = useCallback((alert: AlertParams) => { setAlerts((prevAlerts) => unique( [...prevAlerts, alert], (a) => a.name, ) ?? prevAlerts); }, [setAlerts]); const removeAlert = useCallback((name: AlertParams['name']) => { setAlerts((prevAlerts) => { const i = prevAlerts.findIndex((a) => a.name === name); if (i === -1) { return prevAlerts; } const newAlerts = [...prevAlerts]; newAlerts.splice(i, 1); return newAlerts; }); }, [setAlerts]); const updateAlert = useCallback((name: AlertParams['name'], paramsWithoutName: Omit) => { setAlerts((prevAlerts) => { const i = prevAlerts.findIndex((a) => a.name === name); if (i === -1) { return prevAlerts; } const newAlerts = [...prevAlerts]; newAlerts[i] = { ...newAlerts[i], ...paramsWithoutName, }; return newAlerts; }); }, [setAlerts]); const alertContextValue = useMemo( () => ({ alerts, addAlert, removeAlert, updateAlert, }), [alerts, addAlert, removeAlert, updateAlert], ); const languageContextValue = useMemo( () => ({ languageNamespaceStatus: {}, setLanguageNamespaceStatus: () => {}, currentLanguage: 'en', setCurrentLanguage: () => {}, strings: {}, setStrings: () => {}, registerNamespace: () => {}, }), [], ); return ( ); } export default function App() { return ; }