w-aura/src/components/App/index.tsx
gofnnp cb56c45c2c develop
update version of packages
2025-12-26 22:18:03 +04:00

1313 lines
43 KiB
TypeScript
Executable File

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 (
<Routes>
<Route
element={
<CookieYesController isDelete={subscriptionStatus === "subscribed"} />
}
>
<Route path={`${profilePrefix}/*`} element={<ProfileRoutes />} />
<Route
path={`${retainingFunnelPrefix}/*`}
element={<RetainingFunnelRoutes />}
/>
<Route path={`${anonymousPrefix}/*`} element={<AnonymousRoutes />} />
<Route
path={`${palmistryV1Prefix}/*`}
element={<PalmistryV1Routes />}
/>
<Route
path={`${compatibilityV2Prefix}/*`}
element={<CompatibilityV2Routes />}
/>
<Route
path={`${compatibilityV3Prefix}/*`}
element={<CompatibilityV3Routes />}
/>
<Route
path={`${compatibilityV4Prefix}/*`}
element={<CompatibilityV4Routes />}
/>
<Route
path={routes.client.auth()}
element={<Auth redirectUrl={routes.client.trialPaymentV1()} />}
/>
<Route element={<AuthorizedUserOutlet />}>
<Route
path={`${palmistryV2Prefix}/*`}
element={<PalmistryV2Routes />}
/>
</Route>
<Route
path={`${emailMarketingV1Prefix}/*`}
element={<MarketingLandingV1Routes />}
/>
{/* Additional Purchases Main */}
<Route element={<PrivateOutlet />}>
<Route element={<AdditionalPurchasesPalmistry />}>
<Route path={routes.client.skipTrial()} element={<SkipTrial />} />
<Route
path={routes.client.addConsultant()}
element={
<AddConsultant
funnel={ELocalesPlacement.V1}
paymentPlacement="add_consultant"
/>
}
/>
<Route
path={routes.client.addGuides()}
element={
<AddGuides
funnel={ELocalesPlacement.V1}
paymentPlacement="add_guides"
/>
}
/>
</Route>
</Route>
{/* Additional Purchases Main End */}
<Route
path={routes.client.getInformationPartner()}
element={<GetInformationPartnerPage />}
/>
<Route
path={routes.client.paymentResult()}
element={<PaymentResultPage />}
>
<Route path=":id" element={<PaymentResultPage />} />
</Route>
<Route
path={routes.client.paymentSuccess()}
element={<PaymentSuccessPage />}
/>
<Route
path={routes.client.paymentFail()}
element={<PaymentFailPage />}
/>
<Route element={<AuthorizedUserOutlet />}>
<Route path={routes.client.root()} element={<MainPage />} />
<Route path={routes.client.birthday()} element={<BirthdayPage />} />
<Route
path={routes.client.didYouKnow()}
element={<DidYouKnowPage />}
/>
<Route
path={routes.client.freePeriodInfo()}
element={<FreePeriodInfoPage />}
/>
<Route path={routes.client.feedback()} element={<FeedbackPage />} />
<Route path={routes.client.birthtime()} element={<BirthtimePage />} />
<Route path={routes.client.createProfile()} element={<SkipStep />} />
<Route
path={routes.client.emailEnter()}
element={<EmailEnterPage />}
/>
{/* <Route
path={routes.client.auth()}
element={<AuthPage padLockApng={padLockApng} />}
/> */}
<Route
path={routes.client.authResult()}
element={<AuthResultPage />}
/>
{/* <Route path={routes.client.static()} element={<StaticPage />} /> */}
<Route path={routes.client.priceList()} element={<PriceListPage />} />
</Route>
{/* <Route element={<AuthorizedUserOutlet />}>
<Route
path={routes.client.subscription()}
element={<SubscriptionPage />}
>
<Route path=":subPlan" element={<SubscriptionPage />} />
</Route>
</Route> */}
<Route element={<PrivateOutlet />}>
<Route element={<AuthorizedUserOutlet />}>
<Route
path={routes.client.paymentMethod()}
element={<PaymentPage />}
/>
</Route>
<Route element={<PrivateSubscriptionOutlet />}>
<Route element={<Layout />}>
<Route path={routes.client.home()} element={<HomePage />} />
<Route
path={routes.client.compatibility()}
element={<CompatibilityPage />}
/>
<Route
path={routes.client.compatibilityResult()}
element={<CompatResultPage />}
/>
<Route
path={routes.client.breathResult()}
element={<UserCallbacksPage />}
/>
<Route
path={routes.client.wallpaper()}
element={<WallpaperPage />}
/>
<Route path={routes.client.advisors()} element={<Advisors />} />
<Route path={routes.client.advisors()}>
<Route path=":id" element={<AdvisorChatPage />} />
</Route>
<Route
path={routes.client.magicBall()}
element={<MagicBallPage />}
/>
<Route
path={routes.client.horoscopeBestiesResult()}
element={<BestiesHoroscopeResult />}
/>
<Route
path={routes.client.predictionMoonResult()}
element={<PredictionMoonResult />}
/>
<Route
path={routes.client.myHoroscopeResult()}
element={<MyHoroscopeResult />}
/>
<Route
path={routes.client.thermalResult()}
element={<ThermalResult />}
/>
<Route
path={routes.client.moonPhaseTracker()}
element={<MoonPhaseTrackerResult />}
/>
<Route
path={routes.client.energyVampirismResult()}
element={<EnergyVampirismResult />}
/>
<Route
path={routes.client.nameHoroscopeResult()}
element={<NameHoroscopeResult />}
/>
</Route>
</Route>
</Route>
{/* <Route path="*" element={<ABDesignV1Routes />} /> */}
<Route
path="*"
element={<Navigate to={getRouteBy(subscriptionStatus)} />}
/>
{/* ROUTES OFF */}
{/* <Route path="*" element={<ABDesignV1Routes />} /> */}
{/* <Route path={`${chatsPrefix}/*`} element={<ChatsRoutes />} />
<Route
path={`${routes.client.mikeV1()}/*`}
element={<MikeV1Routes />}
/>
<Route
element={<Layout />}
>
<Route path={routes.client.loadingPage()} element={<LoadingPage />} />
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["moons.pdf.aura"]}
redirectUrls={{
user: {
force: routes.client.epeBirthdate(),
},
purchasedProduct: {
no: routes.client.epePayment(),
},
}}
requiredParameters={[isForceShortPath || gender]}
/>
}
>
<Route
path={routes.client.epeGender()}
element={
<GenderPage productKey={EProductKeys["moons.pdf.aura"]} />
}
>
<Route path=":targetId" element={<GenderPage />} />
</Route>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["moons.pdf.aura"]}
redirectUrls={{
data: {
no: routes.client.epeGender(),
},
purchasedProduct: {
no: routes.client.epePayment(),
},
}}
requiredParameters={[isForceShortPath || gender]}
/>
}
>
<Route
path={routes.client.epeBirthdate()}
element={<BirthdayPage />}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["moons.pdf.aura"]}
redirectUrls={{
data: {
no: routes.client.epeGender(),
force: routes.client.epeBirthdate(),
},
purchasedProduct: {
no: routes.client.epePayment(),
},
}}
requiredParameters={[birthdate, isForceShortPath || gender]}
/>
}
>
<Route
path={routes.client.epeEmail()}
element={
<EmailEnterPage redirectUrl={routes.client.epePayment()} />
}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["moons.pdf.aura"]}
redirectUrls={{
data: {
no: routes.client.epeGender(),
force: routes.client.epeBirthdate(),
},
user: {
no: routes.client.epeEmail(),
},
}}
requiredParameters={[birthdate, isForceShortPath || gender]}
/>
}
>
<Route
path={routes.client.epePayment()}
element={
<SinglePaymentPage
productId={EProductKeys["moons.pdf.aura"]}
isForce={isForceShortPath}
/>
}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["moons.pdf.aura"]}
redirectUrls={{
user: {
no: routes.client.epeGender(),
force: routes.client.epeBirthdate(),
},
data: {
no: routes.client.epeGender(),
force: routes.client.epeBirthdate(),
},
purchasedProduct: {
no: routes.client.epePayment(),
},
}}
requiredParameters={[isForceShortPath || gender, birthdate]}
isProductPage={true}
/>
}
>
<Route
path={routes.client.epeSuccessPayment()}
element={<SuccessPaymentPage />}
/>
</Route>
<Route
path={routes.client.epeFailPayment()}
element={<FailPaymentPage />}
/>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
user: {
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.advisorChatPayment(),
},
}}
requiredParameters={[isForceShortPath || gender]}
/>
}
>
<Route
path={routes.client.advisorChatGender()}
element={<GenderPage productKey={EProductKeys["chat.aura"]} />}
>
<Route path=":targetId" element={<GenderPage />} />
</Route>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
},
purchasedProduct: {
no: routes.client.advisorChatPayment(),
},
}}
requiredParameters={[isForceShortPath || gender]}
/>
}
>
<Route
path={routes.client.advisorChatBirthdate()}
element={<BirthdayPage />}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.advisorChatPayment(),
},
}}
requiredParameters={[birthdate, isForceShortPath || gender]}
/>
}
>
<Route
path={routes.client.advisorChatBirthtime()}
element={<BirthtimePage />}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.advisorChatPayment(),
},
}}
requiredParameters={[birthdate, isForceShortPath || gender]}
/>
}
>
<Route
path={routes.client.advisorChatBirthPlace()}
element={<BirthPlacePage />}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.advisorChatPayment(),
},
}}
requiredParameters={[
birthdate,
birthPlace,
isForceShortPath || gender,
]}
/>
}
>
<Route
path={routes.client.advisorChatEmail()}
element={
<EmailEnterPage
redirectUrl={routes.client.advisorChatPayment()}
isRequiredName={true}
/>
}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
user: {
no: routes.client.advisorChatEmail(),
},
}}
requiredParameters={[
birthdate,
birthPlace,
isForceShortPath || gender,
]}
/>
}
>
<Route
path={routes.client.advisorChatPayment()}
element={
<SinglePaymentPage
productId={EProductKeys["chat.aura"]}
isForce={isForceShortPath}
/>
}
/>
</Route>
<Route
path={routes.client.advisorChatSuccessPayment()}
element={<SuccessPaymentPage />}
/>
<Route
path={routes.client.advisorChatFailPayment()}
element={<FailPaymentPage />}
/>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
user: {
no: routes.client.advisorChatEmail(),
},
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.advisorChatPayment(),
},
}}
requiredParameters={[
birthdate,
birthPlace,
isForceShortPath || gender,
]}
isProductPage={true}
/>
}
>
<Route path={`${routes.client.advisorChatPrivate()}`}>
<Route path=":id" element={<AdvisorChatPage />} />
</Route>
</Route>
<Route path={routes.client.notFound()} element={<NotFoundPage />} />
<Route path={routes.client.gender()} element={<GenderPage />}>
<Route path=":targetId" element={<GenderPage />} />
</Route>
<Route path={routes.client.tryApp()} element={<TryAppPage />} />
<Route
path={routes.client.questionnaire()}
element={<QuestionnairePage />}
>
<Route path=":stepId" element={<QuestionnairePage />}>
<Route path=":question" element={<QuestionnairePage />} />
</Route>
</Route>
<Route path={routes.client.goalSetup()} element={<GoalSetupPage />} />
<Route
path={routes.client.hyperPersonalizedAstrology()}
element={<HyperPersonalizedAstrologyPage />}
/>
<Route path={routes.client.noTime()} element={<NoBirthtimePage />} />
<Route
path={routes.client.loadingInRelationship()}
element={<LoadingInRelationshipPage />}
/>
<Route
path={routes.client.worksRouter()}
element={<WorksRouterPage />}
/>
<Route
path={routes.client.worksForUs()}
element={<QuestionnaireIntermediatePage />}
/>
<Route
path={routes.client.worksTraits()}
element={<QuestionnaireIntermediatePage />}
/>
<Route path={routes.client.notAlone()} element={<NotAlonePage />} />
<Route path={routes.client.allRight()} element={<AllRightPage />} />
<Route
path={routes.client.almostThere()}
element={<AlmostTherePage />}
/>
<Route
path={routes.client.relationshipAlmostThere()}
element={<RelationshipAlmostTherePage />}
/>
<Route
path={routes.client.singleZodiacInfo()}
element={<SingleZodiacInfoPage />}
/>
<Route path={routes.client.problems()} element={<ProblemsPage />} />
<Route
path={routes.client.partnerRightPlace()}
element={<PartnerRightPlacePage />}
/>
<Route
path={routes.client.partnerThing()}
element={<PartnerThingPage />}
/>
<Route
path={routes.client.partnerTotallyNormal()}
element={<PartnerTotallyNormalPage />}
/>
<Route path={routes.client.withHeart()} element={<WithHeartPage />} />
<Route path={routes.client.withHead()} element={<WithHeadPage />} />
<Route path={routes.client.both()} element={<BothPage />} />
<Route
path={routes.client.relationshipZodiacInfo()}
element={<RelationshipZodiacInfoPage />}
/>
<Route
path={routes.client.satisfiedResult()}
element={<Satisfied />}
/>
<Route path={routes.client.aboutUs()} element={<AboutUsPage />} />
<Route
path={routes.client.loadingProfile()}
element={<LoadingProfilePage />}
/>
<Route
path={routes.client.emailConfirm()}
element={<EmailConfirmPage />}
/>
<Route
path={routes.client.onboarding()}
element={<OnboardingPage />}
/>
<Route
path={routes.client.additionalDiscount()}
element={<AdditionalDiscount />}
/>
<Route
path={routes.client.trialPaymentWithDiscount()}
element={<TrialPaymentWithDiscount />}
/>
<Route
path={routes.client.trialChoice()}
element={<TrialChoicePage />}
/>
<Route
path={routes.client.trialPayment()}
element={<TrialPaymentPage />}
>
<Route path=":subPlan" element={<TrialPaymentPage />} />
</Route>
<Route
path={routes.client.email("marketing-landing")}
element={<MarketingLanding />}
/>
<Route
path={routes.client.email("marketing-trial-payment")}
element={<MarketingTrialPayment />}
/>
<Route element={<PrivateOutlet />}>
<Route element={<AdditionalPurchases />}>
<Route
path={routes.client.addReport()}
element={<AddReportPage />}
/>
<Route
path={routes.client.unlimitedReadings()}
element={<UnlimitedReadingsPage />}
/>
<Route
path={routes.client.addConsultation()}
element={<AddConsultationPage />}
/>
</Route>
</Route>
<Route path="/palmistry" element={<StepsManager />} />
<Route path="/palmistry/:step" element={<StepsManager />} />
<Route path="*" element={<NotFoundPage />} />
</Route> */}
</Route>
</Routes>
);
}
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<boolean>(false);
// const homeConfig = useSelector(selectors.selectHome);
// const showNavbarFooter = homeConfig.isShowNavbar;
const showNavbarFooter = true;
const mainRef = useRef<HTMLDivElement>(null);
useSchemeColorByElement(mainRef.current, "section.page, .page, section", [
location,
]);
const birthdate = useSelector(selectors.selectBirthdate);
const dataItems = useMemo(() => [birthdate], [birthdate]);
const [isShowFullDataModal, setIsShowFullDataModal] =
useState<boolean>(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 (
<div className="container">
{showHeader ? <Header openMenu={() => setIsMenuOpen(true)} /> : null}
{isRouteFullDataModal && (
<Modal
open={isShowFullDataModal}
isCloseButtonVisible={false}
onClose={() => setIsShowFullDataModal(false)}
>
<FullDataModal onClose={onCloseFullDataModal} />
</Modal>
)}
<main className="content" ref={mainRef}>
<Outlet />
</main>
{showFooter ? <Footer color={showNavbar ? "black" : "white"} /> : null}
{showNavbar ? (
<Navbar isOpen={isMenuOpen} closeMenu={() => setIsMenuOpen(false)} />
) : null}
{showNavbarFooter && hasNavbarFooter(location.pathname) ? (
<NavbarFooter items={navbarItems} />
) : null}
</div>
);
}
// 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 <Navigate to={redirectUrl} replace={true} />;
// }
// if (!user && pageType === EIsAuthPageType.private) {
// return <Navigate to={redirectUrl} replace={true} />;
// }
// return <Outlet />;
// }
// 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 <LoadingPage />;
// }
// 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 <Navigate to={redirectUrls.data.force} replace={true} />;
// }
// if (redirectUrls.data?.no && !isForce) {
// return <Navigate to={redirectUrls.data.no} replace={true} />;
// }
// return <Outlet />;
// }
// if (!isUser) {
// if (isForce && redirectUrls.user?.force) {
// return <Navigate to={redirectUrls.user.force} replace={true} />;
// }
// if (redirectUrls.user?.no && !isForce) {
// return <Navigate to={redirectUrls.user.no} replace={true} />;
// }
// return <Outlet />;
// }
// if (!isPurchasedProduct && !isForcePaymentStatus) {
// if (isForce && redirectUrls.purchasedProduct?.force) {
// return (
// <Navigate to={redirectUrls.purchasedProduct.force} replace={true} />
// );
// }
// if (redirectUrls.purchasedProduct?.no && !isForce) {
// return <Navigate to={redirectUrls.purchasedProduct.no} replace={true} />;
// }
// return <Outlet />;
// }
// if (isProductPage) {
// return <Outlet />;
// }
// return <Navigate to={productUrls[productKey]} replace={true} />;
// }
export function AuthorizedUserOutlet(): JSX.Element {
const status = useSelector(selectors.selectStatus);
const { user } = useAuth();
return user && status === "subscribed" ? (
<Navigate to={routes.client.home()} replace={true} />
) : (
<Outlet />
);
}
export function PrivateOutlet(): JSX.Element {
const { user } = useAuth();
return user ? (
<Outlet />
) : (
<Navigate to={routes.client.root()} replace={true} />
);
}
function PrivateSubscriptionOutlet(): JSX.Element {
const isProduction = import.meta.env.MODE === "production";
const status = useSelector(selectors.selectStatus);
return status === "subscribed" || !isProduction ? (
<Outlet />
) : (
<Navigate to={getRouteBy(status)} replace={true} />
);
}
function getIsShowFullDataModal(dataItems: Array<unknown> = []): 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 ? (
<Navigate to={routes.client.emailEnter()} replace={true} />
) : (
<CreateProfilePage />
);
}
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 <Navigate to={route} replace={true} />;
}
export default App;