Merge branch 'new-payment-method' into 'develop'
new-payment-method See merge request witapp/aura-webapp!149
This commit is contained in:
commit
fcb60fc459
@ -12,6 +12,9 @@ export interface PayloadGet extends Payload {
|
|||||||
export enum EPlacementKeys {
|
export enum EPlacementKeys {
|
||||||
"aura.placement.main" = "aura.placement.main",
|
"aura.placement.main" = "aura.placement.main",
|
||||||
"aura.placement.redesign.main" = "aura.placement.redesign.main",
|
"aura.placement.redesign.main" = "aura.placement.redesign.main",
|
||||||
|
"aura.placement.email.marketing" = "aura.placement.email.marketing",
|
||||||
|
"aura.placement.secret.discount" = "aura.placement.secret.discount",
|
||||||
|
"aura.placement.palmistry.main" = "aura.placement.palmistry.main"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ResponseGetSuccess {
|
interface ResponseGetSuccess {
|
||||||
|
|||||||
@ -57,7 +57,6 @@ import { Asset } from "@/api/resources/Assets";
|
|||||||
import PaymentResultPage from "../PaymentPage/results";
|
import PaymentResultPage from "../PaymentPage/results";
|
||||||
import PaymentSuccessPage from "../PaymentPage/results/SuccessPage";
|
import PaymentSuccessPage from "../PaymentPage/results/SuccessPage";
|
||||||
import PaymentFailPage from "../PaymentPage/results/ErrorPage";
|
import PaymentFailPage from "../PaymentPage/results/ErrorPage";
|
||||||
import { StripePage } from "../StripePage";
|
|
||||||
import AuthPage from "../AuthPage";
|
import AuthPage from "../AuthPage";
|
||||||
import AuthResultPage from "../AuthResultPage";
|
import AuthResultPage from "../AuthResultPage";
|
||||||
import MagicBallPage from "../pages/MagicBall";
|
import MagicBallPage from "../pages/MagicBall";
|
||||||
@ -113,8 +112,8 @@ import AddConsultationPage from "../pages/AdditionalPurchases/pages/AddConsultat
|
|||||||
import StepsManager from "@/components/palmistry/steps-manager/steps-manager";
|
import StepsManager from "@/components/palmistry/steps-manager/steps-manager";
|
||||||
import Advisors from "../pages/Advisors";
|
import Advisors from "../pages/Advisors";
|
||||||
import AdvisorChatPage from "../pages/AdvisorChat";
|
import AdvisorChatPage from "../pages/AdvisorChat";
|
||||||
import SuccessPaymentPage from "../pages/PaymentWithEmailPage/ResultPayment/SuccessPaymentPage";
|
import SuccessPaymentPage from "../pages/SinglePaymentPage/ResultPayment/SuccessPaymentPage";
|
||||||
import FailPaymentPage from "../pages/PaymentWithEmailPage/ResultPayment/FailPaymentPage";
|
import FailPaymentPage from "../pages/SinglePaymentPage/ResultPayment/FailPaymentPage";
|
||||||
import { useSchemeColorByElement } from "@/hooks/useSchemeColorByElement";
|
import { useSchemeColorByElement } from "@/hooks/useSchemeColorByElement";
|
||||||
import GetInformationPartnerPage from "../pages/GetInformationPartner";
|
import GetInformationPartnerPage from "../pages/GetInformationPartner";
|
||||||
import BirthPlacePage from "../pages/BirthPlacePage";
|
import BirthPlacePage from "../pages/BirthPlacePage";
|
||||||
@ -598,34 +597,6 @@ function App(): JSX.Element {
|
|||||||
</Route>
|
</Route>
|
||||||
{/* Advisor short path */}
|
{/* Advisor short path */}
|
||||||
|
|
||||||
{/* Single Payment Page Short Path */}
|
|
||||||
{/* <Route
|
|
||||||
element={
|
|
||||||
<ShortPathOutlet
|
|
||||||
productKey={EProductKeys["chat.aura"]}
|
|
||||||
redirectUrls={{
|
|
||||||
data: {
|
|
||||||
no: routes.client.advisorChatGender(),
|
|
||||||
force: routes.client.advisorChatBirthdate(),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
requiredParameters={[
|
|
||||||
birthdate,
|
|
||||||
birthPlace,
|
|
||||||
isForceShortPath || gender,
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Route
|
|
||||||
path={routes.client.advisorChatPayment()}
|
|
||||||
element={<PaymentWithEmailPage />}
|
|
||||||
>
|
|
||||||
<Route path=":productId" element={<PaymentWithEmailPage />} />
|
|
||||||
</Route>
|
|
||||||
</Route> */}
|
|
||||||
{/* Single Payment Page Short Path */}
|
|
||||||
|
|
||||||
{/* Test Routes Start */}
|
{/* Test Routes Start */}
|
||||||
<Route path={routes.client.notFound()} element={<NotFoundPage />} />
|
<Route path={routes.client.notFound()} element={<NotFoundPage />} />
|
||||||
<Route path={routes.client.gender()} element={<GenderPage />}>
|
<Route path={routes.client.gender()} element={<GenderPage />}>
|
||||||
@ -813,10 +784,6 @@ function App(): JSX.Element {
|
|||||||
/>
|
/>
|
||||||
<Route path={routes.client.static()} element={<StaticPage />} />
|
<Route path={routes.client.static()} element={<StaticPage />} />
|
||||||
<Route path={routes.client.priceList()} element={<PriceListPage />} />
|
<Route path={routes.client.priceList()} element={<PriceListPage />} />
|
||||||
{/* <Route
|
|
||||||
path={routes.client.wallpaper()}
|
|
||||||
element={<ProtectWallpaperPage />}
|
|
||||||
/> */}
|
|
||||||
</Route>
|
</Route>
|
||||||
<Route element={<AuthorizedUserOutlet />}>
|
<Route element={<AuthorizedUserOutlet />}>
|
||||||
<Route
|
<Route
|
||||||
@ -828,18 +795,10 @@ function App(): JSX.Element {
|
|||||||
</Route>
|
</Route>
|
||||||
<Route element={<PrivateOutlet />}>
|
<Route element={<PrivateOutlet />}>
|
||||||
<Route element={<AuthorizedUserOutlet />}>
|
<Route element={<AuthorizedUserOutlet />}>
|
||||||
{/* <Route
|
|
||||||
path={routes.client.subscription()}
|
|
||||||
element={<SubscriptionPage />}
|
|
||||||
/> */}
|
|
||||||
<Route
|
<Route
|
||||||
path={routes.client.paymentMethod()}
|
path={routes.client.paymentMethod()}
|
||||||
element={<PaymentPage />}
|
element={<PaymentPage />}
|
||||||
/>
|
/>
|
||||||
<Route
|
|
||||||
path={routes.client.paymentStripe()}
|
|
||||||
element={<StripePage />}
|
|
||||||
/>
|
|
||||||
</Route>
|
</Route>
|
||||||
<Route element={<PrivateSubscriptionOutlet />}>
|
<Route element={<PrivateSubscriptionOutlet />}>
|
||||||
<Route path={routes.client.home()} element={<HomePage />} />
|
<Route path={routes.client.home()} element={<HomePage />} />
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import MainButton from '@/components/MainButton'
|
|
||||||
|
|
||||||
interface IStripeButtonProps {
|
|
||||||
onClick: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StripeButton({ onClick }: IStripeButtonProps): JSX.Element {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
return (
|
|
||||||
<MainButton color='blue' onClick={onClick}>
|
|
||||||
{t('stripe')}
|
|
||||||
</MainButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,120 +0,0 @@
|
|||||||
import styles from "./styles.module.css";
|
|
||||||
import Modal from "@/components/Modal";
|
|
||||||
import Loader from "@/components/Loader";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
|
||||||
import { Elements } from "@stripe/react-stripe-js";
|
|
||||||
import CheckoutForm from "./CheckoutForm";
|
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
import { selectors } from "@/store";
|
|
||||||
import Title from "@/components/Title";
|
|
||||||
import ApplePayButton from "@/components/StripePage/ApplePayButton";
|
|
||||||
import SubPlanInformation from "@/components/SubPlanInformation";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import routes from "@/routes";
|
|
||||||
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
|
||||||
import { EPlacementKeys } from "@/api/resources/Paywall";
|
|
||||||
import { useMakePayment } from "@/hooks/payment/useMakePayment";
|
|
||||||
|
|
||||||
interface StripeModalProps {
|
|
||||||
open: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
// onSuccess: (receipt: SubscriptionReceipts.SubscriptionReceipt) => void;
|
|
||||||
// onError: (error: Error) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StripeModal({
|
|
||||||
open,
|
|
||||||
onClose,
|
|
||||||
}: // onSuccess,
|
|
||||||
// onError,
|
|
||||||
StripeModalProps): JSX.Element {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const email = useSelector(selectors.selectUser).email;
|
|
||||||
const [stripePromise, setStripePromise] =
|
|
||||||
useState<Promise<Stripe | null> | null>(null);
|
|
||||||
|
|
||||||
const { products } = usePaywall({
|
|
||||||
placementKey: EPlacementKeys["aura.placement.main"],
|
|
||||||
});
|
|
||||||
|
|
||||||
const activeProduct = useSelector(selectors.selectActiveProduct);
|
|
||||||
if (!activeProduct) {
|
|
||||||
navigate(routes.client.trialChoice());
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
paymentIntentId,
|
|
||||||
clientSecret,
|
|
||||||
returnUrl: checkoutUrl,
|
|
||||||
paymentType,
|
|
||||||
publicKey,
|
|
||||||
isLoading,
|
|
||||||
error,
|
|
||||||
} = useMakePayment({
|
|
||||||
productId: activeProduct?._id || "",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (checkoutUrl?.length) {
|
|
||||||
window.location.href = checkoutUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
if (!products?.length || !publicKey) return;
|
|
||||||
setStripePromise(loadStripe(publicKey));
|
|
||||||
const isActiveSubPlan = products.find(
|
|
||||||
(product) => product._id === activeProduct?._id
|
|
||||||
);
|
|
||||||
if (!activeProduct || !isActiveSubPlan) {
|
|
||||||
navigate(routes.client.priceList());
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [activeProduct, navigate, products, publicKey]);
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
onClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
if (error?.length) {
|
|
||||||
return (
|
|
||||||
<div className={styles["payment-modal"]}>
|
|
||||||
<Title variant="h3" className={styles.title}>
|
|
||||||
Something went wrong
|
|
||||||
</Title>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal open={open} onClose={handleClose}>
|
|
||||||
{isLoading ? (
|
|
||||||
<div className={styles["payment-loader"]}>
|
|
||||||
<Loader />
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{!isLoading && (
|
|
||||||
<>
|
|
||||||
<Title variant="h2" className={styles.title}>
|
|
||||||
Choose payment method
|
|
||||||
</Title>
|
|
||||||
<p className={styles.email}>{email}</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{stripePromise && clientSecret && paymentIntentId && (
|
|
||||||
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
|
||||||
<ApplePayButton
|
|
||||||
activeProduct={activeProduct}
|
|
||||||
client_secret={clientSecret}
|
|
||||||
subscriptionReceiptId={paymentIntentId}
|
|
||||||
/>
|
|
||||||
{activeProduct && <SubPlanInformation product={activeProduct} />}
|
|
||||||
<CheckoutForm
|
|
||||||
confirmType={paymentType}
|
|
||||||
subscriptionReceiptId={paymentIntentId}
|
|
||||||
/>
|
|
||||||
</Elements>
|
|
||||||
)}
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from './Button'
|
|
||||||
export * from './Modal'
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
import Loader from "@/components/Loader";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
|
||||||
import { Elements } from "@stripe/react-stripe-js";
|
|
||||||
import CheckoutForm from "../PaymentPage/methods/Stripe/CheckoutForm";
|
|
||||||
import styles from "./styles.module.css";
|
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
import { selectors } from "@/store";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import routes from "@/routes";
|
|
||||||
import SubPlanInformation from "../SubPlanInformation";
|
|
||||||
import Title from "../Title";
|
|
||||||
import ApplePayButton from "./ApplePayButton";
|
|
||||||
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
|
||||||
import { EPlacementKeys } from "@/api/resources/Paywall";
|
|
||||||
import { useMakePayment } from "@/hooks/payment/useMakePayment";
|
|
||||||
|
|
||||||
export function StripePage(): JSX.Element {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const activeProduct = useSelector(selectors.selectActiveProduct);
|
|
||||||
const email = useSelector(selectors.selectUser).email;
|
|
||||||
const [stripePromise, setStripePromise] =
|
|
||||||
useState<Promise<Stripe | null> | null>(null);
|
|
||||||
if (!activeProduct) {
|
|
||||||
navigate(routes.client.priceList());
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
paymentIntentId,
|
|
||||||
clientSecret,
|
|
||||||
returnUrl: checkoutUrl,
|
|
||||||
paymentType,
|
|
||||||
publicKey,
|
|
||||||
isLoading,
|
|
||||||
error,
|
|
||||||
} = useMakePayment({
|
|
||||||
productId: activeProduct?._id || "",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (checkoutUrl?.length) {
|
|
||||||
window.location.href = checkoutUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { products } = usePaywall({
|
|
||||||
placementKey: EPlacementKeys["aura.placement.main"],
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
if (!products?.length || !publicKey) return;
|
|
||||||
setStripePromise(loadStripe(publicKey));
|
|
||||||
const isActiveProduct = products.find(
|
|
||||||
(product) => product._id === activeProduct?._id
|
|
||||||
);
|
|
||||||
if (!activeProduct || !isActiveProduct) {
|
|
||||||
navigate(routes.client.priceList());
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [activeProduct, navigate, products, publicKey]);
|
|
||||||
|
|
||||||
if (error?.length) {
|
|
||||||
return (
|
|
||||||
<div className={styles["payment-modal"]}>
|
|
||||||
<Title variant="h3" className={styles.title}>
|
|
||||||
Something went wrong
|
|
||||||
</Title>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`${styles.page} page`}>
|
|
||||||
{isLoading ? (
|
|
||||||
<div className={styles["payment-loader"]}>
|
|
||||||
<Loader />
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{!isLoading && (
|
|
||||||
<>
|
|
||||||
<Title variant="h2" className={styles.title}>
|
|
||||||
Pay
|
|
||||||
</Title>
|
|
||||||
<p className={styles.email}>{email}</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{stripePromise && clientSecret && paymentIntentId && (
|
|
||||||
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
|
||||||
<ApplePayButton
|
|
||||||
activeProduct={activeProduct}
|
|
||||||
client_secret={clientSecret}
|
|
||||||
subscriptionReceiptId={paymentIntentId}
|
|
||||||
/>
|
|
||||||
{activeProduct && <SubPlanInformation product={activeProduct} />}
|
|
||||||
<CheckoutForm
|
|
||||||
confirmType={paymentType}
|
|
||||||
subscriptionReceiptId={paymentIntentId}
|
|
||||||
/>
|
|
||||||
</Elements>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
.page {
|
|
||||||
/* position: relative; */
|
|
||||||
position: static;
|
|
||||||
/* height: calc(100vh - 50px);
|
|
||||||
max-height: -webkit-fill-available; */
|
|
||||||
display: flex;
|
|
||||||
justify-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import TotalToday from "./TotalToday";
|
import TotalToday from "./TotalToday";
|
||||||
import ApplePayButton from "../StripePage/ApplePayButton";
|
import ApplePayButton from "../PaymentPage/methods/ApplePayButton";
|
||||||
import { IPaywallProduct } from "@/api/resources/Paywall";
|
import { IPaywallProduct } from "@/api/resources/Paywall";
|
||||||
|
|
||||||
interface ISubPlanInformationProps {
|
interface ISubPlanInformationProps {
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import PaymentMethodsChoice from "../PaymentMethodsChoice";
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { EPaymentMethod, paymentMethods } from "@/data/paymentMethods";
|
import { EPaymentMethod, paymentMethods } from "@/data/paymentMethods";
|
||||||
import { Elements } from "@stripe/react-stripe-js";
|
import { Elements } from "@stripe/react-stripe-js";
|
||||||
import ApplePayButton from "@/components/StripePage/ApplePayButton";
|
import ApplePayButton from "@/components/PaymentPage/methods/ApplePayButton";
|
||||||
import CheckoutForm from "@/components/PaymentPage/methods/Stripe/CheckoutForm";
|
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
||||||
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { selectors } from "@/store";
|
import { selectors } from "@/store";
|
||||||
|
|||||||
@ -71,6 +71,16 @@ function TrialPaymentPage() {
|
|||||||
}
|
}
|
||||||
}, [dispatch, subPlan, products, activeProduct]);
|
}, [dispatch, subPlan, products, activeProduct]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!products.length) return;
|
||||||
|
const isActiveProduct = products.find(
|
||||||
|
(product) => product._id === activeProduct?._id
|
||||||
|
);
|
||||||
|
if (!activeProduct || !isActiveProduct) {
|
||||||
|
navigate(routes.client.trialChoiceV1());
|
||||||
|
}
|
||||||
|
}, [activeProduct, navigate, products]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (["relationship", "married"].includes(flowChoice)) {
|
if (["relationship", "married"].includes(flowChoice)) {
|
||||||
setSingleOrWithPartner("partner");
|
setSingleOrWithPartner("partner");
|
||||||
|
|||||||
@ -38,7 +38,7 @@ function PaymentDiscountTable() {
|
|||||||
<p>Your cost per 14 days after trial:</p>
|
<p>Your cost per 14 days after trial:</p>
|
||||||
<div className={styles.side}>
|
<div className={styles.side}>
|
||||||
<span className={styles.discount}>$19</span>
|
<span className={styles.discount}>$19</span>
|
||||||
<strong>$9</strong>
|
<strong>${(activeProduct?.price || 0) / 100}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className={styles.save}>You save $30</p>
|
<p className={styles.save}>You save $30</p>
|
||||||
|
|||||||
@ -4,15 +4,38 @@ import MainButton from "@/components/MainButton";
|
|||||||
import PaymentDiscountTable from "./PaymentDiscountTable";
|
import PaymentDiscountTable from "./PaymentDiscountTable";
|
||||||
import Modal from "@/components/Modal";
|
import Modal from "@/components/Modal";
|
||||||
import PaymentModal from "../TrialPayment/components/PaymentModal";
|
import PaymentModal from "../TrialPayment/components/PaymentModal";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { actions, selectors } from "@/store";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
||||||
|
import { EPlacementKeys } from "@/api/resources/Paywall";
|
||||||
|
|
||||||
function TrialPaymentWithDiscount() {
|
function TrialPaymentWithDiscount() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const { products } = usePaywall({
|
||||||
|
placementKey: EPlacementKeys["aura.placement.secret.discount"],
|
||||||
|
});
|
||||||
|
const productFromStore = useSelector(selectors.selectActiveProduct);
|
||||||
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
|
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setIsOpenPaymentModal(false);
|
setIsOpenPaymentModal(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!products.length) return;
|
||||||
|
const activeProduct = products.find(
|
||||||
|
(p) => p.trialPrice === productFromStore?.trialPrice
|
||||||
|
);
|
||||||
|
if (!activeProduct) {
|
||||||
|
dispatch(actions.payment.update({ activeProduct: products[0] }));
|
||||||
|
}
|
||||||
|
if (activeProduct) {
|
||||||
|
dispatch(actions.payment.update({ activeProduct }));
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [dispatch, products]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`${styles.page} page`}>
|
<section className={`${styles.page} page`}>
|
||||||
<Modal open={isOpenPaymentModal} onClose={handleClose}>
|
<Modal open={isOpenPaymentModal} onClose={handleClose}>
|
||||||
@ -35,10 +58,12 @@ function TrialPaymentWithDiscount() {
|
|||||||
</MainButton>
|
</MainButton>
|
||||||
<p className={styles.policy}>
|
<p className={styles.policy}>
|
||||||
By continuing you agree that if you don't cancel prior to the end of the
|
By continuing you agree that if you don't cancel prior to the end of the
|
||||||
3-days trial, you will automatically be charged $9 for the introductory
|
3-days trial, you will automatically be charged $
|
||||||
period of 14 days thereafter the standard rate of $9 every 14 days until
|
{(productFromStore?.price || 0) / 100} for the introductory period of 14
|
||||||
you cancel in settings. Learn more about cancellation and refund policy
|
days thereafter the standard rate of $
|
||||||
in Subscription terms.
|
{(productFromStore?.price || 0) / 100} every 14 days until you cancel in
|
||||||
|
settings. Learn more about cancellation and refund policy in
|
||||||
|
Subscription terms.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
} from "@/api/resources/SinglePayment";
|
} from "@/api/resources/SinglePayment";
|
||||||
import { createSinglePayment } from "@/services/singlePayment";
|
import { createSinglePayment } from "@/services/singlePayment";
|
||||||
import Modal from "@/components/Modal";
|
import Modal from "@/components/Modal";
|
||||||
import PaymentForm from "@/components/pages/PaymentWithEmailPage/PaymentForm";
|
import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm";
|
||||||
import { getPriceCentsToDollars } from "@/services/price";
|
import { getPriceCentsToDollars } from "@/services/price";
|
||||||
import Loader, { LoaderColor } from "@/components/Loader";
|
import Loader, { LoaderColor } from "@/components/Loader";
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import { SinglePayment, useApi, useApiCall } from "@/api";
|
|||||||
import Loader, { LoaderColor } from "@/components/Loader";
|
import Loader, { LoaderColor } from "@/components/Loader";
|
||||||
import { getPriceCentsToDollars } from "@/services/price";
|
import { getPriceCentsToDollars } from "@/services/price";
|
||||||
import Modal from "@/components/Modal";
|
import Modal from "@/components/Modal";
|
||||||
import PaymentForm from "@/components/pages/PaymentWithEmailPage/PaymentForm";
|
import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm";
|
||||||
|
|
||||||
function AddReportPage() {
|
function AddReportPage() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import {
|
|||||||
} from "@/api/resources/SinglePayment";
|
} from "@/api/resources/SinglePayment";
|
||||||
import Modal from "@/components/Modal";
|
import Modal from "@/components/Modal";
|
||||||
import { getPriceCentsToDollars } from "@/services/price";
|
import { getPriceCentsToDollars } from "@/services/price";
|
||||||
import PaymentForm from "@/components/pages/PaymentWithEmailPage/PaymentForm";
|
import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm";
|
||||||
|
|
||||||
const sliderSettings = {
|
const sliderSettings = {
|
||||||
dots: false,
|
dots: false,
|
||||||
|
|||||||
@ -1,7 +1,13 @@
|
|||||||
import Title from "@/components/Title";
|
import Title from "@/components/Title";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
|
|
||||||
function ComparePrices() {
|
function ComparePrices({
|
||||||
|
oldPrice,
|
||||||
|
newPrice,
|
||||||
|
}: {
|
||||||
|
oldPrice: string;
|
||||||
|
newPrice: string;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={`${styles["old-price"]} ${styles["price-container"]}`}>
|
<div className={`${styles["old-price"]} ${styles["price-container"]}`}>
|
||||||
@ -11,7 +17,7 @@ function ComparePrices() {
|
|||||||
</Title>
|
</Title>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles["main-container"]}>
|
<div className={styles["main-container"]}>
|
||||||
<p className={styles.text}>up to $13.67</p>
|
<p className={styles.text}>{oldPrice}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`${styles["new-price"]} ${styles["price-container"]}`}>
|
<div className={`${styles["new-price"]} ${styles["price-container"]}`}>
|
||||||
@ -22,7 +28,7 @@ function ComparePrices() {
|
|||||||
</Title>
|
</Title>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles["main-container"]}>
|
<div className={styles["main-container"]}>
|
||||||
<p className={styles.text}>$0</p>
|
<p className={styles.text}>${newPrice}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import Title from "@/components/Title";
|
import Title from "@/components/Title";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
|
|
||||||
function SpecialOfferBanner() {
|
function SpecialOfferBanner({ title }: { title: string }) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<img src="/wrapped-gift.webp" alt="Wrapped Gift" />
|
<img src="/wrapped-gift.webp" alt="Wrapped Gift" />
|
||||||
<div className="text-container">
|
<div className="text-container">
|
||||||
<Title className={styles.title} variant="h3">
|
<Title className={styles.title} variant="h3">
|
||||||
Special Offer!
|
{title}
|
||||||
</Title>
|
</Title>
|
||||||
<p className={styles.text}>Everything for free. Trial include!</p>
|
<p className={styles.text}>Everything for free. Trial include!</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -15,11 +15,16 @@ import { selectors } from "@/store";
|
|||||||
import { getZodiacSignByDate } from "@/services/zodiac-sign";
|
import { getZodiacSignByDate } from "@/services/zodiac-sign";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import routes from "@/routes";
|
import routes from "@/routes";
|
||||||
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
||||||
|
import { EPlacementKeys } from "@/api/resources/Paywall";
|
||||||
|
|
||||||
function MarketingLanding() {
|
function MarketingLanding() {
|
||||||
const birthdate = useSelector(selectors.selectBirthdate);
|
const birthdate = useSelector(selectors.selectBirthdate);
|
||||||
const zodiacSign = getZodiacSignByDate(birthdate);
|
const zodiacSign = getZodiacSignByDate(birthdate);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { paywall, products, getText } = usePaywall({
|
||||||
|
placementKey: EPlacementKeys["aura.placement.email.marketing"],
|
||||||
|
});
|
||||||
|
|
||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
navigate(routes.client.email("marketing-trial-payment"));
|
navigate(routes.client.email("marketing-trial-payment"));
|
||||||
@ -27,7 +32,7 @@ function MarketingLanding() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`${styles.page} page`}>
|
<section className={`${styles.page} page`}>
|
||||||
<SpecialOfferBanner />
|
<SpecialOfferBanner title={paywall?.name || ""} />
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<Title variant="h2" className={`${styles.title} ${styles["hi-title"]}`}>
|
<Title variant="h2" className={`${styles.title} ${styles["hi-title"]}`}>
|
||||||
Hey, {zodiacSign} Sun 👋
|
Hey, {zodiacSign} Sun 👋
|
||||||
@ -66,7 +71,10 @@ function MarketingLanding() {
|
|||||||
alt="Understanding"
|
alt="Understanding"
|
||||||
style={{ minHeight: "323px" }}
|
style={{ minHeight: "323px" }}
|
||||||
/>
|
/>
|
||||||
<ComparePrices />
|
<ComparePrices
|
||||||
|
oldPrice={getText("text.old.price", {}) as string}
|
||||||
|
newPrice={`${((products[0]?.trialPrice || 0) / 100).toFixed(2)}`}
|
||||||
|
/>
|
||||||
<PointsList
|
<PointsList
|
||||||
points={marketingLandingPointsList}
|
points={marketingLandingPointsList}
|
||||||
title="Your plan also includes:"
|
title="Your plan also includes:"
|
||||||
|
|||||||
@ -5,31 +5,22 @@ import MainButton from "@/components/MainButton";
|
|||||||
import Modal from "@/components/Modal";
|
import Modal from "@/components/Modal";
|
||||||
import PaymentModal from "../../TrialPayment/components/PaymentModal";
|
import PaymentModal from "../../TrialPayment/components/PaymentModal";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApi } from "@/api";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
||||||
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
import { EPlacementKeys } from "@/api/resources/Paywall";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { actions } from "@/store";
|
||||||
|
|
||||||
function MarketingTrialPayment() {
|
function MarketingTrialPayment() {
|
||||||
const { i18n } = useTranslation();
|
const dispatch = useDispatch();
|
||||||
const locale = i18n.language;
|
|
||||||
const api = useApi();
|
|
||||||
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
|
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
|
||||||
const [freeTrialProduct, setFreeTrialProduct] = useState<
|
|
||||||
IPaywallProduct | undefined
|
|
||||||
>();
|
|
||||||
|
|
||||||
const { products } = usePaywall({
|
const { products } = usePaywall({
|
||||||
placementKey: EPlacementKeys["aura.placement.main"],
|
placementKey: EPlacementKeys["aura.placement.email.marketing"],
|
||||||
});
|
});
|
||||||
|
|
||||||
// get free trial plan
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
dispatch(actions.payment.update({ activeProduct: products[0] }));
|
||||||
const _freeProduct = products.find((product) => product.isFreeTrial);
|
}, [dispatch, products]);
|
||||||
setFreeTrialProduct(_freeProduct);
|
|
||||||
})();
|
|
||||||
}, [api, locale, products]);
|
|
||||||
|
|
||||||
const openStripeModal = () => {
|
const openStripeModal = () => {
|
||||||
setIsOpenPaymentModal(true);
|
setIsOpenPaymentModal(true);
|
||||||
@ -41,13 +32,17 @@ function MarketingTrialPayment() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
{products[0] && (
|
||||||
containerClassName={styles.modal}
|
<Modal
|
||||||
open={isOpenPaymentModal}
|
containerClassName={styles.modal}
|
||||||
onClose={handleCloseModal}
|
open={isOpenPaymentModal}
|
||||||
>
|
onClose={handleCloseModal}
|
||||||
<PaymentModal activeProduct={freeTrialProduct} />
|
>
|
||||||
</Modal>
|
<PaymentModal
|
||||||
|
placementKey={EPlacementKeys["aura.placement.email.marketing"]}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
<section className={`${styles.page} page`}>
|
<section className={`${styles.page} page`}>
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<div className={styles.banner}>Special Offer</div>
|
<div className={styles.banner}>Special Offer</div>
|
||||||
@ -57,7 +52,7 @@ function MarketingTrialPayment() {
|
|||||||
<p className={styles.description}>No pressure. Cancel anytime</p>
|
<p className={styles.description}>No pressure. Cancel anytime</p>
|
||||||
<div className={styles["total-today"]}>
|
<div className={styles["total-today"]}>
|
||||||
<p className={styles.description}>Total today:</p>
|
<p className={styles.description}>Total today:</p>
|
||||||
<p className={styles.value}>$0</p>
|
<p className={styles.value}>${(products[0]?.trialPrice / 100).toFixed(2) || 0}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.line} />
|
<div className={styles.line} />
|
||||||
<div className={styles["code-container"]}>
|
<div className={styles["code-container"]}>
|
||||||
@ -76,7 +71,7 @@ function MarketingTrialPayment() {
|
|||||||
<p className={styles["sale-description"]}>Save $10 every period</p>
|
<p className={styles["sale-description"]}>Save $10 every period</p>
|
||||||
<div className={styles.line} />
|
<div className={styles.line} />
|
||||||
<p className={styles["text-description"]}>
|
<p className={styles["text-description"]}>
|
||||||
You will be charged only <b>$0 for your 7-day trial.</b>{" "}
|
You will be charged only <b>${(products[0]?.trialPrice / 100).toFixed(2) || 0} for your 7-day trial.</b>{" "}
|
||||||
Subscription <b>renews automatically</b> until cancelled. You{" "}
|
Subscription <b>renews automatically</b> until cancelled. You{" "}
|
||||||
<b>can cancel at any time</b> before the end of the trial.
|
<b>can cancel at any time</b> before the end of the trial.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -1,246 +0,0 @@
|
|||||||
import EmailInput from "@/components/EmailEnterPage/EmailInput";
|
|
||||||
import styles from "./styles.module.css";
|
|
||||||
import { useCallback, 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 { useParams } from "react-router-dom";
|
|
||||||
import routes from "@/routes";
|
|
||||||
import PaymentForm from "./PaymentForm";
|
|
||||||
import { getPriceCentsToDollars } from "@/services/price";
|
|
||||||
import { useSinglePayment } from "@/hooks/payment/useSinglePayment";
|
|
||||||
|
|
||||||
function PaymentWithEmailPage() {
|
|
||||||
const { productId } = useParams();
|
|
||||||
const { t, i18n } = useTranslation();
|
|
||||||
// const tokenFromStore = useSelector(selectors.selectToken);
|
|
||||||
const { signUp, user: userFromStore, token: tokenFromStore } = useAuth();
|
|
||||||
const api = useApi();
|
|
||||||
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(productId !== "chat.aura");
|
|
||||||
const [isDisabled, setIsDisabled] = useState(true);
|
|
||||||
const [isAuth, setIsAuth] = useState(false);
|
|
||||||
const [apiError, setApiError] = useState<ApiError | null>(null);
|
|
||||||
const [error, setError] = useState<boolean>(false);
|
|
||||||
const returnUrl = `${window.location.protocol}//${
|
|
||||||
window.location.host
|
|
||||||
}${routes.client.paymentResult()}`;
|
|
||||||
|
|
||||||
const [isLoadingAuth, setIsLoadingAuth] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const {
|
|
||||||
product,
|
|
||||||
paymentIntent,
|
|
||||||
createSinglePayment,
|
|
||||||
isLoading: isLoadingSinglePayment,
|
|
||||||
error: errorSinglePayment,
|
|
||||||
} = useSinglePayment();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (
|
|
||||||
isValidName &&
|
|
||||||
isValidEmail &&
|
|
||||||
!(error || apiError || errorSinglePayment?.error)
|
|
||||||
) {
|
|
||||||
setIsDisabled(false);
|
|
||||||
} else {
|
|
||||||
setIsDisabled(true);
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
isValidEmail,
|
|
||||||
email,
|
|
||||||
isValidName,
|
|
||||||
name,
|
|
||||||
error,
|
|
||||||
apiError,
|
|
||||||
errorSinglePayment?.error,
|
|
||||||
]);
|
|
||||||
|
|
||||||
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 {
|
|
||||||
setIsLoadingAuth(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 });
|
|
||||||
setIsLoadingAuth(false);
|
|
||||||
return { user: userUpdated?.user, token };
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
if (error instanceof ApiError) {
|
|
||||||
setApiError(error as ApiError);
|
|
||||||
} else {
|
|
||||||
setError(true);
|
|
||||||
}
|
|
||||||
setIsLoadingAuth(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClick = async () => {
|
|
||||||
const authData = await authorization();
|
|
||||||
if (!authData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { user, token } = authData;
|
|
||||||
|
|
||||||
await createSinglePayment({
|
|
||||||
user,
|
|
||||||
token,
|
|
||||||
targetProductKey: productId || "",
|
|
||||||
returnUrl,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleAuthUser = useCallback(async () => {
|
|
||||||
if (!tokenFromStore.length || !userFromStore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await createSinglePayment({
|
|
||||||
user: userFromStore,
|
|
||||||
token: tokenFromStore,
|
|
||||||
targetProductKey: productId || "",
|
|
||||||
returnUrl,
|
|
||||||
});
|
|
||||||
}, [
|
|
||||||
createSinglePayment,
|
|
||||||
productId,
|
|
||||||
returnUrl,
|
|
||||||
tokenFromStore,
|
|
||||||
userFromStore,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
handleAuthUser();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`${styles.page} page`}>
|
|
||||||
{(isLoadingSinglePayment || isLoadingSinglePayment) && (
|
|
||||||
<Loader color={LoaderColor.Black} />
|
|
||||||
)}
|
|
||||||
{!isLoadingSinglePayment &&
|
|
||||||
!isLoadingAuth &&
|
|
||||||
paymentIntent &&
|
|
||||||
"paymentIntent" in paymentIntent &&
|
|
||||||
!!tokenFromStore.length && (
|
|
||||||
<>
|
|
||||||
<Title variant="h1" className={styles.title}>
|
|
||||||
{getPriceCentsToDollars(product?.price || 0)}$
|
|
||||||
</Title>
|
|
||||||
<PaymentForm
|
|
||||||
stripePublicKey={paymentIntent.paymentIntent.data.public_key}
|
|
||||||
clientSecret={paymentIntent.paymentIntent.data.client_secret}
|
|
||||||
returnUrl={`${returnUrl}?redirect_type=${product?.key}`}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{(!tokenFromStore || !paymentIntent) &&
|
|
||||||
// || (productId !== "chat.aura" && !name.length)
|
|
||||||
!isLoadingSinglePayment &&
|
|
||||||
!isLoadingAuth && (
|
|
||||||
<>
|
|
||||||
<NameInput
|
|
||||||
value={name}
|
|
||||||
placeholder="Your name"
|
|
||||||
onValid={handleValidName}
|
|
||||||
onInvalid={() => setIsValidName(productId !== "chat.aura")}
|
|
||||||
/>
|
|
||||||
<EmailInput
|
|
||||||
name="email"
|
|
||||||
value={email}
|
|
||||||
placeholder={t("your_email")}
|
|
||||||
onValid={handleValidEmail}
|
|
||||||
onInvalid={() => setIsValidEmail(false)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<MainButton
|
|
||||||
className={styles.button}
|
|
||||||
onClick={handleClick}
|
|
||||||
disabled={isDisabled}
|
|
||||||
>
|
|
||||||
{isLoadingSinglePayment && <Loader color={LoaderColor.White} />}
|
|
||||||
{!isLoadingSinglePayment &&
|
|
||||||
!(!apiError && !error && !isLoadingSinglePayment && isAuth) &&
|
|
||||||
t("_continue")}
|
|
||||||
{!apiError && !error && !isLoadingSinglePayment && isAuth && (
|
|
||||||
<img
|
|
||||||
className={styles["success-icon"]}
|
|
||||||
src="/SuccessIcon.png"
|
|
||||||
alt="Success Icon"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</MainButton>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{(error || apiError || errorSinglePayment?.error) && (
|
|
||||||
<Title variant="h3" style={{ color: "red", margin: 0 }}>
|
|
||||||
Something went wrong:{" "}
|
|
||||||
{errorSinglePayment?.error?.length && errorSinglePayment?.error}
|
|
||||||
</Title>
|
|
||||||
)}
|
|
||||||
{apiError && (
|
|
||||||
<ErrorText
|
|
||||||
size="medium"
|
|
||||||
isShown={Boolean(apiError)}
|
|
||||||
message={apiError ? extractErrorMessage(apiError) : null}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PaymentWithEmailPage;
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
.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%;
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { Elements } from "@stripe/react-stripe-js";
|
import { Elements } from "@stripe/react-stripe-js";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import CheckoutForm from "@/components/PaymentPage/methods/Stripe/CheckoutForm";
|
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
||||||
import SecurityPayments from "../../TrialPayment/components/SecurityPayments";
|
import SecurityPayments from "../../TrialPayment/components/SecurityPayments";
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import Title from "@/components/Title";
|
import Title from "@/components/Title";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import PaymentForm from "../PaymentWithEmailPage/PaymentForm";
|
import PaymentForm from "./PaymentForm";
|
||||||
import { getPriceCentsToDollars } from "@/services/price";
|
import { getPriceCentsToDollars } from "@/services/price";
|
||||||
import { useSinglePayment } from "@/hooks/payment/useSinglePayment";
|
import { useSinglePayment } from "@/hooks/payment/useSinglePayment";
|
||||||
import routes from "@/routes";
|
import routes from "@/routes";
|
||||||
|
|||||||
@ -4,13 +4,11 @@ import PaymentMethodsChoice from "../PaymentMethodsChoice";
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { EPaymentMethod, paymentMethods } from "@/data/paymentMethods";
|
import { EPaymentMethod, paymentMethods } from "@/data/paymentMethods";
|
||||||
import { Elements } from "@stripe/react-stripe-js";
|
import { Elements } from "@stripe/react-stripe-js";
|
||||||
import ApplePayButton from "@/components/StripePage/ApplePayButton";
|
import ApplePayButton from "@/components/PaymentPage/methods/ApplePayButton";
|
||||||
import CheckoutForm from "@/components/PaymentPage/methods/Stripe/CheckoutForm";
|
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
||||||
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { selectors } from "@/store";
|
import { selectors } from "@/store";
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import routes from "@/routes";
|
|
||||||
import Loader from "@/components/Loader";
|
import Loader from "@/components/Loader";
|
||||||
import SecurityPayments from "../SecurityPayments";
|
import SecurityPayments from "../SecurityPayments";
|
||||||
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
||||||
@ -21,6 +19,7 @@ interface IPaymentModalProps {
|
|||||||
activeProduct?: IPaywallProduct;
|
activeProduct?: IPaywallProduct;
|
||||||
noTrial?: boolean;
|
noTrial?: boolean;
|
||||||
returnUrl?: string;
|
returnUrl?: string;
|
||||||
|
placementKey?: EPlacementKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPrice = (product: IPaywallProduct | null) => {
|
const getPrice = (product: IPaywallProduct | null) => {
|
||||||
@ -34,13 +33,13 @@ function PaymentModal({
|
|||||||
activeProduct,
|
activeProduct,
|
||||||
noTrial,
|
noTrial,
|
||||||
returnUrl,
|
returnUrl,
|
||||||
|
placementKey = EPlacementKeys["aura.placement.main"],
|
||||||
}: IPaymentModalProps) {
|
}: IPaymentModalProps) {
|
||||||
const navigate = useNavigate();
|
|
||||||
const [stripePromise, setStripePromise] =
|
const [stripePromise, setStripePromise] =
|
||||||
useState<Promise<Stripe | null> | null>(null);
|
useState<Promise<Stripe | null> | null>(null);
|
||||||
|
|
||||||
const { products } = usePaywall({
|
const { products } = usePaywall({
|
||||||
placementKey: EPlacementKeys["aura.placement.main"],
|
placementKey,
|
||||||
});
|
});
|
||||||
const activeProductFromStore = useSelector(selectors.selectActiveProduct);
|
const activeProductFromStore = useSelector(selectors.selectActiveProduct);
|
||||||
|
|
||||||
@ -81,14 +80,8 @@ function PaymentModal({
|
|||||||
(async () => {
|
(async () => {
|
||||||
if (!products?.length || !publicKey) return;
|
if (!products?.length || !publicKey) return;
|
||||||
setStripePromise(loadStripe(publicKey));
|
setStripePromise(loadStripe(publicKey));
|
||||||
const isActiveProduct = products.find(
|
|
||||||
(product) => product._id === _activeProduct?._id
|
|
||||||
);
|
|
||||||
if (!_activeProduct || !isActiveProduct) {
|
|
||||||
navigate(routes.client.trialChoice());
|
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
}, [_activeProduct, navigate, products, publicKey]);
|
}, [products, publicKey]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -68,6 +68,16 @@ function TrialPaymentPage() {
|
|||||||
}
|
}
|
||||||
}, [dispatch, subPlan, products, activeProduct]);
|
}, [dispatch, subPlan, products, activeProduct]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!products.length) return;
|
||||||
|
const isActiveProduct = products.find(
|
||||||
|
(product) => product._id === activeProduct?._id
|
||||||
|
);
|
||||||
|
if (!activeProduct || !isActiveProduct) {
|
||||||
|
navigate(routes.client.trialChoice());
|
||||||
|
}
|
||||||
|
}, [activeProduct, navigate, products]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (["relationship", "married"].includes(flowChoice)) {
|
if (["relationship", "married"].includes(flowChoice)) {
|
||||||
setMarginTopTitle(460);
|
setMarginTopTitle(460);
|
||||||
|
|||||||
@ -38,7 +38,7 @@ function PaymentDiscountTable() {
|
|||||||
<p>Your cost per 14 days after trial:</p>
|
<p>Your cost per 14 days after trial:</p>
|
||||||
<div className={styles.side}>
|
<div className={styles.side}>
|
||||||
<span className={styles.discount}>$19</span>
|
<span className={styles.discount}>$19</span>
|
||||||
<strong>$9</strong>
|
<strong>${(activeProduct?.price || 0) / 100}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className={styles.save}>You save $30</p>
|
<p className={styles.save}>You save $30</p>
|
||||||
|
|||||||
@ -4,11 +4,35 @@ import MainButton from "@/components/MainButton";
|
|||||||
import PaymentDiscountTable from "./PaymentDiscountTable";
|
import PaymentDiscountTable from "./PaymentDiscountTable";
|
||||||
import Modal from "@/components/Modal";
|
import Modal from "@/components/Modal";
|
||||||
import PaymentModal from "../TrialPayment/components/PaymentModal";
|
import PaymentModal from "../TrialPayment/components/PaymentModal";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
||||||
|
import { EPlacementKeys } from "@/api/resources/Paywall";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { actions, selectors } from "@/store";
|
||||||
|
|
||||||
function TrialPaymentWithDiscount() {
|
function TrialPaymentWithDiscount() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const { products } = usePaywall({
|
||||||
|
placementKey: EPlacementKeys["aura.placement.secret.discount"],
|
||||||
|
});
|
||||||
|
const productFromStore = useSelector(selectors.selectActiveProduct);
|
||||||
|
|
||||||
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
|
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!products.length) return;
|
||||||
|
const activeProduct = products.find(
|
||||||
|
(p) => p.trialPrice === productFromStore?.trialPrice
|
||||||
|
);
|
||||||
|
if (!activeProduct) {
|
||||||
|
dispatch(actions.payment.update({ activeProduct: products[0] }));
|
||||||
|
}
|
||||||
|
if (activeProduct) {
|
||||||
|
dispatch(actions.payment.update({ activeProduct }));
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [dispatch, products]);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setIsOpenPaymentModal(false);
|
setIsOpenPaymentModal(false);
|
||||||
};
|
};
|
||||||
@ -16,7 +40,9 @@ function TrialPaymentWithDiscount() {
|
|||||||
return (
|
return (
|
||||||
<section className={`${styles.page} page`}>
|
<section className={`${styles.page} page`}>
|
||||||
<Modal open={isOpenPaymentModal} onClose={handleClose}>
|
<Modal open={isOpenPaymentModal} onClose={handleClose}>
|
||||||
<PaymentModal />
|
<PaymentModal
|
||||||
|
placementKey={EPlacementKeys["aura.placement.secret.discount"]}
|
||||||
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
<img
|
<img
|
||||||
className={styles["party-popper"]}
|
className={styles["party-popper"]}
|
||||||
@ -34,11 +60,13 @@ function TrialPaymentWithDiscount() {
|
|||||||
Start your 3-day trial
|
Start your 3-day trial
|
||||||
</MainButton>
|
</MainButton>
|
||||||
<p className={styles.policy}>
|
<p className={styles.policy}>
|
||||||
By continuing you agree that if you don't cancel prior to the end of the
|
By continuing you agree that if you don`t cancel prior to the end of the
|
||||||
3-days trial, you will automatically be charged $9 for the introductory
|
3-days trial, you will automatically be charged $
|
||||||
period of 14 days thereafter the standard rate of $9 every 14 days until
|
{(productFromStore?.price || 0) / 100} for the introductory period of 14
|
||||||
you cancel in settings. Learn more about cancellation and refund policy
|
days thereafter the standard rate of $
|
||||||
in Subscription terms.
|
{(productFromStore?.price || 0) / 100} every 14 days until you cancel in
|
||||||
|
settings. Learn more about cancellation and refund policy in
|
||||||
|
Subscription terms.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import routes from "@/routes";
|
|||||||
import { useApi } from "@/api";
|
import { useApi } from "@/api";
|
||||||
import { useAuth } from "@/auth";
|
import { useAuth } from "@/auth";
|
||||||
import HeaderLogo from "@/components/palmistry/header-logo/header-logo";
|
import HeaderLogo from "@/components/palmistry/header-logo/header-logo";
|
||||||
import CheckoutForm from "@/components/PaymentPage/methods/Stripe/CheckoutForm";
|
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
||||||
import { ResponseGet } from "@/api/resources/SinglePayment";
|
import { ResponseGet } from "@/api/resources/SinglePayment";
|
||||||
|
|
||||||
const currentProductKey = "skip.trial.subscription.aura";
|
const currentProductKey = "skip.trial.subscription.aura";
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import useTimer from "@/hooks/palmistry/use-timer";
|
|||||||
import HeaderLogo from "@/components/palmistry/header-logo/header-logo";
|
import HeaderLogo from "@/components/palmistry/header-logo/header-logo";
|
||||||
import PaymentModal from "@/components/pages/TrialPayment/components/PaymentModal";
|
import PaymentModal from "@/components/pages/TrialPayment/components/PaymentModal";
|
||||||
import { selectors } from "@/store";
|
import { selectors } from "@/store";
|
||||||
|
import { EPlacementKeys } from "@/api/resources/Paywall";
|
||||||
|
import { useSearchParams } from "react-router-dom";
|
||||||
|
|
||||||
const getFormattedPrice = (price: number) => {
|
const getFormattedPrice = (price: number) => {
|
||||||
return (price / 100).toFixed(2);
|
return (price / 100).toFixed(2);
|
||||||
@ -17,7 +19,12 @@ const getFormattedPrice = (price: number) => {
|
|||||||
export default function PaymentScreen() {
|
export default function PaymentScreen() {
|
||||||
const time = useTimer();
|
const time = useTimer();
|
||||||
const activeProductFromStore = useSelector(selectors.selectActiveProduct);
|
const activeProductFromStore = useSelector(selectors.selectActiveProduct);
|
||||||
const subscriptionStatus = useSelector(selectors.selectStatus);
|
const [searchParams] = useSearchParams();
|
||||||
|
const subscriptionStatus =
|
||||||
|
searchParams.get("redirect_status") === "succeeded"
|
||||||
|
? "subscribed"
|
||||||
|
: "lead";
|
||||||
|
// const subscriptionStatus = useSelector(selectors.selectStatus);
|
||||||
|
|
||||||
const steps = useSteps();
|
const steps = useSteps();
|
||||||
|
|
||||||
@ -247,7 +254,10 @@ export default function PaymentScreen() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{subscriptionStatus !== "subscribed" && (
|
{subscriptionStatus !== "subscribed" && (
|
||||||
<PaymentModal returnUrl={window.location.href} />
|
<PaymentModal
|
||||||
|
returnUrl={window.location.href}
|
||||||
|
placementKey={EPlacementKeys["aura.placement.palmistry.main"]}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{subscriptionStatus === "subscribed" && (
|
{subscriptionStatus === "subscribed" && (
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import routes from "@/routes";
|
|||||||
import HeaderLogo from "@/components/palmistry/header-logo/header-logo";
|
import HeaderLogo from "@/components/palmistry/header-logo/header-logo";
|
||||||
import { useApi } from "@/api";
|
import { useApi } from "@/api";
|
||||||
import { useAuth } from "@/auth";
|
import { useAuth } from "@/auth";
|
||||||
import CheckoutForm from "@/components/PaymentPage/methods/Stripe/CheckoutForm";
|
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
||||||
import { ResponseGet } from "@/api/resources/SinglePayment";
|
import { ResponseGet } from "@/api/resources/SinglePayment";
|
||||||
|
|
||||||
const currentProductKey = "premium.bundle.aura";
|
const currentProductKey = "premium.bundle.aura";
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export default function StepSubscriptionPlan() {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const activeProductFromStore = useSelector(selectors.selectActiveProduct);
|
const activeProductFromStore = useSelector(selectors.selectActiveProduct);
|
||||||
const { products } = usePaywall({
|
const { products } = usePaywall({
|
||||||
placementKey: EPlacementKeys["aura.placement.main"],
|
placementKey: EPlacementKeys["aura.placement.palmistry.main"],
|
||||||
});
|
});
|
||||||
|
|
||||||
const storedEmail = steps.getStoredValue(Step.Email);
|
const storedEmail = steps.getStoredValue(Step.Email);
|
||||||
@ -35,23 +35,16 @@ export default function StepSubscriptionPlan() {
|
|||||||
}
|
}
|
||||||
}, [activeProductFromStore]);
|
}, [activeProductFromStore]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (product) {
|
|
||||||
const targetProduct = products.find(
|
|
||||||
(_product) => _product._id === product
|
|
||||||
);
|
|
||||||
|
|
||||||
if (targetProduct) {
|
|
||||||
dispatch(actions.payment.update({ activeProduct: targetProduct }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [dispatch, product, products]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setEmail(storedEmail || "");
|
setEmail(storedEmail || "");
|
||||||
}, [storedEmail]);
|
}, [storedEmail]);
|
||||||
|
|
||||||
const onNext = () => {
|
const onNext = () => {
|
||||||
|
const targetProduct = products.find((_product) => _product._id === product);
|
||||||
|
|
||||||
|
if (targetProduct) {
|
||||||
|
dispatch(actions.payment.update({ activeProduct: targetProduct }));
|
||||||
|
}
|
||||||
steps.saveCurrent(product);
|
steps.saveCurrent(product);
|
||||||
steps.goNext();
|
steps.goNext();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,6 +15,8 @@ type Props = {
|
|||||||
onOpenModal: (isOpen: boolean) => void;
|
onOpenModal: (isOpen: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isProduction = import.meta.env.MODE === "production";
|
||||||
|
|
||||||
export default function StepUpload(props: Props) {
|
export default function StepUpload(props: Props) {
|
||||||
const steps = useSteps();
|
const steps = useSteps();
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
@ -606,7 +608,11 @@ export default function StepUpload(props: Props) {
|
|||||||
className="palmistry-container__take-palm-button"
|
className="palmistry-container__take-palm-button"
|
||||||
disabled={isUpladProcessing}
|
disabled={isUpladProcessing}
|
||||||
active={!isUpladProcessing}
|
active={!isUpladProcessing}
|
||||||
onClick={() => setPalmCameraModalIsOpen(true)}
|
onClick={() =>
|
||||||
|
isProduction
|
||||||
|
? setPalmCameraModalIsOpen(true)
|
||||||
|
: setUploadMenuModalIsOpen(true)
|
||||||
|
}
|
||||||
isProcessing={isUpladProcessing}
|
isProcessing={isUpladProcessing}
|
||||||
>
|
>
|
||||||
{(isUpladProcessing && "Loading photo") || "Take a picture now"}
|
{(isUpladProcessing && "Loading photo") || "Take a picture now"}
|
||||||
|
|||||||
@ -242,5 +242,208 @@ export const defaultPaywalls: { [key in EPlacementKeys]: IPaywall } = {
|
|||||||
"_id": "664542bbfe0a8eb4ee0b4f2e"
|
"_id": "664542bbfe0a8eb4ee0b4f2e"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"aura.placement.email.marketing": {
|
||||||
|
"_id": "66565b15e4ad13456f7d04f2",
|
||||||
|
"key": "aura.paywall.email.marketing",
|
||||||
|
"name": "Special Offer!",
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"_id": "66565aa8e4ad13456f7d02a6",
|
||||||
|
"key": "compatibility.pdf.trial.5",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4",
|
||||||
|
"name": "Сompatibility AURA | Trial $0.50",
|
||||||
|
"description": "Description",
|
||||||
|
"price": 1900,
|
||||||
|
"discountPrice": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 50,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"trialPriceId": "price_1PG1vKIlX4lgwUxrVhBf6eIq",
|
||||||
|
"type": "subscription"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"key": "text.old.price",
|
||||||
|
"value": "up to $13.67",
|
||||||
|
"_id": "66565b15e4ad13456f7d04f3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"aura.placement.secret.discount": {
|
||||||
|
"_id": "6658973fef0d180993cdbcc1",
|
||||||
|
"key": "aura.paywall.secret.discount",
|
||||||
|
"name": "Secret Discount",
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"_id": "66589439ef0d180993cdb72f",
|
||||||
|
"key": "compatibility.secret.discount.trial.0",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"priceId": "price_1PMAREIlX4lgwUxrmvtHWth1",
|
||||||
|
"name": "Сompatibility AURA Secret Discount | Trial $0.99",
|
||||||
|
"description": "Description",
|
||||||
|
"price": 900,
|
||||||
|
"discountPrice": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 99,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"trialPriceId": "price_1PFiSkIlX4lgwUxrVel0l445",
|
||||||
|
"type": "subscription"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "6658946cef0d180993cdb79f",
|
||||||
|
"key": "compatibility.secret.discount.trial.1",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"priceId": "price_1PMAREIlX4lgwUxrmvtHWth1",
|
||||||
|
"name": "Сompatibility AURA Secret Discount | Trial $5.00",
|
||||||
|
"description": "Description",
|
||||||
|
"price": 900,
|
||||||
|
"discountPrice": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 500,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"trialPriceId": "price_1PFyASIlX4lgwUxriLtzsk05",
|
||||||
|
"type": "subscription"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "66589544ef0d180993cdb7dc",
|
||||||
|
"key": "compatibility.secret.discount.trial.2",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"priceId": "price_1PMAREIlX4lgwUxrmvtHWth1",
|
||||||
|
"name": "Сompatibility AURA Secret Discount | Trial $9.00",
|
||||||
|
"description": "Description",
|
||||||
|
"price": 900,
|
||||||
|
"discountPrice": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 900,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"trialPriceId": "price_1PFyAuIlX4lgwUxr4fFoauCV",
|
||||||
|
"type": "subscription"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "66589591ef0d180993cdb88e",
|
||||||
|
"key": "compatibility.secret.discount.trial.3",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"priceId": "price_1PMAREIlX4lgwUxrmvtHWth1",
|
||||||
|
"name": "Сompatibility AURA Secret Discount | Trial $13.76",
|
||||||
|
"description": "Description",
|
||||||
|
"price": 900,
|
||||||
|
"discountPrice": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 1376,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"trialPriceId": "price_1PFyBQIlX4lgwUxrMnEUkV73",
|
||||||
|
"type": "subscription"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": []
|
||||||
|
},
|
||||||
|
"aura.placement.palmistry.main": {
|
||||||
|
"_id": "66565a0ee4ad13456f7d0079",
|
||||||
|
"key": "aura.paywall.palmistry.main",
|
||||||
|
"name": "paywall without free trial",
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"_id": "65ff043dfc0fcfc4be550035",
|
||||||
|
"key": "compatibility.pdf.trial.0",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"name": "Сompatibility AURA | Trial $0.99",
|
||||||
|
"priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4",
|
||||||
|
"type": "subscription",
|
||||||
|
"description": "Description",
|
||||||
|
"discountPrice": null,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"price": 1900,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 99,
|
||||||
|
"trialPriceId": "price_1PFiSkIlX4lgwUxrVel0l445"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "66420b6e859ff1199d3a6e88",
|
||||||
|
"key": "compatibility.pdf.trial.1",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"name": "Сompatibility AURA | Trial $5.00",
|
||||||
|
"priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4",
|
||||||
|
"type": "subscription",
|
||||||
|
"description": "Description",
|
||||||
|
"discountPrice": null,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"price": 1900,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 500,
|
||||||
|
"trialPriceId": "price_1PFyASIlX4lgwUxriLtzsk05"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "66420be1859ff1199d3a6e89",
|
||||||
|
"key": "compatibility.pdf.trial.2",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"name": "Сompatibility AURA | Trial $9.00",
|
||||||
|
"priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4",
|
||||||
|
"type": "subscription",
|
||||||
|
"description": "Description",
|
||||||
|
"discountPrice": null,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"price": 1900,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 900,
|
||||||
|
"trialPriceId": "price_1PFyAuIlX4lgwUxr4fFoauCV"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "66420c1c859ff1199d3a6e8a",
|
||||||
|
"key": "compatibility.pdf.trial.3",
|
||||||
|
"productId": "prod_PnStTEBzrPLgvL",
|
||||||
|
"name": "Сompatibility AURA | Trial $13.76",
|
||||||
|
"priceId": "price_1PG2RSIlX4lgwUxrDfU2BDS4",
|
||||||
|
"type": "subscription",
|
||||||
|
"description": "Description",
|
||||||
|
"discountPrice": null,
|
||||||
|
"discountPriceId": null,
|
||||||
|
"isDiscount": false,
|
||||||
|
"isFreeTrial": false,
|
||||||
|
"isTrial": true,
|
||||||
|
"price": 1900,
|
||||||
|
"trialDuration": 3,
|
||||||
|
"trialPrice": 1376,
|
||||||
|
"trialPriceId": "price_1PFyBQIlX4lgwUxrMnEUkV73"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"key": "text.0",
|
||||||
|
"value": "We've helped millions of people to\nreveal the destiny of their love life\nand what the future holds for them\nand their families.",
|
||||||
|
"_id": "664542bbfe0a8eb4ee0b4f27"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "text.1",
|
||||||
|
"value": "It costs us $13.21 to compensate our AURA\nemployees for the trial, but please choose the\namount you are comfortable with.",
|
||||||
|
"_id": "664542bbfe0a8eb4ee0b4f29"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,7 +57,6 @@ const routes = {
|
|||||||
paymentResult: () => [host, "payment", "result"].join("/"),
|
paymentResult: () => [host, "payment", "result"].join("/"),
|
||||||
paymentSuccess: () => [host, "payment", "success"].join("/"),
|
paymentSuccess: () => [host, "payment", "success"].join("/"),
|
||||||
paymentFail: () => [host, "payment", "fail"].join("/"),
|
paymentFail: () => [host, "payment", "fail"].join("/"),
|
||||||
paymentStripe: () => [host, "payment", "stripe"].join("/"),
|
|
||||||
wallpaper: () => [host, "wallpaper"].join("/"),
|
wallpaper: () => [host, "wallpaper"].join("/"),
|
||||||
static: () => [host, "static", ":typeId"].join("/"),
|
static: () => [host, "static", ":typeId"].join("/"),
|
||||||
legal: (type: string) => [host, "static", type].join("/"),
|
legal: (type: string) => [host, "static", type].join("/"),
|
||||||
@ -349,7 +348,6 @@ export const withoutFooterRoutes = [
|
|||||||
routes.client.paymentResult(),
|
routes.client.paymentResult(),
|
||||||
routes.client.paymentSuccess(),
|
routes.client.paymentSuccess(),
|
||||||
routes.client.paymentFail(),
|
routes.client.paymentFail(),
|
||||||
routes.client.paymentStripe(),
|
|
||||||
routes.client.magicBall(),
|
routes.client.magicBall(),
|
||||||
routes.client.horoscopeBestiesResult(),
|
routes.client.horoscopeBestiesResult(),
|
||||||
routes.client.predictionMoonResult(),
|
routes.client.predictionMoonResult(),
|
||||||
|
|||||||
@ -19,9 +19,15 @@ type IPayloadUpdatePaywall = {
|
|||||||
const initialState: TPaywalls = {
|
const initialState: TPaywalls = {
|
||||||
"aura.placement.main": null,
|
"aura.placement.main": null,
|
||||||
"aura.placement.redesign.main": null,
|
"aura.placement.redesign.main": null,
|
||||||
|
"aura.placement.email.marketing": null,
|
||||||
|
"aura.placement.secret.discount": null,
|
||||||
|
"aura.placement.palmistry.main": null,
|
||||||
isMustUpdate: {
|
isMustUpdate: {
|
||||||
"aura.placement.main": true,
|
"aura.placement.main": true,
|
||||||
"aura.placement.redesign.main": true,
|
"aura.placement.redesign.main": true,
|
||||||
|
"aura.placement.email.marketing": true,
|
||||||
|
"aura.placement.secret.discount": true,
|
||||||
|
"aura.placement.palmistry.main": true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user