import React from 'react'; import { createBrowserRouter, Outlet, Navigate, useLocation, useParams } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import RouteErrorElement from '@/components/RouteErrorElement'; import { useAuth } from './auth/context'; import { useEventContext } from './context/EventContext'; import { ADMIN_BASE_PATH, ADMIN_BILLING_PATH, ADMIN_DEFAULT_AFTER_LOGIN_PATH, ADMIN_EVENTS_PATH, ADMIN_LOGIN_PATH, ADMIN_LOGIN_START_PATH, ADMIN_PUBLIC_LANDING_PATH, ADMIN_WELCOME_BASE_PATH, } from './constants'; import { fetchOnboardingStatus, getTenantPackagesOverview } from './api'; import { resolveOnboardingRedirect } from './mobile/lib/onboardingGuard'; const AuthCallbackPage = React.lazy(() => import('./mobile/AuthCallbackPage')); const LoginStartPage = React.lazy(() => import('./mobile/LoginStartPage')); const LogoutPage = React.lazy(() => import('./mobile/LogoutPage')); const MobileEventsPage = React.lazy(() => import('./mobile/EventsPage')); const MobileEventPhotoboothPage = React.lazy(() => import('./mobile/EventPhotoboothPage')); const MobileBrandingPage = React.lazy(() => import('./mobile/BrandingPage')); const MobileEventFormPage = React.lazy(() => import('./mobile/EventFormPage')); const MobileQrPrintPage = React.lazy(() => import('./mobile/QrPrintPage')); const MobileQrLayoutCustomizePage = React.lazy(() => import('./mobile/QrLayoutCustomizePage')); const MobileEventGuestNotificationsPage = React.lazy(() => import('./mobile/EventGuestNotificationsPage')); const MobileEventControlRoomPage = React.lazy(() => import('./mobile/EventControlRoomPage')); const MobileEventLiveShowSettingsPage = React.lazy(() => import('./mobile/EventLiveShowSettingsPage')); const MobileEventMembersPage = React.lazy(() => import('./mobile/EventMembersPage')); const MobileEventTasksPage = React.lazy(() => import('./mobile/EventTasksPage')); const MobileEventRecapPage = React.lazy(() => import('./mobile/EventRecapPage')); const MobileEventAnalyticsPage = React.lazy(() => import('./mobile/EventAnalyticsPage')); const MobileNotificationsPage = React.lazy(() => import('./mobile/NotificationsPage')); const MobileProfilePage = React.lazy(() => import('./mobile/ProfilePage')); const MobileProfileAccountPage = React.lazy(() => import('./mobile/ProfileAccountPage')); const MobileBillingPage = React.lazy(() => import('./mobile/BillingPage')); const MobilePackageShopPage = React.lazy(() => import('./mobile/PackageShopPage')); const MobileSettingsPage = React.lazy(() => import('./mobile/SettingsPage')); const MobileDataExportsPage = React.lazy(() => import('./mobile/DataExportsPage')); const MobileLoginPage = React.lazy(() => import('./mobile/LoginPage')); const MobilePublicHelpPage = React.lazy(() => import('./mobile/PublicHelpPage')); const MobileForgotPasswordPage = React.lazy(() => import('./mobile/ForgotPasswordPage')); const MobileResetPasswordPage = React.lazy(() => import('./mobile/ResetPasswordPage')); const MobileDashboardPage = React.lazy(() => import('./mobile/DashboardPage')); const MobileTasksTabPage = React.lazy(() => import('./mobile/TasksTabPage')); const MobileUploadsTabPage = React.lazy(() => import('./mobile/UploadsTabPage')); const MobileAnimatedOutlet = React.lazy(() => import('./mobile/components/MobileAnimatedOutlet')); const MobileWelcomeLandingPage = React.lazy(() => import('./mobile/welcome/WelcomeLandingPage')); const MobileWelcomePackagesPage = React.lazy(() => import('./mobile/welcome/WelcomePackagesPage')); const MobileWelcomeSummaryPage = React.lazy(() => import('./mobile/welcome/WelcomeSummaryPage')); const MobileWelcomeEventPage = React.lazy(() => import('./mobile/welcome/WelcomeEventPage')); function RequireAuth() { const { status, user } = useAuth(); const location = useLocation(); const { hasEvents, isLoading: eventsLoading } = useEventContext(); const isWelcomePath = location.pathname.startsWith(ADMIN_WELCOME_BASE_PATH); const isBillingPath = location.pathname.startsWith(ADMIN_BILLING_PATH); const isTenantAdmin = Boolean(user && user.role !== 'member'); const shouldCheckPackages = status === 'authenticated' && isTenantAdmin && !eventsLoading && !hasEvents && !isWelcomePath && !isBillingPath; const { data: packagesData, isLoading: packagesLoading } = useQuery({ queryKey: ['mobile', 'onboarding', 'packages-overview'], queryFn: () => getTenantPackagesOverview({ force: true }), enabled: shouldCheckPackages, staleTime: 60_000, }); const { data: onboardingStatus, isLoading: onboardingLoading } = useQuery({ queryKey: ['mobile', 'onboarding', 'status'], queryFn: fetchOnboardingStatus, enabled: shouldCheckPackages, staleTime: 60_000, }); const hasActivePackage = Boolean(packagesData?.activePackage) || Boolean(packagesData?.packages?.some((pkg) => pkg.active)); const remainingEvents = packagesData?.activePackage?.remaining_events ?? null; const isOnboardingDismissed = Boolean(onboardingStatus?.steps?.dismissed_at); const isOnboardingCompleted = Boolean(onboardingStatus?.steps?.completed_at); const shouldBlockOnboarding = shouldCheckPackages && onboardingLoading; const redirectTarget = resolveOnboardingRedirect({ hasEvents, hasActivePackage, remainingEvents, pathname: location.pathname, isBillingPath, isOnboardingDismissed, isOnboardingCompleted, }); if (status === 'loading') { return (