Merge branch 'preview/email-pay-email' into 'develop'

Revert "fix: remove double image key and update filter of subscription plans"

See merge request witapp/aura-webapp!60
This commit is contained in:
Victor Ershov 2024-03-24 21:01:16 +00:00
commit d22157cde1
17 changed files with 690 additions and 58 deletions

View File

@ -23,7 +23,8 @@ import {
GoogleAuth,
SubscriptionPlans,
AppleAuth,
AIRequestsV2
AIRequestsV2,
SinglePayment
} from './resources'
const api = {
@ -55,6 +56,9 @@ const api = {
getZodiacs: createMethod<Zodiacs.Payload, Zodiacs.Response>(Zodiacs.createRequest),
AIRequestsV2: createMethod<AIRequestsV2.Payload, AIRequestsV2.Response>(AIRequestsV2.createRequest),
getAIRequestsV2: createMethod<AIRequestsV2.PayloadGet, AIRequestsV2.IAiResponseGet>(AIRequestsV2.createRequestGet),
getSinglePaymentProducts: createMethod<SinglePayment.PayloadGet, SinglePayment.ResponseGet[]>(SinglePayment.createRequestGet),
createSinglePayment: createMethod<SinglePayment.PayloadPost, SinglePayment.ResponsePost | SinglePayment.ResponsePostExistPaymentData>(SinglePayment.createRequestPost),
}
export type ApiContextValue = typeof api

View File

@ -0,0 +1,82 @@
import routes from "@/routes";
import { getAuthHeaders } from "../utils";
interface Payload {
token: string;
}
export interface PayloadGet extends Payload {
id: string;
}
export interface PayloadPost extends Payload {
data: {
user: {
id: string;
email: string;
name: string;
sign: string;
age: number;
};
partner: {
sign: string | null;
age: number | null;
};
paymentInfo: {
productId: string;
};
return_url: string;
};
}
export interface ResponseGet {
key: string;
productId: string;
amount: number;
currency: string;
}
export interface ResponsePost {
paymentIntent: {
status: string;
data: {
client_secret: string;
paymentIntentId: string;
return_url?: string;
public_key: string;
product: {
id: string;
name: string;
description: null | string;
price: {
id: string;
unit_amount: number;
currency: string;
};
};
};
};
}
export interface ResponsePostExistPaymentData {
payment: {
status: string;
invoiceId: string;
};
}
export const createRequestPost = ({ data, token }: PayloadPost): Request => {
const url = new URL(routes.server.dApiPaymentCheckout());
const body = JSON.stringify(data);
return new Request(url, {
method: "POST",
headers: getAuthHeaders(token),
body,
});
};
export const createRequestGet = ({ id, token }: PayloadGet): Request => {
id;
const url = new URL(routes.server.dApiTestPaymentProducts());
return new Request(url, { method: "GET", headers: getAuthHeaders(token) });
};

View File

@ -22,3 +22,4 @@ export * as GoogleAuth from "./GoogleAuth";
export * as SubscriptionPlans from "./SubscriptionPlans";
export * as AppleAuth from "./AppleAuth";
export * as AIRequestsV2 from "./AIRequestsV2";
export * as SinglePayment from "./SinglePayment";

View File

@ -104,6 +104,9 @@ 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 PaymentWithEmailPage from "../pages/PaymentWithEmailPage";
import SuccessPaymentPage from "../pages/PaymentWithEmailPage/ResultPayment/SuccessPaymentPage";
import FailPaymentPage from "../pages/PaymentWithEmailPage/ResultPayment/FailPaymentPage";
const isProduction = import.meta.env.MODE === "production";
@ -216,6 +219,13 @@ function App(): JSX.Element {
return (
<Routes>
<Route element={<Layout setIsSpecialOfferOpen={setIsSpecialOfferOpen} />}>
{/* Email - Pay - Email */}
<Route path={routes.client.epeBirthdate()} element={<BirthdayPage />} />
<Route path={routes.client.epePayment()} element={<PaymentWithEmailPage />} />
<Route path={routes.client.epeSuccessPayment()} element={<SuccessPaymentPage />} />
<Route path={routes.client.epeFailPayment()} element={<FailPaymentPage />} />
{/* Email - Pay - Email */}
{/* Test Routes Start */}
<Route path={routes.client.notFound()} element={<NotFoundPage />} />
<Route path={routes.client.gender()} element={<GenderPage />}>
@ -331,8 +341,14 @@ function App(): JSX.Element {
{/* Additional Purchases */}
<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
path={routes.client.unlimitedReadings()}
element={<UnlimitedReadingsPage />}
/>
<Route
path={routes.client.addConsultation()}
element={<AddConsultationPage />}
/>
</Route>
{/* Additional Purchases End */}
@ -472,15 +488,9 @@ function App(): JSX.Element {
</Route>
</Route>
<Route
path="/palmistry"
element={<StepsManager/>}
/>
<Route path="/palmistry" element={<StepsManager />} />
<Route
path="/palmistry/:step"
element={<StepsManager/>}
/>
<Route path="/palmistry/:step" element={<StepsManager />} />
<Route path="*" element={<NotFoundPage />} />
</Route>

View File

@ -1,54 +1,83 @@
import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { actions, selectors } from '@/store'
import { DatePicker } from '../DateTimePicker'
import MainButton from '../MainButton'
import Policy from '../Policy'
import Purposes from '../Purposes'
import Title from '../Title'
import routes from '@/routes'
import './styles.css'
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import { DatePicker } from "../DateTimePicker";
import MainButton from "../MainButton";
import Policy from "../Policy";
import Purposes from "../Purposes";
import Title from "../Title";
import routes from "@/routes";
import "./styles.css";
function BirthdayPage(): JSX.Element {
const { t } = useTranslation()
const dispatch = useDispatch()
const navigate = useNavigate()
const birthdate = useSelector(selectors.selectBirthdate)
const [isDisabled, setIsDisabled] = useState(true)
const handleNext = () => navigate(routes.client.didYouKnow())
const { t } = useTranslation();
const dispatch = useDispatch();
const navigate = useNavigate();
const birthdate = useSelector(selectors.selectBirthdate);
const [isDisabled, setIsDisabled] = useState(true);
const nextRoute = window.location.href.includes("/epe/")
? routes.client.epePayment()
: routes.client.didYouKnow();
const handleNext = () => navigate(nextRoute);
const handleValid = (birthdate: string) => {
dispatch(actions.form.addDate(birthdate))
setIsDisabled(birthdate === '')
}
dispatch(actions.form.addDate(birthdate));
setIsDisabled(birthdate === "");
};
return (
<section className='page'>
<Title variant='h3' className='mt-24'>{t('lets_start')}</Title>
<Title variant='h2'>{t('date_of_birth')}</Title>
<section className="page">
<Title variant="h3" className="mt-24">
{t("lets_start")}
</Title>
<Title variant="h2">{t("date_of_birth")}</Title>
<DatePicker
name='birthdate'
name="birthdate"
value={birthdate}
onValid={handleValid}
onInvalid={() => setIsDisabled(true)}
inputClassName='date-picker-input'
inputClassName="date-picker-input"
/>
<MainButton onClick={handleNext} disabled={isDisabled}>
{t('next')}
{t("next")}
</MainButton>
<footer className='footer'>
<footer className="footer">
<Policy>
{t('privacy_text', {
eulaLink: <a href='https://aura.wit.life/terms' target='_blank' rel='noopener noreferrer'>{t('eula')}</a>,
privacyLink: <a href='https://aura.wit.life/privacy' target='_blank' rel='noopener noreferrer'>{t('privacy_notice')}</a>,
clickHere: <a href='https://aura.wit.life/' target='_blank' rel='noopener noreferrer'>{t('here')}</a>,
{t("privacy_text", {
eulaLink: (
<a
href="https://aura.wit.life/terms"
target="_blank"
rel="noopener noreferrer"
>
{t("eula")}
</a>
),
privacyLink: (
<a
href="https://aura.wit.life/privacy"
target="_blank"
rel="noopener noreferrer"
>
{t("privacy_notice")}
</a>
),
clickHere: (
<a
href="https://aura.wit.life/"
target="_blank"
rel="noopener noreferrer"
>
{t("here")}
</a>
),
})}
</Policy>
<Purposes />
</footer>
</section>
)
);
}
export default BirthdayPage
export default BirthdayPage;

View File

@ -15,11 +15,13 @@ import styles from "./styles.module.css";
interface ICheckoutFormProps {
children?: JSX.Element | null;
subscriptionReceiptId?: string;
returnUrl?: string;
}
export default function CheckoutForm({
children,
subscriptionReceiptId,
returnUrl,
}: ICheckoutFormProps) {
const stripe = useStripe();
const elements = useElements();
@ -43,7 +45,9 @@ export default function CheckoutForm({
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `https://${window.location.host}/payment/result/${subscriptionReceiptId}/`,
return_url: returnUrl
? returnUrl
: `https://${window.location.host}/payment/result/${subscriptionReceiptId}/`,
},
});
if (error) {
@ -75,9 +79,7 @@ export default function CheckoutForm({
className={styles.button}
>
<img src="/lock.svg" alt="Secure" />
<span id="button-text">
{isProcessing ? "Processing..." : "Start"}
</span>
<span id="button-text">{isProcessing ? "Processing..." : "Start"}</span>
</MainButton>
{!!message.length && (
<Title variant="h5" style={{ color: "red" }}>

View File

@ -16,6 +16,7 @@ function PaymentResultPage(): JSX.Element {
const dispatch = useDispatch();
const [searchParams] = useSearchParams();
const status = searchParams.get("redirect_status");
const type = searchParams.get("type");
// const { id } = useParams();
// const requestTimeOutRef = useRef<NodeJS.Timeout>();
const [isLoading] = useState(true);
@ -89,9 +90,17 @@ function PaymentResultPage(): JSX.Element {
useEffect(() => {
if (status === "succeeded") {
dispatch(actions.status.update("subscribed"));
return navigate(routes.client.paymentSuccess());
let successPaymentRoute = routes.client.paymentSuccess();
if (type === "epe") {
successPaymentRoute = routes.client.epeSuccessPayment();
}
return navigate(successPaymentRoute);
}
return navigate(routes.client.paymentFail());
let failPaymentRoute = routes.client.paymentFail();
if (type === "epe") {
failPaymentRoute = routes.client.epeFailPayment();
}
return navigate(failPaymentRoute);
}, [navigate, status, dispatch]);
return <div className={styles.page}>{isLoading && <Loader />}</div>;

View File

@ -0,0 +1,36 @@
import { Elements } from "@stripe/react-stripe-js";
import styles from "./styles.module.css";
import CheckoutForm from "@/components/PaymentPage/methods/Stripe/CheckoutForm";
import { useEffect, useState } from "react";
import { Stripe, loadStripe } from "@stripe/stripe-js";
import SecurityPayments from "../../TrialPayment/components/SecurityPayments";
interface IPaymentFormProps {
stripePublicKey: string;
clientSecret: string;
returnUrl: string;
}
function PaymentForm({ stripePublicKey, clientSecret, returnUrl }: IPaymentFormProps) {
const [stripePromise, setStripePromise] =
useState<Promise<Stripe | null> | null>(null);
useEffect(() => {
setStripePromise(loadStripe(stripePublicKey));
}, [stripePublicKey]);
return (
<div className={styles["payment-modal"]}>
<div className={styles["payment-method-container"]}>
{stripePromise && clientSecret && (
<Elements stripe={stripePromise} options={{ clientSecret }}>
<CheckoutForm returnUrl={returnUrl} />
</Elements>
)}
</div>
<SecurityPayments />
<p className={styles.address}>500 N RAINBOW BLVD LAS VEGAS, NV 89107</p>
</div>
);
}
export default PaymentForm;

View File

@ -0,0 +1,44 @@
.payment-modal {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 250px;
gap: 25px;
color: #2f2e37;
}
.title {
font-weight: 700;
font-size: 20px;
line-height: 20px;
text-align: center;
margin: 0;
}
.sub-plan-description {
font-size: 12px;
text-align: center;
line-height: 150%;
}
.payment-method-container {
width: 100%;
}
.address {
margin-bottom: 24px;
}
.payment-method {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 16px;
}
.address {
color: gray;
font-size: 10px;
}

View File

@ -0,0 +1,34 @@
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import routes from "@/routes";
import styles from "./styles.module.css";
import Title from "@/components/Title";
import MainButton from "@/components/MainButton";
function FailPaymentPage(): JSX.Element {
const { t } = useTranslation();
const navigate = useNavigate();
const handleNext = () => navigate(routes.client.epePayment());
return (
<section className={`${styles.page} page`}>
<img
src="/ExclamationIcon.png"
alt="Exclamation Icon"
style={{ minHeight: "180px" }}
/>
<div className={styles.text}>
<Title variant="h1">{t("auweb.pay_bad.title")}</Title>
<p className={styles.list}>{t("auweb.pay_bad.text1")}</p>
</div>
<div className={styles.bottom}>
<p className={styles.description}>{t("auweb.pay_bad.text2")}</p>
<MainButton className={styles.button} onClick={handleNext}>
{t("auweb.pay_bad.button")}
</MainButton>
</div>
</section>
);
}
export default FailPaymentPage;

View File

@ -0,0 +1,38 @@
.page {
position: relative;
height: calc(100vh - 50px);
/* max-height: -webkit-fill-available; */
overflow-y: scroll;
justify-content: center;
gap: 80px;
}
.text {
display: flex;
flex-direction: column;
}
.list {
font-weight: 500;
white-space: pre-wrap;
text-align: left;
}
.description {
font-weight: 500;
text-align: center;
}
.button {
width: 100%;
max-width: 260px;
border-radius: 50px;
background-color: #fe2b57;
}
.bottom {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}

View File

@ -0,0 +1,23 @@
import { useTranslation } from "react-i18next";
import styles from "./styles.module.css";
import Title from "@/components/Title";
function SuccessPaymentPage(): JSX.Element {
const { t } = useTranslation();
return (
<section className={`${styles.page} page`}>
<img
src="/SuccessIcon.png"
alt="Success Icon"
style={{ minHeight: "98px" }}
/>
<div className={styles.text}>
<Title variant="h1">The information has been sent to your e-mail</Title>
<p>{t("auweb.pay_good.text1")}</p>
</div>
</section>
);
}
export default SuccessPaymentPage;

View File

@ -0,0 +1,25 @@
.page {
position: relative;
flex: auto;
height: calc(100vh - 50px);
max-height: -webkit-fill-available;
justify-content: center;
gap: 80px;
}
.text {
display: flex;
flex-direction: column;
}
.text > p {
text-align: center;
font-weight: 500;
}
.button {
width: 100%;
max-width: 260px;
border-radius: 50px;
background-color: #fe2b57;
}

View File

@ -0,0 +1,213 @@
import EmailInput from "@/components/EmailEnterPage/EmailInput";
import styles from "./styles.module.css";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { actions, selectors } from "@/store";
import { useDispatch, useSelector } from "react-redux";
import MainButton from "@/components/MainButton";
import Loader, { LoaderColor } from "@/components/Loader";
import { useAuth } from "@/auth";
import { ApiError, extractErrorMessage, useApi } from "@/api";
import { getClientTimezone } from "@/locales";
import ErrorText from "@/components/ErrorText";
import Title from "@/components/Title";
import NameInput from "@/components/EmailEnterPage/NameInput";
import { getZodiacSignByDate } from "@/services/zodiac-sign";
import {
ResponsePost,
ResponsePostExistPaymentData,
} from "@/api/resources/SinglePayment";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import PaymentForm from "./PaymentForm";
function PaymentWithEmailPage() {
const { t, i18n } = useTranslation();
const { signUp } = useAuth();
const api = useApi();
const navigate = useNavigate();
const timezone = getClientTimezone();
const dispatch = useDispatch();
const birthday = useSelector(selectors.selectBirthday);
const locale = i18n.language;
const [email, setEmail] = useState("");
const [name, setName] = useState("");
const [isValidEmail, setIsValidEmail] = useState(false);
const [isValidName, setIsValidName] = useState(true);
const [isDisabled, setIsDisabled] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [isAuth, setIsAuth] = useState(false);
const [apiError, setApiError] = useState<ApiError | null>(null);
const [error, setError] = useState<boolean>(false);
const [paymentIntent, setPaymentIntent] = useState<
ResponsePost | ResponsePostExistPaymentData | null
>(null);
const returnUrl = `${window.location.protocol}//${window.location.host}/payment/result/?type=epe`;
useEffect(() => {
if (isValidName && isValidEmail) {
setIsDisabled(false);
} else {
setIsDisabled(true);
}
}, [isValidEmail, email, isValidName, name]);
const handleValidEmail = (email: string) => {
dispatch(actions.form.addEmail(email));
setEmail(email);
setIsValidEmail(true);
};
const handleValidName = (name: string) => {
setName(name);
setIsValidName(true);
};
const authorization = async () => {
try {
setIsLoading(true);
const auth = await api.auth({ email, timezone, locale });
const {
auth: { token, user },
} = auth;
signUp(token, user);
const payload = {
user: {
profile_attributes: {
birthday,
full_name: name,
},
},
token,
};
const updatedUser = await api.updateUser(payload).catch((error) => {
console.log("Error: ", error);
});
if (updatedUser?.user) {
dispatch(actions.user.update(updatedUser.user));
}
if (name) {
dispatch(
actions.user.update({
username: name,
})
);
}
dispatch(actions.status.update("registred"));
setIsAuth(true);
const userUpdated = await api.getUser({ token });
return { user: userUpdated?.user, token };
} catch (error) {
console.error(error);
if (error instanceof ApiError) {
setApiError(error as ApiError);
} else {
setError(true);
}
}
};
const handleClick = async () => {
const authData = await authorization();
if (!authData) {
return;
}
const { user, token } = authData;
console.log(token);
const productsSinglePayment = await api.getSinglePaymentProducts({
id: "1",
token,
});
const { productId } = productsSinglePayment[0];
const createSinglePayment = await api.createSinglePayment({
token,
data: {
user: {
id: `${user?.id}`,
email,
name,
sign: user?.profile?.sign?.sign || getZodiacSignByDate(birthday),
age: user?.profile?.age?.years || 1,
},
partner: {
sign: "partner_cancer",
age: 26,
},
paymentInfo: {
productId,
},
return_url: returnUrl,
},
});
setPaymentIntent(createSinglePayment);
setIsLoading(false);
if ("payment" in createSinglePayment) {
if (createSinglePayment.payment.status === "paid")
return navigate(routes.client.epeSuccessPayment());
return navigate(routes.client.epeFailPayment());
}
};
return (
<div className={`${styles.page} page`}>
{paymentIntent && "paymentIntent" in paymentIntent && (
<PaymentForm
stripePublicKey={paymentIntent.paymentIntent.data.public_key}
clientSecret={paymentIntent.paymentIntent.data.client_secret}
returnUrl={returnUrl}
/>
)}
{!paymentIntent && (
<>
<NameInput
value={name}
placeholder="Your name"
onValid={handleValidName}
onInvalid={() => setIsValidName(true)}
/>
<EmailInput
name="email"
value={email}
placeholder={t("your_email")}
onValid={handleValidEmail}
onInvalid={() => setIsValidEmail(false)}
/>
<MainButton
className={styles.button}
onClick={handleClick}
disabled={isDisabled}
>
{isLoading && <Loader color={LoaderColor.White} />}
{!isLoading &&
!(!apiError && !error && !isLoading && isAuth) &&
t("_continue")}
{!apiError && !error && !isLoading && isAuth && (
<img
className={styles["success-icon"]}
src="/SuccessIcon.png"
alt="Success Icon"
/>
)}
</MainButton>
</>
)}
{(error || apiError) && (
<Title variant="h3" style={{ color: "red", margin: 0 }}>
Something went wrong
</Title>
)}
{apiError && (
<ErrorText
size="medium"
isShown={Boolean(apiError)}
message={apiError ? extractErrorMessage(apiError) : null}
/>
)}
</div>
);
}
export default PaymentWithEmailPage;

View File

@ -0,0 +1,61 @@
.page {
/* position: relative; */
position: static;
height: fit-content;
min-height: calc(100dvh - 103px);
/* max-height: -webkit-fill-available; */
display: flex;
justify-items: center;
justify-content: center;
align-items: center;
/* gap: 16px; */
}
.button {
border-radius: 12px;
margin-top: 0;
box-shadow: rgba(0, 0, 0, 0.25) 0px 4px 4px 0px;
height: 50px;
min-height: 0;
background: linear-gradient(
165.54deg,
rgb(20, 19, 51) -33.39%,
rgb(32, 34, 97) 15.89%,
rgb(84, 60, 151) 55.84%,
rgb(105, 57, 162) 74.96%
);
font-size: 18px;
line-height: 21px;
}
.payment-loader {
display: flex;
justify-content: center;
align-items: center;
}
.cross {
position: absolute;
top: -36px;
right: 28px;
width: 22px;
height: 22px;
cursor: pointer;
z-index: 9;
}
.title {
font-size: 27px;
font-weight: 700;
margin: 0;
}
.email {
font-size: 17px;
font-weight: 500;
margin: 0;
}
.success-icon {
height: 100%;
}

View File

@ -22,6 +22,9 @@ import PayPalButton from "./components/PayPalButton";
interface IPaymentModalProps {
activeSubscriptionPlan?: ISubscriptionPlan;
stripePublicKey?: string;
singlePayClientSecret?: string;
defaultPaymentMethod?: EPaymentMethod;
}
function PaymentModal({ activeSubscriptionPlan }: IPaymentModalProps) {

View File

@ -4,6 +4,7 @@ const host = "";
export const apiHost = "https://api-web.aura.wit.life";
const siteHost = "https://aura.wit.life";
const prefix = "api/v1";
const dApiHost = "https://dev.api.witapps.us";
const routes = {
client: {
@ -14,17 +15,22 @@ const routes = {
palmistryBirthdate: () => [host, "palmistry", "birthdate"].join("/"),
palmistryPalmsHold: () => [host, "palmistry", "palms-hold"].join("/"),
palmistryWish: () => [host, "palmistry", "wish"].join("/"),
palmistryRelationship: () => [host, "palmistry", "relationship-status"].join("/"),
palmistryResonatedElement: () => [host, "palmistry", "resonated-element"].join("/"),
palmistryColorYouLike: () => [host, "palmistry", "color-you-like"].join("/"),
palmistryRelationship: () =>
[host, "palmistry", "relationship-status"].join("/"),
palmistryResonatedElement: () =>
[host, "palmistry", "resonated-element"].join("/"),
palmistryColorYouLike: () =>
[host, "palmistry", "color-you-like"].join("/"),
palmistryDecisions: () => [host, "palmistry", "decisions"].join("/"),
palmistryGuidancePlan: () => [host, "palmistry", "guidance-plan"].join("/"),
palmistryPersonalStatement: () => [host, "palmistry", "personal-statement"].join("/"),
palmistryPersonalStatement: () =>
[host, "palmistry", "personal-statement"].join("/"),
palmistryScanInfo: () => [host, "palmistry", "scan-info"].join("/"),
palmistryUpload: () => [host, "palmistry", "upload"].join("/"),
palmistryScanPhoto: () => [host, "palmistry", "scan-photo"].join("/"),
palmistryEmail: () => [host, "palmistry", "email"].join("/"),
palmistrySubscriptionPlan: () => [host, "palmistry", "subscription-plan"].join("/"),
palmistrySubscriptionPlan: () =>
[host, "palmistry", "subscription-plan"].join("/"),
palmistryPaywall: () => [host, "palmistry", "paywall"].join("/"),
palmistryPayment: () => [host, "palmistry", "payment"].join("/"),
palmistryDiscount: () => [host, "palmistry", "discount"].join("/"),
@ -108,6 +114,12 @@ const routes = {
unlimitedReadings: () => [host, "unlimited-readings"].join("/"),
addConsultation: () => [host, "add-consultation"].join("/"),
// Email - Pay - Email
epeBirthdate: () => [host, "epe", "birthdate"].join("/"),
epePayment: () => [host, "epe", "payment"].join("/"),
epeSuccessPayment: () => [host, "epe", "success-payment"].join("/"),
epeFailPayment: () => [host, "epe", "fail-payment"].join("/"),
notFound: () => [host, "404"].join("/"),
},
server: {
@ -164,6 +176,10 @@ const routes = {
),
getAiRequestsV2: (id: string) =>
[apiHost, "api/v2", "ai", "requests", `${id}.json`].join("/"),
dApiTestPaymentProducts: () =>
[dApiHost, "payment", "test", "products"].join("/"),
dApiPaymentCheckout: () => [dApiHost, "payment", "checkout"].join("/"),
},
};
@ -266,6 +282,7 @@ export const withoutFooterRoutes = [
routes.client.addReport(),
routes.client.unlimitedReadings(),
routes.client.addConsultation(),
routes.client.epeSuccessPayment(),
];
export const withoutFooterPartOfRoutes = [routes.client.questionnaire()];
@ -334,14 +351,15 @@ export const withoutHeaderRoutes = [
routes.client.email("marketing-landing"),
routes.client.email("marketing-trial-payment"),
routes.client.tryApp(),
routes.client.epeSuccessPayment(),
];
export const hasNoHeader = (path: string) => {
let result = true;
withoutHeaderRoutes.forEach((route) => {
if (
!path.includes("palmistry") && path.includes(route) ||
path.includes("palmistry") && path === route
(!path.includes("palmistry") && path.includes(route)) ||
(path.includes("palmistry") && path === route)
) {
result = false;
}