import React, { useEffect, useRef, useState } from 'react'; import { HashRouter as Router, Routes, Route, useLocation, useNavigate, } from 'react-router-dom'; import { LuMenu } from 'react-icons/lu'; import { recomaze_ai_personalization_env } from './env'; import { SidebarProvider, useSidebar } from './context/sidebar.context'; import Support from './pages/Support'; import Settings from './pages/Settings'; import SideBar from './components/layout/SideBar'; import Customization from './pages/Customization'; import ImportProducts from './pages/ImportProducts'; import { useAppStateContext } from './context/user.data.context'; import Pricing from './pages/Pricing'; import AgenticFeedPage from './pages/AgenticFeed'; import AiVisibility from './pages/AiVisibility'; import AiVisibilityContents from './pages/AiVisibilityContents'; import AiVisibilityPageTemplates from './pages/AiVisibilityPageTemplates'; import ProductImprovements from './pages/ProductImprovements'; import LlmTxtPage from './pages/LlmTxt'; import AgentAnalytics from './pages/AgentAnalytics'; import KnowledgeBase from './pages/KnowledgeBase'; import ContentGenerator from './pages/ContentGenerator'; import ContentChecker from './pages/ContentChecker'; import OptimizedTextPages from './pages/OptimizedTextPages'; import PromptTemplatesPage from './pages/PromptTemplatesPage'; import Campaigns from './pages/Campaigns'; import CampaignCreate from './pages/CampaignCreate'; import CampaignDetail from './pages/CampaignDetail'; import CatalogQuality from './pages/CatalogQuality'; import Connectors from './pages/Connectors'; import Dashboard from './pages/Dashboard'; import CompanyId from './pages/CompanyId'; import SignupMirror from './pages/SignupMirror'; import LaunchDiscount from './pages/LaunchDiscount'; import OnboardingChain from './pages/OnboardingChain'; import { useAccessControl } from './hooks/useAccessControl'; import { signupMirrorRedirect } from './lib/signup-mirror/access'; import PreviewBanner from './components/PreviewBanner'; import { updatePreviewMode } from './service/user/user.service'; import VerificationModal from './components/VerificationModal'; import ErrorBoundary from './components/ErrorBoundary'; import { CopilotPanel } from './components/copilot/CopilotPanel'; import StoreContextAnnounceModal from './components/visibility/StoreContextAnnounceModal'; import { canSeeBetaVisibilityFeatures } from './components/visibility/beta-access'; import { listBrands } from './service/visibility/visibility.service'; const BARE_ROUTES = ['/signup-mirror', '/launch-discount', '/onboarding-chain']; const MobileTopBar = (): JSX.Element => { const { setMobileOpen } = useSidebar(); const logo = recomaze_ai_personalization_env?.plugin_icon; return (
{logo ? ( Recomaze ) : null} Recomaze
); }; // Everything that needs router hooks (useLocation / useNavigate) lives here, // inside . This is also where the Signup Mirror resume redirect fires // and where the full-screen onboarding routes bypass the app chrome. const AppShell = (): JSX.Element => { const { token, clientId, user, setUser } = useAppStateContext(); const { canAccessAllRoutes, canSeeBulkUpload } = useAccessControl(user); const location = useLocation(); const navigate = useNavigate(); const resumedRef = useRef(false); useEffect(() => { if (resumedRef.current || !user) return; if (location.pathname !== '/' && location.pathname !== '/dashboard') return; const target = signupMirrorRedirect(user); if (target) { resumedRef.current = true; navigate(target, { replace: true }); } }, [user, location.pathname, navigate]); const [announceBrandId, setAnnounceBrandId] = useState(null); const canSeeVisibility = Boolean( clientId && canSeeBetaVisibilityFeatures(clientId) ); useEffect(() => { if (!token || !clientId || !canSeeVisibility) return; let cancelled = false; listBrands(clientId, token) .then(list => { if (!cancelled) setAnnounceBrandId(list.brands[0]?.brand_id ?? null); }) .catch(() => {}); return () => { cancelled = true; }; }, [token, clientId, canSeeVisibility]); const handleActivatePreview = async () => { if (!token) return; try { await updatePreviewMode({ token, preview_mode: true }); if (user) setUser({ ...user, preview_mode: true }); } catch (error) { console.error('Error enabling preview mode:', error); } }; const handleDeactivatePreview = async () => { if (!token) return; try { await updatePreviewMode({ token, preview_mode: false }); if (user) setUser({ ...user, preview_mode: false }); } catch (error) { console.error('Error disabling preview mode:', error); } }; // Full-screen onboarding routes: no sidebar, no banners, no copilot. if (BARE_ROUTES.includes(location.pathname)) { return ( } /> } /> } /> ); } return (
{!canAccessAllRoutes ? ( }> ) : ( } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> : } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> )}
{token && clientId ? ( ) : null} {token && clientId && canSeeVisibility ? ( ) : null}
); }; const App = (): JSX.Element => { const { token, clientId, user, setToken, setClientId, fetchUser, setCanUseWpApi, } = useAppStateContext(); useEffect(() => { if (!token && recomaze_ai_personalization_env?.auth?.token) setToken(recomaze_ai_personalization_env?.auth?.token); if (!clientId && recomaze_ai_personalization_env?.auth?.client_id) setClientId(recomaze_ai_personalization_env?.auth?.client_id); if (!user && token) fetchUser(); if (!recomaze_ai_personalization_env?.can_use_wp_api) setCanUseWpApi(false); }, [token, clientId]); return ( ); }; export default App;