import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react"; import { Routes, Route, Navigate, Outlet, useLocation, useNavigate, useSearchParams, } 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, } 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 BreathPage from "../BreathPage"; 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 { APNG } from "apng-js"; import { useApi, useApiCall } from "@/api"; import { Asset } from "@/api/resources/Assets"; 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"; const isProduction = import.meta.env.MODE === "production"; if (isProduction) { ReactGA.initialize("G-00S3ECJGSJ"); } function App(): JSX.Element { const location = useLocation(); const [leoApng, setLeoApng] = useState(Error); setLeoApng useScrollToTop({ scrollBehavior: "auto" }); // const [ // padLockApng, // setPadLockApng, // ] = useState(Error); const api = useApi(); const dispatch = useDispatch(); const { token, user, signUp, logout } = useAuth(); const [searchParams] = useSearchParams(); const jwtToken = searchParams.get("token"); const isForce = searchParams.get("force"); const subscriptionStatus = useSelector(selectors.selectStatus); // parse utm query useEffect(() => { const availableUrls = [ routes.client.genderV1(), routes.client.palmistryV1Welcome(), routes.client.palmistryWelcome(), ]; const isPageAvailable = availableUrls.reduce( (acc, url) => !!location.pathname.includes(url) || acc, false ); if (isPageAvailable) { const utm = parseQueryParams(); 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", }); }, []); const assetsData = useCallback(async () => { const { assets } = await api.getAssets({ category: String("au"), }); return assets; }, [api]); const { data } = useApiCall(assetsData); data // jwt auth useLayoutEffect(() => { (async () => { if (!jwtToken) return; logout(); try { const { token } = await api.getRealToken({ token: jwtToken }); const { user } = await api.getUser({ token }); const { user: userMe } = await api.getMe({ token }); signUp(token, user, userMe); } catch (error) { console.log("Error of get real token or get user: "); console.error(error); } })(); }, [api, jwtToken, logout, signUp]); useEffect(() => { (async () => { if (!token.length || !user) return; const { user: { has_subscription }, } = await api.getSubscriptionStatus({ token, }); const { subscription: subscriptionStatusNew } = await api.getSubscriptionStatusNew({ token }); if ((has_subscription || subscriptionStatusNew) && user) { return dispatch(actions.status.update("subscribed")); } if (!has_subscription && !subscriptionStatusNew && user) { return dispatch(actions.status.update("unsubscribed")); } if (!user) { return dispatch(actions.status.update("lead")); } })(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [dispatch, api, token]); // useEffect(() => { // async function getApng() { // if (!data) return; // const response = await fetch( // data.find((item) => item.key === "au.apng.leo")?.url || "" // ); // const arrayBuffer = await response.arrayBuffer(); // setLeoApng(parseAPNG(arrayBuffer)); // } // getApng(); // }, [data]); // useEffect(() => { // (async () => { // const response = await fetch("/padlock_icon_animation_closing.png"); // const arrayBuffer = await response.arrayBuffer(); // setPadLockApng(parseAPNG(arrayBuffer)); // })(); // }, []); 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 Palmistry */} }> }> } /> } /> } /> {/* Additional Purchases Palmistry End */} } /> } > } /> } /> } /> }> } /> } /> } /> } /> } /> } /> } /> } /> {/* } /> */} } /> {/* } /> */} } /> {/* }> } > } /> */} }> }> } /> }> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* ROUTES OFF */} } /> } /> } /> } > } /> {/* Email - Pay - Email */} } > } > } /> } > } /> } > } /> } > } /> } > } /> } /> {/* Email - Pay - Email */} {/* Advisor short path */} } > } > } /> } > } /> } > } /> } > } /> } > } /> } > } /> } /> } /> } > } /> {/* Advisor short path */} {/* Test Routes Start */} } /> }> } /> } /> } > }> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } > } /> {/* Test Routes End */} {/* Email Letters */} } /> } /> {/* Email Letters End */} {/* Additional Purchases */} }> }> } /> } /> } /> {/* Additional Purchases End */} } /> } /> } /> ); } 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 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 && ( { }}> )}
{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); return ; } export default App;