1313 lines
43 KiB
TypeScript
Executable File
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;
|