import { useState, useEffect, useRef, useMemo, useLayoutEffect } from "react"; import { Routes, Route, Navigate, Outlet, useLocation, // useNavigate, useSearchParams, useNavigate, } from "react-router-dom"; import { useAuth } from "@/auth"; import { useDispatch, useSelector } from "react-redux"; import { actions, selectors } from "@/store"; import routes, { // hasNavigation, getRouteBy, // hasNoFooter, // hasNoHeader, hasNavbarFooter, // hasFullDataModal, palmistryV1Prefix, // chatsPrefix, palmistryV2Prefix, emailMarketingV1Prefix, compatibilityV2Prefix, anonymousPrefix, compatibilityV3Prefix, compatibilityV4Prefix, hasFullDataModal, hasNoHeader, hasNoFooter, hasNavigation, profilePrefix, retainingFunnelPrefix, } from "@/routes"; import BirthdayPage from "../BirthdayPage"; import BirthtimePage from "../BirthtimePage"; import CreateProfilePage from "../CreateProfilePage"; import EmailEnterPage from "../EmailEnterPage"; import PaymentPage from "../PaymentPage"; import WallpaperPage from "../WallpaperPage"; // import NotFoundPage from "../NotFoundPage"; import Header from "../Header"; import Navbar from "../Navbar"; import Footer from "../Footer"; import "./styles.css"; import DidYouKnowPage from "../DidYouKnowPage"; import FreePeriodInfoPage from "../FreePeriodInfoPage"; import FeedbackPage from "../FeedbackPage"; import CompatibilityPage from "../Compatibility"; import PriceListPage from "../PriceListPage"; import CompatResultPage from "../CompatResultPage"; import HomePage from "../HomePage"; import UserCallbacksPage from "../UserCallbacksPage"; import NavbarFooter, { INavbarHomeItems } from "../NavbarFooter"; import { EPathsFromHome } from "@/store/siteConfig"; import PaymentResultPage from "../PaymentPage/results"; import PaymentSuccessPage from "../PaymentPage/results/SuccessPage"; import PaymentFailPage from "../PaymentPage/results/ErrorPage"; // import AuthPage from "../AuthPage"; import AuthResultPage from "../AuthResultPage"; import MagicBallPage from "../pages/MagicBall"; import BestiesHoroscopeResult from "../pages/BestiesHoroscopeResult"; import PredictionMoonResult from "../pages/PredictionMoonResult"; import MyHoroscopeResult from "../pages/MyHoroscopeResult"; import ThermalResult from "../pages/ThermalResult"; import MoonPhaseTrackerResult from "../pages/MoonPhaseTrackerResult"; import EnergyVampirismResult from "../pages/EnergyVampirismResult"; import NameHoroscopeResult from "../pages/NameHoroscopeResult"; // import GenderPage from "../pages/Gender"; // import QuestionnairePage from "../pages/Questionnaire"; // import GoalSetupPage from "../pages/GoalSetup"; // import HyperPersonalizedAstrologyPage from "../pages/HyperPersonalizedAstrologyPage"; // import NoBirthtimePage from "../pages/NoBirthtime"; // import LoadingInRelationshipPage from "../pages/LoadingInRelationship"; // import QuestionnaireIntermediatePage from "../pages/QuestionnaireIntermediate"; // import RelationshipAlmostTherePage from "../pages/RelationshipAlmostThere"; import Modal from "../Modal"; import FullDataModal from "../FullDataModal"; // import SingleZodiacInfoPage from "../pages/SingleZodiacInfo"; // import ProblemsPage from "../pages/Problems"; // import WorksRouterPage from "../pages/WorksRouter"; // import NotAlonePage from "../pages/NotAlone"; // import AlmostTherePage from "../pages/AlmostThere"; // import AllRightPage from "../pages/AllRight"; // import PartnerRightPlacePage from "../pages/PartnerRightPlace"; // import PartnerThingPage from "../pages/PartnerThing"; // import PartnerTotallyNormalPage from "../pages/PartnerTotallyNormal"; // import WithHeartPage from "../pages/WithHeart"; // import WithHeadPage from "../pages/WithHead"; // import BothPage from "../pages/Both"; // import RelationshipZodiacInfoPage from "../pages/RelationshipZodiacInfo"; // import Satisfied from "../pages/Satisfied"; // import AboutUsPage from "../pages/AboutUs"; // import LoadingProfilePage from "../pages/LoadingProfile"; // import EmailConfirmPage from "../pages/EmailConfirm"; // import OnboardingPage from "../pages/Onboarding"; // import TrialChoicePage from "../pages/TrialChoice"; // import TrialPaymentPage from "../pages/TrialPayment"; import ReactGA from "react-ga4"; // import AdditionalDiscount from "../pages/AdditionalDiscount"; // import TrialPaymentWithDiscount from "../pages/TrialPaymentWithDiscount"; // import MarketingLanding from "../pages/EmailLetters/MarketingLanding"; // import MarketingTrialPayment from "../pages/EmailLetters/MarketingTrialPayment"; import { EUserDeviceType } from "@/store/userConfig"; // import TryAppPage from "../pages/TryApp"; // import AdditionalPurchases from "../pages/AdditionalPurchases"; // import AddReportPage from "../pages/AdditionalPurchases/pages/AddReport"; // import UnlimitedReadingsPage from "../pages/AdditionalPurchases/pages/UnlimitedReadings"; // import AddConsultationPage from "../pages/AdditionalPurchases/pages/AddConsultation"; // import StepsManager from "@/components/palmistry/steps-manager/steps-manager"; import Advisors from "../pages/Advisors"; import AdvisorChatPage from "../pages/AdvisorChat"; // import SuccessPaymentPage from "../pages/SinglePaymentPage/ResultPayment/SuccessPaymentPage"; // import FailPaymentPage from "../pages/SinglePaymentPage/ResultPayment/FailPaymentPage"; import { useSchemeColorByElement } from "@/hooks/useSchemeColorByElement"; import GetInformationPartnerPage from "../pages/GetInformationPartner"; // import BirthPlacePage from "../pages/BirthPlacePage"; // import LoadingPage from "../pages/LoadingPage"; // import { EProductKeys, productUrls } from "@/data/products"; // import SinglePaymentPage from "../pages/SinglePaymentPage"; // import ABDesignV1Routes from "@/routerComponents/ABDesign/v1"; // import MikeV1Routes from "@/routerComponents/Mike/v1"; import metricService from "@/services/metric/metricService"; import PalmistryV1Routes from "@/routerComponents/Palmistry/v1"; import AdditionalPurchasesPalmistry from "../palmistry/AdditionalPurchases"; import AddConsultant from "../palmistry/AdditionalPurchases/pages/AddConsultant"; import AddGuides from "../palmistry/AdditionalPurchases/pages/AddGuides"; import SkipTrial from "../palmistry/AdditionalPurchases/pages/SkipTrial"; import { parseQueryParams } from "@/services/url"; import Auth from "../pages/Auth"; // import ChatsRoutes from "@/routerComponents/Chats"; import CookieYesController from "@/routerComponents/CookieYesController"; import PalmistryV2Routes from "@/routerComponents/Palmistry/v2"; import MarketingLandingV1Routes from "@/routerComponents/MarketingLanding/v1"; import { useScrollToTop } from "@/hooks/useScrollToTop"; import CompatibilityV2Routes from "@/routerComponents/Compatibility/v2"; import AnonymousRoutes from "@/routerComponents/Anonymous"; import CompatibilityV3Routes from "@/routerComponents/Compatibility/v3"; import CompatibilityV4Routes from "@/routerComponents/Compatibility/v4"; import { useUnleashClient } from "@unleash/proxy-client-react"; import { useSession } from "@/hooks/session/useSession"; import { getSourceByPathname } from "@/utils/source.utils"; import { navigateToAuth } from "@/utils/auth-navigation"; import "../palmistry/palmistry-container/palmistry-container.css"; import ProfileRoutes from "@/routerComponents/Profile"; import RetainingFunnelRoutes from "@/routerComponents/RetainingFunnel"; import { ELocalesPlacement } from "@/locales"; const isProduction = import.meta.env.MODE === "production"; const gaMeasurementId = import.meta.env.AURA_GA_MEASUREMENT_ID; // if (isProduction) { ReactGA.initialize(gaMeasurementId); // } else { // ReactGA.initialize("G-ECQDS5X0EH"); // } function App(): JSX.Element { const location = useLocation(); useScrollToTop({ scrollBehavior: "auto" }); const dispatch = useDispatch(); const { user } = useAuth(); const { session } = useSession(); const [searchParams] = useSearchParams(); // const jwtToken = searchParams.get("token"); const isForce = searchParams.get("force"); const subscriptionStatus = useSelector(selectors.selectStatus); const unleashClient = useUnleashClient(); const source = getSourceByPathname(); // update Unleash context useEffect(() => { if (!unleashClient) return; if (user?.id) { unleashClient.updateContext({ userId: user?.id || undefined, properties: { source, }, }); } if (session?.[source]) { unleashClient.updateContext({ sessionId: session?.[source] || undefined, properties: { source, }, }); } }, [user, session, source, unleashClient]); // parse utm query useEffect(() => { const availableUrls = [ routes.client.genderV1(), routes.client.palmistryV1Welcome(), routes.client.compatibilityV2Welcome(), routes.client.palmistryWelcome(), routes.client.anonymousPayment(), ]; const isPageAvailable = availableUrls.reduce( (acc, url) => !!location.pathname.includes(url) || acc, false ); if (isPageAvailable) { const utm = parseQueryParams(); console.log( "App component - parsed UTM on page:", location.pathname, utm ); // Only update UTM if there are new parameters and they're not empty if (Object.keys(utm).length > 0) { console.log("App component - dispatching UTM update:", utm); dispatch(actions.utm.update(utm)); } } }, [dispatch, location.pathname]); useEffect(() => { if (isForce === "true") { dispatch(actions.userConfig.addIsForceShortPath(true)); } else { dispatch(actions.userConfig.addIsForceShortPath(false)); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // const isForceShortPath = useSelector(selectors.selectIsForceShortPath); // const { gender: genderFromStore } = useSelector( // selectors.selectQuestionnaire // ); // const birthdateFromStore = useSelector(selectors.selectBirthdate); // const { birthPlace: birthPlaceFromStore } = useSelector( // selectors.selectQuestionnaire // ); // const gender = user?.profile?.gender || genderFromStore; // const birthdate = user?.profile?.birthday || birthdateFromStore; // const birthPlace = user?.profile?.birthplace || birthPlaceFromStore; useEffect(() => { // metricService.initMetricAB() metricService.hit(); }, [location]); useLayoutEffect(() => { dispatch(actions.paywalls.resetIsMustUpdate()); }, [dispatch]); useEffect(() => { // api.getAppConfig({ bundleId: "auraweb" }), dispatch( actions.siteConfig.update({ openAiToken: "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", }) ); }, [dispatch]); useEffect(() => { if (!isProduction) return; ReactGA.send({ hitType: "pageview", page: document.location.pathname + document.location.search, title: "Custom Title", }); }, []); useEffect(() => { if (!user) return; dispatch(actions.form.addEmail(user.email)); }, [dispatch, user]); // set user device type useEffect(() => { const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent); if (isIOS) { dispatch(actions.userConfig.addDeviceType(EUserDeviceType.ios)); } else { dispatch(actions.userConfig.addDeviceType(EUserDeviceType.android)); } }, [dispatch]); return ( } > } /> } /> } /> } /> } /> } /> } /> } /> }> } /> } /> {/* Additional Purchases Main */} }> }> } /> } /> } /> {/* Additional Purchases Main End */} } /> } > } /> } /> } /> }> } /> } /> } /> } /> } /> } /> } /> } /> {/* } /> */} } /> {/* } /> */} } /> {/* }> } > } /> */} }> }> } /> }> }> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* } /> */} } /> {/* ROUTES OFF */} {/* } /> */} {/* } /> } /> } > } /> } > } > } /> } > } /> } > } /> } > } /> } > } /> } /> } > } > } /> } > } /> } > } /> } > } /> } > } /> } > } /> } /> } /> } > } /> } /> }> } /> } /> } > }> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } > } /> } /> } /> }> }> } /> } /> } /> } /> } /> } /> */} ); } function Layout(): JSX.Element { const location = useLocation(); const navigate = useNavigate(); const dispatch = useDispatch(); const showNavbar = hasNavigation(location.pathname); const showFooter = hasNoFooter(location.pathname); const showHeader = hasNoHeader(location.pathname); const isRouteFullDataModal = hasFullDataModal(location.pathname); const [isMenuOpen, setIsMenuOpen] = useState(false); // const homeConfig = useSelector(selectors.selectHome); // const showNavbarFooter = homeConfig.isShowNavbar; const showNavbarFooter = true; const mainRef = useRef(null); useSchemeColorByElement(mainRef.current, "section.page, .page, section", [ location, ]); const birthdate = useSelector(selectors.selectBirthdate); const dataItems = useMemo(() => [birthdate], [birthdate]); const [isShowFullDataModal, setIsShowFullDataModal] = useState(false); useEffect(() => { setIsShowFullDataModal(getIsShowFullDataModal(dataItems)); }, [dataItems]); const onCloseFullDataModal = (_birthDate: string) => { dispatch(actions.form.addDate(_birthDate)); setIsShowFullDataModal(getIsShowFullDataModal(dataItems)); }; const handleCompatibility = () => { dispatch( actions.siteConfig.update({ home: { pathFromHome: EPathsFromHome.navbar, isShowNavbar: showNavbarFooter, }, }) ); navigate(routes.client.compatibility()); }; const handleBreath = () => { dispatch( actions.siteConfig.update({ home: { pathFromHome: EPathsFromHome.navbar, isShowNavbar: showNavbarFooter, }, }) ); navigate(routes.client.breath()); }; const navbarItems: INavbarHomeItems[] = [ { title: "Breathing", path: routes.client.breath(), paths: [routes.client.breath(), routes.client.breathResult()], image: "Breath.svg", onClick: handleBreath, }, { title: "Aura", path: routes.client.home(), paths: [routes.client.home()], image: "Aura.svg", active: true, onClick: () => null, }, { title: "Compatibility", path: routes.client.compatibility(), paths: [ routes.client.compatibility(), routes.client.compatibilityResult(), ], image: "Compatibility.svg", onClick: handleCompatibility, }, { title: "Advisors", path: routes.client.advisors(), paths: [routes.client.advisors()], image: "moon.svg", onClick: () => null, }, { title: "My Moon", path: routes.client.wallpaper(), paths: [routes.client.wallpaper()], image: "moon.svg", onClick: () => null, }, ]; return (
{showHeader ?
setIsMenuOpen(true)} /> : null} {isRouteFullDataModal && ( setIsShowFullDataModal(false)} > )}
{showFooter ?
: null} {showNavbar ? ( setIsMenuOpen(false)} /> ) : null} {showNavbarFooter && hasNavbarFooter(location.pathname) ? ( ) : null}
); } // enum EIsAuthPageType { // private, // public, // } // interface ICheckIsAuthOutletProps { // redirectUrl: string; // pageType: EIsAuthPageType; // } // function CheckIsAuthOutlet({ // redirectUrl, // pageType, // }: ICheckIsAuthOutletProps): JSX.Element { // const { user } = useAuth(); // if (user && pageType === EIsAuthPageType.public) { // return ; // } // if (!user && pageType === EIsAuthPageType.private) { // return ; // } // return ; // } // interface IShortPathOutletProps { // productKey: EProductKeys; // requiredParameters: unknown[]; // isProductPage?: boolean; // redirectUrls: { // user?: { // yes?: string; // no?: string; // force?: string; // }; // data?: { // yes?: string; // no?: string; // force?: string; // }; // purchasedProduct?: { // yes?: string; // no?: string; // force?: string; // }; // force?: { // yes?: string; // no?: string; // force?: string; // }; // }; // } // function ShortPathOutlet(props: IShortPathOutletProps): JSX.Element { // const dispatch = useDispatch(); // const { productKey, requiredParameters, redirectUrls, isProductPage } = props; // const { user, token } = useAuth(); // const dateOfPaymentChatMike = useSelector( // selectors.selectDateOfPaymentChatMike // ); // const queryParameters = new URLSearchParams(window.location.search); // const paymentMadeChatMike = queryParameters.get("paymentMadeChatMike"); // if (paymentMadeChatMike && !dateOfPaymentChatMike) { // dispatch(actions.userConfig.setDateOfPaymentChatMike(new Date())); // } // const isForcePaymentStatus = useMemo(() => { // if ((Date.now() - new Date(dateOfPaymentChatMike).getTime()) / 1000 < 180) { // return true; // } // if (paymentMadeChatMike && !dateOfPaymentChatMike) { // return true; // } // return false; // }, [dateOfPaymentChatMike, paymentMadeChatMike]); // const api = useApi(); // const isForce = useSelector(selectors.selectIsForceShortPath); // const loadData = useCallback(async () => { // if (!token?.length || !user?.email || !productKey?.length) // return { // status: "error", // error: "Missing params", // }; // try { // const purchased = await api.checkProductPurchased({ // productKey, // token, // }); // return purchased; // } catch (error) { // console.error(error); // return { // status: "error", // error: "Something went wrong", // }; // } // // eslint-disable-next-line react-hooks/exhaustive-deps // }, [token]); // const { data, isPending } = useApiCall(loadData, "pending"); // if (isPending) { // return ; // } // const isPurchasedProduct = !!(data && "active" in data && data.active); // const isUser = !!user && !!token.length; // const isFullData = requiredParameters.every((item) => !!item); // if (!isFullData) { // if (isForce && redirectUrls.data?.force) { // return ; // } // if (redirectUrls.data?.no && !isForce) { // return ; // } // return ; // } // if (!isUser) { // if (isForce && redirectUrls.user?.force) { // return ; // } // if (redirectUrls.user?.no && !isForce) { // return ; // } // return ; // } // if (!isPurchasedProduct && !isForcePaymentStatus) { // if (isForce && redirectUrls.purchasedProduct?.force) { // return ( // // ); // } // if (redirectUrls.purchasedProduct?.no && !isForce) { // return ; // } // return ; // } // if (isProductPage) { // return ; // } // return ; // } export function AuthorizedUserOutlet(): JSX.Element { const status = useSelector(selectors.selectStatus); const { user } = useAuth(); return user && status === "subscribed" ? ( ) : ( ); } export function PrivateOutlet(): JSX.Element { const { user } = useAuth(); return user ? ( ) : ( ); } function PrivateSubscriptionOutlet(): JSX.Element { const isProduction = import.meta.env.MODE === "production"; const status = useSelector(selectors.selectStatus); return status === "subscribed" || !isProduction ? ( ) : ( ); } function getIsShowFullDataModal(dataItems: Array = []): boolean { let hasNoDataItem = false; for (const item of dataItems) { if (!item) { hasNoDataItem = true; break; } } return hasNoDataItem; } function SkipStep(): JSX.Element { const { user } = useAuth(); return user ? ( ) : ( ); } function MainPage(): JSX.Element { const status = useSelector(selectors.selectStatus); const route = getRouteBy(status); const [shouldRedirect, setShouldRedirect] = useState(false); useEffect(() => { // Check if we're navigating to auth and on witlab.app domain if (route === routes.client.auth()) { const isWitlabDomain = window.location.hostname === "witlab.app" || window.location.hostname.endsWith(".witlab.app"); // If we're on witlab.app domain, use server-side navigation if (isWitlabDomain) { navigateToAuth(); setShouldRedirect(true); } } }, [route]); // If we're redirecting via server-side navigation, return empty fragment if (shouldRedirect) { return <>; } // For all other cases, use client-side navigation return ; } export default App;