AW-130-actual-price

actual price
This commit is contained in:
gofnnp 2024-07-02 05:43:44 +04:00
parent a2f9c8a913
commit 89ef6d66dc
10 changed files with 101 additions and 63 deletions

View File

@ -149,7 +149,10 @@ function PaymentModal({
<> <>
<p className={styles["sub-plan-description"]}> <p className={styles["sub-plan-description"]}>
You will be charged only{" "} You will be charged only{" "}
<b>${getPrice(_activeProduct)} for your 3-day trial.</b> <b>
${getPrice(_activeProduct)} for your{" "}
{_activeProduct.trialDuration}-day trial.
</b>
</p> </p>
<p className={styles["sub-plan-description"]}> <p className={styles["sub-plan-description"]}>
We`ll <b>email you a reminder</b> before your trial period We`ll <b>email you a reminder</b> before your trial period

View File

@ -3,9 +3,33 @@ import styles from "./styles.module.css";
import MainButton from "@/components/MainButton"; import MainButton from "@/components/MainButton";
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";
import { actions, selectors } from "@/store";
import { useDispatch, useSelector } from "react-redux";
import { useEffect } from "react";
function AdditionalDiscount() { function AdditionalDiscount() {
const navigate = useNavigate(); const navigate = useNavigate();
const dispatch = useDispatch();
const activeProduct = useSelector(selectors.selectActiveProduct);
const { products, getText } = usePaywall({
placementKey: EPlacementKeys["aura.placement.secret.discount"],
});
useEffect(() => {
if (!products.length) return;
const _activeProduct = products.find(
(p) => p.trialPrice === activeProduct?.trialPrice
);
if (!_activeProduct) {
dispatch(actions.payment.update({ activeProduct: products[0] }));
}
if (_activeProduct) {
dispatch(actions.payment.update({ activeProduct: _activeProduct }));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dispatch, products]);
const handleNext = () => { const handleNext = () => {
navigate(routes.client.trialPaymentWithDiscountV1()); navigate(routes.client.trialPaymentWithDiscountV1());
@ -14,21 +38,25 @@ function AdditionalDiscount() {
return ( return (
<section className={`${styles.page} page`}> <section className={`${styles.page} page`}>
<Title variant="h2" className={styles.title}> <Title variant="h2" className={styles.title}>
Save 65% off! Save {(getText("discount.1") as string).replace("-", "")} off!
</Title> </Title>
<img src="/friends.webp" alt="Friends" style={{ minHeight: "180px" }} /> <img src="/friends.webp" alt="Friends" style={{ minHeight: "180px" }} />
<div className={styles["discount-point"]}> <div className={styles["discount-point"]}>
<img src="/fire.webp" alt="Fire" /> <img src="/fire.webp" alt="Fire" />
<p className={styles["discount-point-description"]}> <p className={styles["discount-point-description"]}>
65% off on your personalized plan {(getText("discount.1") as string).replace("-", "")} off on your
personalized plan
</p> </p>
</div> </div>
<div className={styles["discount-point"]}> <div className={styles["discount-point"]}>
<img src="/present.webp" alt="Present" /> <img src="/present.webp" alt="Present" />
<p className={styles["discount-point-description"]}>7-day trial</p> <p className={styles["discount-point-description"]}>
{activeProduct?.trialDuration}-day trial
</p>
</div> </div>
<p className={styles["discount-description"]}> <p className={styles["discount-description"]}>
<span>$9</span> instead of $19 <span>${(activeProduct?.price || 0) / 100}</span> instead of $
{Number(getText("full.price")) / 100}
</p> </p>
<MainButton className={styles.button} onClick={handleNext}> <MainButton className={styles.button} onClick={handleNext}>
Get secret discount! Get secret discount!

View File

@ -21,6 +21,7 @@ function TrialChoicePage() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate(); const navigate = useNavigate();
const selectedPrice = useSelector(selectors.selectSelectedPrice); const selectedPrice = useSelector(selectors.selectSelectedPrice);
const activeProduct = useSelector(selectors.selectActiveProduct);
const homeConfig = useSelector(selectors.selectHome); const homeConfig = useSelector(selectors.selectHome);
const email = useSelector(selectors.selectEmail); const email = useSelector(selectors.selectEmail);
const [isDisabled, setIsDisabled] = useState(true); const [isDisabled, setIsDisabled] = useState(true);
@ -30,6 +31,7 @@ function TrialChoicePage() {
const { products, isLoading, getText } = usePaywall({ const { products, isLoading, getText } = usePaywall({
placementKey: EPlacementKeys["aura.placement.redesign.main"], placementKey: EPlacementKeys["aura.placement.redesign.main"],
}); });
const { videoUrl } = useSelector(selectors.selectPersonalVideo); const { videoUrl } = useSelector(selectors.selectPersonalVideo);
useEffect(() => { useEffect(() => {
@ -103,6 +105,10 @@ function TrialChoicePage() {
<p className={`${styles.text} ${styles.bold} ${styles.blue}`}> <p className={`${styles.text} ${styles.bold} ${styles.blue}`}>
{getText("text.2", { {getText("text.2", {
color: "#1C38EA", color: "#1C38EA",
replacement: {
target: "${trialDuration}",
replacement: activeProduct?.trialDuration.toString() || "3",
},
})} })}
</p> </p>
<div className={styles["price-container"]}> <div className={styles["price-container"]}>

View File

@ -4,11 +4,13 @@ import CustomButton from "../CustomButton";
import GuardPayments from "../GuardPayments"; import GuardPayments from "../GuardPayments";
import { useState } from "react"; import { useState } from "react";
import FullScreenModal from "@/components/FullScreenModal"; import FullScreenModal from "@/components/FullScreenModal";
import { IPaywallProduct } from "@/api/resources/Paywall"; import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
import { usePaywall } from "@/hooks/paywall/usePaywall";
interface IPaymentTableProps { interface IPaymentTableProps {
product: IPaywallProduct; product: IPaywallProduct;
gender: string; gender: string;
placementKey: EPlacementKeys;
buttonClick: () => void; buttonClick: () => void;
} }
@ -16,7 +18,15 @@ const getPrice = (product: IPaywallProduct) => {
return (product.trialPrice || 0) / 100; return (product.trialPrice || 0) / 100;
}; };
function PaymentTable({ gender, product, buttonClick }: IPaymentTableProps) { function PaymentTable({
gender,
product,
placementKey,
buttonClick,
}: IPaymentTableProps) {
const { getText } = usePaywall({
placementKey,
});
const [isOpenPrivacyModal, setIsOpenPrivacyModal] = useState<boolean>(false); const [isOpenPrivacyModal, setIsOpenPrivacyModal] = useState<boolean>(false);
const handleSubscriptionPolicyClick = (event: React.MouseEvent) => { const handleSubscriptionPolicyClick = (event: React.MouseEvent) => {
event.preventDefault(); event.preventDefault();
@ -63,8 +73,10 @@ function PaymentTable({ gender, product, buttonClick }: IPaymentTableProps) {
<div className={styles["table-element"]}> <div className={styles["table-element"]}>
<p>Your cost per 2 weeks after trial</p> <p>Your cost per 2 weeks after trial</p>
<div> <div>
<span className={styles.discount}>$65</span> <span className={styles.discount}>
<span>${product.trialPrice / 100}</span> ${Number(getText("full.price")) / 100}
</span>
<span>${product.price / 100}</span>
</div> </div>
</div> </div>
</div> </div>
@ -75,10 +87,11 @@ function PaymentTable({ gender, product, buttonClick }: IPaymentTableProps) {
<GuardPayments /> <GuardPayments />
<p className={styles.policy}> <p className={styles.policy}>
You are enrolling in 2 weeks subscription. By continuing you agree that You are enrolling in 2 weeks subscription. By continuing you agree that
if you don't cancel prior to the end of the 3-day trial for the $ if you don't cancel prior to the end of the {product.trialDuration}-day
{getPrice(product)} you will automatically be charged $19 every 2 weeks trial for the ${getPrice(product)} you will automatically be charged $
until you cancel in settings. Learn more about cancellation and refund {product.price / 100}{" "}
policy in{" "} every 2 weeks until you cancel in settings. Learn more about
cancellation and refund policy in{" "}
<a onClick={handleSubscriptionPolicyClick}>Subscription policy</a> <a onClick={handleSubscriptionPolicyClick}>Subscription policy</a>
</p> </p>
</> </>

View File

@ -163,6 +163,7 @@ function TrialPaymentPage() {
gender={gender} gender={gender}
product={activeProduct} product={activeProduct}
buttonClick={openStripeModal} buttonClick={openStripeModal}
placementKey={EPlacementKeys["aura.placement.redesign.main"]}
/> />
<YourReading <YourReading
gender={gender} gender={gender}
@ -180,6 +181,7 @@ function TrialPaymentPage() {
gender={gender} gender={gender}
product={activeProduct} product={activeProduct}
buttonClick={openStripeModal} buttonClick={openStripeModal}
placementKey={EPlacementKeys["aura.placement.redesign.main"]}
/> />
</section> </section>
); );

View File

@ -2,7 +2,8 @@ import Title from "@/components/Title";
import styles from "./styles.module.css"; import styles from "./styles.module.css";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { selectors } from "@/store"; import { selectors } from "@/store";
import { IPaywallProduct } from "@/api/resources/Paywall"; import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
import { usePaywall } from "@/hooks/paywall/usePaywall";
const getPrice = (product: IPaywallProduct | null) => { const getPrice = (product: IPaywallProduct | null) => {
if (!product) { if (!product) {
@ -12,6 +13,9 @@ const getPrice = (product: IPaywallProduct | null) => {
}; };
function PaymentDiscountTable() { function PaymentDiscountTable() {
const { getText } = usePaywall({
placementKey: EPlacementKeys["aura.placement.secret.discount"],
});
const activeProduct = useSelector(selectors.selectActiveProduct); const activeProduct = useSelector(selectors.selectActiveProduct);
return ( return (
@ -30,14 +34,16 @@ function PaymentDiscountTable() {
<p className={styles.description}>Secret discount applied!</p> <p className={styles.description}>Secret discount applied!</p>
</div> </div>
<div className={styles.side}> <div className={styles.side}>
<span className={styles.discount}>-30%</span> <span className={styles.discount}>{getText("discount.0")}</span>
<strong>-50%</strong> <strong>{getText("discount.1")}</strong>
</div> </div>
</div> </div>
<div className={styles["cost-container"]}> <div className={styles["cost-container"]}>
<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}>
${Number(getText("full.price")) / 100}
</span>
<strong>${(activeProduct?.price || 0) / 100}</strong> <strong>${(activeProduct?.price || 0) / 100}</strong>
</div> </div>
</div> </div>

View File

@ -3,39 +3,20 @@ import styles from "./styles.module.css";
import MainButton from "@/components/MainButton"; import MainButton from "@/components/MainButton";
import PaymentDiscountTable from "./PaymentDiscountTable"; import PaymentDiscountTable from "./PaymentDiscountTable";
import Modal from "@/components/Modal"; import Modal from "@/components/Modal";
import { useEffect, useState } from "react"; import { useState } from "react";
import { actions, selectors } from "@/store"; import { selectors } from "@/store";
import { useDispatch, useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { usePaywall } from "@/hooks/paywall/usePaywall";
import { EPlacementKeys } from "@/api/resources/Paywall"; import { EPlacementKeys } from "@/api/resources/Paywall";
import PaymentModal from "@/components/PaymentModal"; import PaymentModal from "@/components/PaymentModal";
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 activeProduct = useSelector(selectors.selectActiveProduct);
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} type="hidden"> <Modal open={isOpenPaymentModal} onClose={handleClose} type="hidden">
@ -56,14 +37,14 @@ function TrialPaymentWithDiscount() {
className={styles.button} className={styles.button}
onClick={() => setIsOpenPaymentModal(true)} onClick={() => setIsOpenPaymentModal(true)}
> >
Start your 3-day trial Start your {activeProduct?.trialDuration}-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 $ {activeProduct?.trialDuration}-days trial, you will automatically be
{(productFromStore?.price || 0) / 100} for the introductory period of 14 charged ${(activeProduct?.price || 0) / 100} for the introductory
days thereafter the standard rate of $ period of 14 days thereafter the standard rate of $
{(productFromStore?.price || 0) / 100} every 14 days until you cancel in {(activeProduct?.price || 0) / 100} every 14 days until you cancel in
settings. Learn more about cancellation and refund policy in settings. Learn more about cancellation and refund policy in
Subscription terms. Subscription terms.
</p> </p>

View File

@ -7,14 +7,15 @@ import PaymentModal from "@/components/PaymentModal";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { usePaywall } from "@/hooks/paywall/usePaywall"; import { usePaywall } from "@/hooks/paywall/usePaywall";
import { EPlacementKeys } from "@/api/resources/Paywall"; import { EPlacementKeys } from "@/api/resources/Paywall";
import { useDispatch } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { actions } from "@/store"; import { actions, selectors } from "@/store";
function MarketingTrialPayment() { function MarketingTrialPayment() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false); const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
const activeProduct = useSelector(selectors.selectActiveProduct);
const { products } = usePaywall({ const { products, getText } = usePaywall({
placementKey: EPlacementKeys["aura.placement.email.marketing"], placementKey: EPlacementKeys["aura.placement.email.marketing"],
}); });
@ -48,7 +49,7 @@ function MarketingTrialPayment() {
<div className={styles.wrapper}> <div className={styles.wrapper}>
<div className={styles.banner}>Special Offer</div> <div className={styles.banner}>Special Offer</div>
<Title variant="h2" className={styles.title}> <Title variant="h2" className={styles.title}>
Start your 7-day trial Start your {activeProduct?.trialDuration}-day trial
</Title> </Title>
<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"]}>
@ -67,16 +68,16 @@ function MarketingTrialPayment() {
Your cost per 2 weeks after trial Your cost per 2 weeks after trial
</p> </p>
<p className={styles.value}> <p className={styles.value}>
<span className={styles["old-price"]}>$29</span> <span className={styles["old-price"]}>${Number(getText("full.price")) / 100}</span>
<span className={styles["new-price"]}>$19</span> <span className={styles["new-price"]}>${(activeProduct?.price || 0) / 100}</span>
</p> </p>
</div> </div>
<p className={styles["sale-description"]}>Save $10 every period</p> <p className={styles["sale-description"]}>{getText("text.save")}</p>
<div className={styles.line} /> <div className={styles.line} />
<p className={styles["text-description"]}> <p className={styles["text-description"]}>
You will be charged only{" "} You will be charged only{" "}
<b> <b>
${(products[0]?.trialPrice / 100).toFixed(2) || 0} for your 7-day ${(products[0]?.trialPrice / 100).toFixed(2) || 0} for your {activeProduct?.trialDuration}-day
trial. trial.
</b>{" "} </b>{" "}
Subscription <b>renews automatically</b> until cancelled. You{" "} Subscription <b>renews automatically</b> until cancelled. You{" "}
@ -87,8 +88,8 @@ function MarketingTrialPayment() {
<p>Get access</p> <p>Get access</p>
</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 By continuing you agree that if you don`t cancel prior to the end of
the 3-days trial, you will automatically be charged $19 every 2 the {activeProduct?.trialDuration}-days trial, you will automatically be charged ${(activeProduct?.price || 0) / 100} every 2
weeks until you cancel in settings. Learn more about cancellation weeks until you cancel in settings. Learn more about cancellation
and refund policy in Subscription terms and refund policy in Subscription terms
</p> </p>

View File

@ -125,7 +125,7 @@ export default function PaymentScreen() {
</div> </div>
</div> </div>
<h1 className="payment-screen__title">Start your 7-day trial</h1> <h1 className="payment-screen__title">Start your {activeProductFromStore?.trialDuration}-day trial</h1>
<div className="payment-screen__total-today"> <div className="payment-screen__total-today">
<span>Total today</span> <span>Total today</span>
@ -163,7 +163,7 @@ export default function PaymentScreen() {
<div className="payment-screen__prices"> <div className="payment-screen__prices">
<span> <span>
You will be charged only{" "} You will be charged only{" "}
<b>${getFormattedPrice(trialPrice)} for your 7-day trial.</b> <b>${getFormattedPrice(trialPrice)} for your {activeProductFromStore?.trialDuration}-day trial.</b>
</span> </span>
<span> <span>

View File

@ -83,14 +83,12 @@ export function usePaywall({ placementKey }: IUsePaywallProps) {
}, [getPaywallByPlacementKey, placementKey, isMustUpdate]); }, [getPaywallByPlacementKey, placementKey, isMustUpdate]);
const getText = useCallback( const getText = useCallback(
( (key: string, options?: IGetTextProps) => {
key: string, const {
{
replacementSelector = "span", replacementSelector = "span",
color = "inherit", color = "inherit",
replacement, replacement,
}: IGetTextProps } = options || {};
) => {
const property = properties.find((property) => property.key === key); const property = properties.find((property) => property.key === key);
if (!property) return ""; if (!property) return "";
const text = property.value; const text = property.value;