import { BrowserRouter as Router, Routes, Route, useLocation, useNavigate } from 'react-router-dom';
import React, { Suspense, lazy, useEffect } from 'react';
import ErrorBoundary from './utils/errorBoundary';
import Header from './components/Header';
import AnalyticsInitializer from './components/AnalyticsInitializer';
import ReferralInitializer from './components/ReferralInitializer';
import Hero from './components/Hero';
import { useConsent } from './hooks/useConsent';
import { I18nProvider } from './context/I18nContext';
import { resolveLocaleFromPath } from './i18n';
// Lazy-load heavy routes
const Trade = lazy(() => import('./pages/Trade'));
const AboutUs = lazy(() => import('./pages/AboutUs'));
const ContactUs = lazy(() => import('./pages/ContactUs'));
const Security = lazy(() => import('./pages/Security'));
const CookiePolicy = lazy(() => import('./pages/CookiePolicy'));
const ReverseSolicitation = lazy(() => import('./pages/ReverseSolicitation'));
const OtherDocuments = lazy(() => import('./pages/OtherDocuments'));
const BecomePartner = lazy(() => import('./pages/BecomePartner'));
const AccountTypes = lazy(() => import('./pages/AccountTypes'));
const Forbidden = lazy(() => import('./pages/Forbidden'));
// Lazy-load below-the-fold home components and footer
const Features = lazy(() => import('./components/Features'));
const HowToStart = lazy(() => import('./components/HowToStart'));
const About = lazy(() => import('./components/About'));
const Footer = lazy(() => import('./components/Footer'));
const LazyConsentPopup = lazy(() => import('./components/ConsentPopup'));
// Redirect helper to ensure language prefix in URL based on selected language
const LanguageRedirector = () => {
const location = useLocation();
const navigate = useNavigate();
useEffect(() => {
try {
const stored = localStorage.getItem('finprime_language');
const raw = stored ? (JSON.parse(stored) as string) : 'en';
const storedLang: 'en' | 'es' | 'cs' | 'ar' | 'tr' | 'fr' | 'hu' =
raw === 'cz' ? 'cs' : (raw === 'en' || raw === 'es' || raw === 'cs' || raw === 'ar' || raw === 'tr' || raw === 'fr' || raw === 'hu' ? (raw as 'en' | 'es' | 'cs' | 'ar' | 'tr' | 'fr' | 'hu') : 'en');
const path = location.pathname;
const langToPrefix: Record<'en' | 'es' | 'cs' | 'ar' | 'tr' | 'fr' | 'hu', '/en' | '/es' | '/cz' | '/ar' | '/tr' | '/fr' | '/hu'> = {
en: '/en',
es: '/es',
cs: '/cz',
ar: '/ar',
tr: '/tr',
fr: '/fr',
hu: '/hu',
};
const prefixToLang: Record<'/en' | '/es' | '/cz' | '/ar' | '/tr' | '/fr' | '/hu', 'en' | 'es' | 'cs' | 'ar' | 'tr' | 'fr' | 'hu'> = {
'/en': 'en',
'/es': 'es',
'/cz': 'cs',
'/ar': 'ar',
'/tr': 'tr',
'/fr': 'fr',
'/hu': 'hu',
};
const knownPrefixes = ['/en', '/es', '/cz', '/ar', '/tr', '/fr', '/hu'];
const supportedPaths = new Set([
'/',
'/trade',
'/about-us',
'/help-center',
'/security',
'/cookie-policy',
'/reverse-solicitation',
'/privacy-policy',
'/other-documents',
'/become-partner',
'/account-types',
'/forbidden',
]);
const hasAnyPrefix = knownPrefixes.some(p => path === p || path.startsWith(`${p}/`));
const currentPrefix = knownPrefixes.find(p => path === p || path.startsWith(`${p}/`)) as '/en' | '/es' | '/cz' | '/ar' | undefined;
// If URL already specifies a language prefix, honor it and sync localStorage
if (hasAnyPrefix && currentPrefix) {
const urlLang = prefixToLang[currentPrefix];
if (storedLang !== urlLang) {
localStorage.setItem('finprime_language', JSON.stringify(urlLang));
}
return; // Do not rewrite user's chosen prefixed URL
}
// If on unprefixed known path, add the stored language prefix
const isKnownUnprefixedPath = supportedPaths.has(path);
if (!hasAnyPrefix && isKnownUnprefixedPath) {
const targetPrefix = langToPrefix[storedLang] || '/en';
const newPath = path === '/' ? targetPrefix : `${targetPrefix}${path}`;
navigate({ pathname: newPath, search: location.search, hash: location.hash }, { replace: true });
}
} catch {
// ignore parsing issues
}
}, [location.pathname, location.search, location.hash, navigate]);
return null;
};
const ScrollToTop = () => {
const location = useLocation();
useEffect(() => {
if (typeof window !== 'undefined') {
window.scrollTo({ top: 0, left: 0, behavior: 'instant' as ScrollBehavior });
}
}, [location.pathname, location.search, location.hash]);
return null;
};
function App() {
// Manage consent at the app level to gate heavy initializers
const { showConsentPopup, handleConsentAccepted, consentData } = useConsent();
// Render-time consent manager so we can access location (inside Router)
const ConsentManager: React.FC = () => {
const loc = useLocation();
const isReverseSolicitationPage = loc.pathname === '/reverse-solicitation' || loc.pathname.endsWith('/reverse-solicitation');
if (isReverseSolicitationPage) return null;
return showConsentPopup ? (