Merge branch 'develop' into 'main'
develop See merge request witapp/aura-webapp!505
This commit is contained in:
commit
aaedc42362
20
index.html
20
index.html
@ -35,11 +35,6 @@
|
|||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- NMI CollectJS -->
|
|
||||||
<script src="https://hms.transactiongateway.com/token/Collect.js" data-tokenization-key="MMJJDe-ESZqfT-7P4f8z-mwD8N4"
|
|
||||||
data-variant="inline"></script>
|
|
||||||
<!-- <script src="https://hms.transactiongateway.com/js/v1/Gateway.js"></script> -->
|
|
||||||
<!-- NMI CollectJS -->
|
|
||||||
|
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
@ -184,6 +179,21 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<!-- Load NMI Collect.js -->
|
||||||
|
<script type="module">
|
||||||
|
import { createApi } from "/src/api/api.ts"
|
||||||
|
const api = createApi();
|
||||||
|
api.getPaymentConfig(null).then((paymentConfig) => {
|
||||||
|
const nmiPublicKey = paymentConfig?.data?.nmi?.publicKey;
|
||||||
|
|
||||||
|
const scriptElement = document.createElement("script");
|
||||||
|
scriptElement.src = "https://hms.transactiongateway.com/token/Collect.js";
|
||||||
|
scriptElement.setAttribute("data-tokenization-key", nmiPublicKey);
|
||||||
|
scriptElement.setAttribute("data-variant", "inline");
|
||||||
|
document.head.appendChild(scriptElement);
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<!-- Load NMI Collect.js -->
|
||||||
<!-- Klaviyo Metric -->
|
<!-- Klaviyo Metric -->
|
||||||
<script type="module">
|
<script type="module">
|
||||||
const klaviyoKeys = {
|
const klaviyoKeys = {
|
||||||
|
|||||||
@ -91,6 +91,7 @@ const api = {
|
|||||||
getPaywallByPlacementKey: createMethod<Paywall.PayloadGet, Paywall.ResponseGet>(Paywall.createRequestGet),
|
getPaywallByPlacementKey: createMethod<Paywall.PayloadGet, Paywall.ResponseGet>(Paywall.createRequestGet),
|
||||||
// Payment
|
// Payment
|
||||||
makePayment: createMethod<Payment.PayloadPost, Payment.ResponsePost>(Payment.createRequestPost),
|
makePayment: createMethod<Payment.PayloadPost, Payment.ResponsePost>(Payment.createRequestPost),
|
||||||
|
getPaymentConfig: createMethod<null, Payment.IPaymentConfigResponse>(Payment.getConfigRequest),
|
||||||
// User videos
|
// User videos
|
||||||
getUserVideos: createMethod<UserVideos.PayloadGet, UserVideos.ResponseGet>(UserVideos.createRequest),
|
getUserVideos: createMethod<UserVideos.PayloadGet, UserVideos.ResponseGet>(UserVideos.createRequest),
|
||||||
// User PDF
|
// User PDF
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import routes from "@/routes";
|
import routes from "@/routes";
|
||||||
import { getAuthHeaders } from "../utils";
|
import { getAuthHeaders, getBaseHeaders } from "../utils";
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
token: string;
|
token: string;
|
||||||
@ -50,3 +50,17 @@ export const createRequestPost = ({ token, productId, placementId, paywallId, pa
|
|||||||
});
|
});
|
||||||
return new Request(url, { method: "POST", headers: getAuthHeaders(token), body });
|
return new Request(url, { method: "POST", headers: getAuthHeaders(token), body });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface IPaymentConfigResponse {
|
||||||
|
status: "success" | string,
|
||||||
|
data: {
|
||||||
|
nmi: {
|
||||||
|
publicKey: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getConfigRequest = (): Request => {
|
||||||
|
const url = new URL(routes.server.getPaymentConfig());
|
||||||
|
return new Request(url, { method: "GET", headers: getBaseHeaders() });
|
||||||
|
};
|
||||||
|
|||||||
@ -14,22 +14,24 @@ import PointsList from "./components/PointsList";
|
|||||||
import OftenAsk from "./components/OftenAsk";
|
import OftenAsk from "./components/OftenAsk";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import WithPartnerInformation from "./components/WithPartnerInformation";
|
import WithPartnerInformation from "./components/WithPartnerInformation";
|
||||||
import Modal from "@/components/Modal";
|
|
||||||
import { trialPaymentPointsList } from "@/data/pointsLists";
|
import { trialPaymentPointsList } from "@/data/pointsLists";
|
||||||
import { trialPaymentReviews } from "@/data/reviews";
|
import { trialPaymentReviews } from "@/data/reviews";
|
||||||
import TrialPaymentHeader from "./components/Header";
|
import TrialPaymentHeader from "./components/Header";
|
||||||
import Header from "../../components/Header";
|
import Header from "../../components/Header";
|
||||||
import BackgroundTopBlob from "../../ui/BackgroundTopBlob";
|
import BackgroundTopBlob from "../../ui/BackgroundTopBlob";
|
||||||
import { useDynamicSize } from "@/hooks/useDynamicSize";
|
import { useDynamicSize } from "@/hooks/useDynamicSize";
|
||||||
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
import { EPlacementKeys } from "@/api/resources/Paywall";
|
||||||
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
||||||
import PaymentModal from "@/components/PaymentModal";
|
|
||||||
import metricService, {
|
import metricService, {
|
||||||
EGoals,
|
EGoals,
|
||||||
EMetrics,
|
EMetrics,
|
||||||
} from "@/services/metric/metricService";
|
} from "@/services/metric/metricService";
|
||||||
import { useTranslations } from "@/hooks/translations";
|
import { useTranslations } from "@/hooks/translations";
|
||||||
import { ELocalesPlacement } from "@/locales";
|
import { ELocalesPlacement } from "@/locales";
|
||||||
|
import { usePayment } from "@/hooks/payment/nmi/usePayment";
|
||||||
|
import Loader, { LoaderColor } from "@/components/Loader";
|
||||||
|
|
||||||
|
const placementKey = EPlacementKeys["aura.placement.redesign.main"]
|
||||||
|
|
||||||
function TrialPaymentPage() {
|
function TrialPaymentPage() {
|
||||||
const { translate } = useTranslations(ELocalesPlacement.V1);
|
const { translate } = useTranslations(ELocalesPlacement.V1);
|
||||||
@ -49,19 +51,38 @@ function TrialPaymentPage() {
|
|||||||
} = useSelector(selectors.selectQuestionnaire);
|
} = useSelector(selectors.selectQuestionnaire);
|
||||||
const partnerZodiacSign = getZodiacSignByDate(partnerBirthdate);
|
const partnerZodiacSign = getZodiacSignByDate(partnerBirthdate);
|
||||||
const { products } = usePaywall({
|
const { products } = usePaywall({
|
||||||
placementKey: EPlacementKeys["aura.placement.redesign.main"],
|
placementKey,
|
||||||
localesPlacement: ELocalesPlacement.V1,
|
localesPlacement: ELocalesPlacement.V1,
|
||||||
});
|
});
|
||||||
const activeProductFromStore = useSelector(selectors.selectActiveProduct);
|
const activeProduct = useSelector(selectors.selectActiveProduct);
|
||||||
const [activeProduct, setActiveProduct] = useState<IPaywallProduct | null>(
|
|
||||||
activeProductFromStore
|
|
||||||
);
|
|
||||||
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
|
|
||||||
const [singleOrWithPartner, setSingleOrWithPartner] = useState<
|
const [singleOrWithPartner, setSingleOrWithPartner] = useState<
|
||||||
"single" | "partner"
|
"single" | "partner"
|
||||||
>("single");
|
>("single");
|
||||||
const { subPlan } = useParams();
|
const { subPlan } = useParams();
|
||||||
|
|
||||||
|
const { isLoading, isModalClosed, error, isPaymentSuccess, showCreditCardForm } = usePayment({
|
||||||
|
placementKey,
|
||||||
|
activeProduct: activeProduct!
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isPaymentSuccess) {
|
||||||
|
return navigate(routes.client.paymentSuccess())
|
||||||
|
}
|
||||||
|
}, [isPaymentSuccess])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isModalClosed) {
|
||||||
|
return handleDiscount()
|
||||||
|
}
|
||||||
|
}, [isModalClosed])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (error?.length && error !== "Product not found") {
|
||||||
|
return navigate(routes.client.paymentFail())
|
||||||
|
}
|
||||||
|
}, [error])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
metricService.reachGoal(EGoals.AURA_TRIAL_PAYMENT_PAGE_VISIT, [
|
metricService.reachGoal(EGoals.AURA_TRIAL_PAYMENT_PAGE_VISIT, [
|
||||||
EMetrics.KLAVIYO,
|
EMetrics.KLAVIYO,
|
||||||
@ -79,11 +100,10 @@ function TrialPaymentPage() {
|
|||||||
) === subPlan
|
) === subPlan
|
||||||
);
|
);
|
||||||
if (targetProduct) {
|
if (targetProduct) {
|
||||||
setActiveProduct(targetProduct);
|
dispatch(actions.payment.update({ activeProduct: targetProduct }));
|
||||||
dispatch(actions.payment.update({ activeProduct }));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [dispatch, subPlan, products, activeProduct]);
|
}, [dispatch, subPlan, products]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!products.length) return;
|
if (!products.length) return;
|
||||||
@ -112,13 +132,12 @@ function TrialPaymentPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleDiscount = () => {
|
const handleDiscount = () => {
|
||||||
setIsOpenPaymentModal(false);
|
|
||||||
navigate(routes.client.additionalDiscountV1());
|
navigate(routes.client.additionalDiscountV1());
|
||||||
};
|
};
|
||||||
|
|
||||||
const openStripeModal = () => {
|
const openPaymentModal = () => {
|
||||||
metricService.reachGoal(EGoals.AURA_PAYMENT_METHODS_OPENED);
|
metricService.reachGoal(EGoals.AURA_PAYMENT_METHODS_OPENED);
|
||||||
setIsOpenPaymentModal(true);
|
showCreditCardForm()
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -129,16 +148,11 @@ function TrialPaymentPage() {
|
|||||||
backgroundColor: gender === "male" ? "#C1E5FF" : "#F7EBFF",
|
backgroundColor: gender === "male" ? "#C1E5FF" : "#F7EBFF",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Modal
|
{isLoading &&
|
||||||
containerClassName={styles.modal}
|
<div className={styles["loader-container"]}>
|
||||||
open={isOpenPaymentModal}
|
<Loader color={LoaderColor.White} />
|
||||||
onClose={handleDiscount}
|
</div>
|
||||||
type="hidden"
|
}
|
||||||
>
|
|
||||||
<PaymentModal
|
|
||||||
placementKey={EPlacementKeys["aura.placement.redesign.main"]}
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
<div className={styles["background-top-blob-container"]}>
|
<div className={styles["background-top-blob-container"]}>
|
||||||
<BackgroundTopBlob
|
<BackgroundTopBlob
|
||||||
width={pageWidth}
|
width={pageWidth}
|
||||||
@ -148,7 +162,7 @@ function TrialPaymentPage() {
|
|||||||
</div>
|
</div>
|
||||||
<Header className={styles.header} />
|
<Header className={styles.header} />
|
||||||
<TrialPaymentHeader
|
<TrialPaymentHeader
|
||||||
buttonClick={openStripeModal}
|
buttonClick={openPaymentModal}
|
||||||
buttonText={translate("/trial-payment.button") as string}
|
buttonText={translate("/trial-payment.button") as string}
|
||||||
/>
|
/>
|
||||||
{singleOrWithPartner === "partner" && (
|
{singleOrWithPartner === "partner" && (
|
||||||
@ -178,13 +192,13 @@ function TrialPaymentPage() {
|
|||||||
<PaymentTable
|
<PaymentTable
|
||||||
gender={gender}
|
gender={gender}
|
||||||
product={activeProduct}
|
product={activeProduct}
|
||||||
buttonClick={openStripeModal}
|
buttonClick={openPaymentModal}
|
||||||
placementKey={EPlacementKeys["aura.placement.redesign.main"]}
|
placementKey={placementKey}
|
||||||
/>
|
/>
|
||||||
<YourReading
|
<YourReading
|
||||||
gender={gender}
|
gender={gender}
|
||||||
zodiacSign={zodiacSign}
|
zodiacSign={zodiacSign}
|
||||||
buttonClick={openStripeModal}
|
buttonClick={openPaymentModal}
|
||||||
singleOrWithPartner={singleOrWithPartner}
|
singleOrWithPartner={singleOrWithPartner}
|
||||||
callToActionText={translate("/trial-payment.to_read_full") as string}
|
callToActionText={translate("/trial-payment.to_read_full") as string}
|
||||||
buttonText={translate("/trial-payment.button") as string}
|
buttonText={translate("/trial-payment.button") as string}
|
||||||
@ -201,8 +215,8 @@ function TrialPaymentPage() {
|
|||||||
<PaymentTable
|
<PaymentTable
|
||||||
gender={gender}
|
gender={gender}
|
||||||
product={activeProduct}
|
product={activeProduct}
|
||||||
buttonClick={openStripeModal}
|
buttonClick={openPaymentModal}
|
||||||
placementKey={EPlacementKeys["aura.placement.redesign.main"]}
|
placementKey={placementKey}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -45,4 +45,17 @@
|
|||||||
top: 32px;
|
top: 32px;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100dvh;
|
||||||
|
z-index: 9999;
|
||||||
|
background-color: #000000bb;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
@ -1,44 +1,65 @@
|
|||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import PaymentDiscountTable from "./PaymentDiscountTable";
|
import PaymentDiscountTable from "./PaymentDiscountTable";
|
||||||
import Modal from "@/components/Modal";
|
import { useEffect } from "react";
|
||||||
import { useState } from "react";
|
|
||||||
import { selectors } from "@/store";
|
import { selectors } from "@/store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { EPlacementKeys } from "@/api/resources/Paywall";
|
import { EPlacementKeys } from "@/api/resources/Paywall";
|
||||||
import PaymentModal from "@/components/PaymentModal";
|
|
||||||
import { useTranslations } from "@/hooks/translations";
|
import { useTranslations } from "@/hooks/translations";
|
||||||
import { addCurrency, ELocalesPlacement } from "@/locales";
|
import { addCurrency, ELocalesPlacement } from "@/locales";
|
||||||
import DiscountLayout from "../../layouts/Discount/DiscountLayout";
|
import DiscountLayout from "../../layouts/Discount/DiscountLayout";
|
||||||
import QuestionnaireGreenButton from "../../ui/GreenButton";
|
import QuestionnaireGreenButton from "../../ui/GreenButton";
|
||||||
|
import { usePayment } from "@/hooks/payment/nmi/usePayment";
|
||||||
|
import { Navigate, useNavigate } from "react-router-dom";
|
||||||
|
import routes from "@/routes";
|
||||||
|
import Loader, { LoaderColor } from "@/components/Loader";
|
||||||
|
|
||||||
function TrialPaymentWithDiscount() {
|
function TrialPaymentWithDiscount() {
|
||||||
|
const navigate = useNavigate()
|
||||||
const { translate } = useTranslations(ELocalesPlacement.V1);
|
const { translate } = useTranslations(ELocalesPlacement.V1);
|
||||||
const [isOpenPaymentModal, setIsOpenPaymentModal] = useState<boolean>(false);
|
|
||||||
const activeProduct = useSelector(selectors.selectActiveProduct);
|
const activeProduct = useSelector(selectors.selectActiveProduct);
|
||||||
const currency = useSelector(selectors.selectCurrency);
|
const currency = useSelector(selectors.selectCurrency);
|
||||||
|
|
||||||
const handleClose = () => {
|
if (!activeProduct) {
|
||||||
setIsOpenPaymentModal(false);
|
return <Navigate to={routes.client.additionalDiscountV1()} />
|
||||||
|
}
|
||||||
|
|
||||||
|
const { isLoading, error, isPaymentSuccess, showCreditCardForm } = usePayment({
|
||||||
|
placementKey: EPlacementKeys["aura.placement.secret.discount"],
|
||||||
|
activeProduct: activeProduct!
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isPaymentSuccess) {
|
||||||
|
return navigate(routes.client.paymentSuccess())
|
||||||
|
}
|
||||||
|
}, [isPaymentSuccess])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (error?.length && error !== "Product not found") {
|
||||||
|
return navigate(routes.client.paymentFail())
|
||||||
|
}
|
||||||
|
}, [error])
|
||||||
|
|
||||||
|
|
||||||
|
const openPaymentModal = () => {
|
||||||
|
showCreditCardForm()
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DiscountLayout title={translate("/trial-payment-with-discount.title")}>
|
<DiscountLayout title={translate("/trial-payment-with-discount.title")}>
|
||||||
<Modal
|
{isLoading &&
|
||||||
containerClassName={styles.modal}
|
<div className={styles["loader-container"]}>
|
||||||
open={isOpenPaymentModal}
|
<Loader color={LoaderColor.White} />
|
||||||
onClose={handleClose}
|
</div>
|
||||||
type="hidden"
|
}
|
||||||
>
|
|
||||||
<PaymentModal
|
|
||||||
placementKey={EPlacementKeys["aura.placement.secret.discount"]}
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
<PaymentDiscountTable />
|
<PaymentDiscountTable />
|
||||||
|
|
||||||
<div className={styles['button-wrapper']}>
|
<div className={styles['button-wrapper']}>
|
||||||
<QuestionnaireGreenButton
|
<QuestionnaireGreenButton
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
onClick={() => setIsOpenPaymentModal(true)}
|
onClick={openPaymentModal}
|
||||||
>
|
>
|
||||||
{translate("/trial-payment-with-discount.button", {
|
{translate("/trial-payment-with-discount.button", {
|
||||||
trialDuration: activeProduct?.trialDuration,
|
trialDuration: activeProduct?.trialDuration,
|
||||||
|
|||||||
@ -32,8 +32,21 @@
|
|||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loader-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100dvh;
|
||||||
|
z-index: 9999;
|
||||||
|
background-color: #000000bb;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 390px) {
|
@media (max-width: 390px) {
|
||||||
.button {
|
.button {
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
30
src/hooks/DOM/useElementRemovalObserver.ts
Normal file
30
src/hooks/DOM/useElementRemovalObserver.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
const useElementRemovalObserver = (
|
||||||
|
targetId: string,
|
||||||
|
onRemove: (removedNode: HTMLElement) => void,
|
||||||
|
container: HTMLElement | null = document.body
|
||||||
|
): void => {
|
||||||
|
useEffect(() => {
|
||||||
|
if (!container) {
|
||||||
|
console.warn("Контейнер для наблюдения не найден");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
mutations.forEach((mutation) => {
|
||||||
|
mutation.removedNodes.forEach((node) => {
|
||||||
|
if (node instanceof HTMLElement && node.id === targetId) {
|
||||||
|
onRemove(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(container, { childList: true, subtree: true });
|
||||||
|
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, [targetId, onRemove, container]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useElementRemovalObserver;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import { useApi } from "@/api";
|
import { useApi } from "@/api";
|
||||||
import { ResponsePost } from "@/api/resources/Payment";
|
import { ResponsePost } from "@/api/resources/Payment";
|
||||||
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
||||||
|
import useElementRemovalObserver from "@/hooks/DOM/useElementRemovalObserver";
|
||||||
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
||||||
import { selectors } from "@/store";
|
import { selectors } from "@/store";
|
||||||
import { useEffect, useMemo, useState } from "react"
|
import { useEffect, useMemo, useState } from "react"
|
||||||
@ -19,6 +20,15 @@ export const usePayment = ({ placementKey, activeProduct }: IUsePaymentProps) =>
|
|||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [isPaymentSuccess, setIsPaymentSuccess] = useState(false);
|
const [isPaymentSuccess, setIsPaymentSuccess] = useState(false);
|
||||||
const formPrice = String((activeProduct?.trialPrice || 99) / 100);
|
const formPrice = String((activeProduct?.trialPrice || 99) / 100);
|
||||||
|
const [isOpenModal, setIsOpenModal] = useState(false);
|
||||||
|
const [isModalClosed, setIsModalClosed] = useState(false);
|
||||||
|
|
||||||
|
const updatePaymentModalState = () => {
|
||||||
|
setIsOpenModal(false);
|
||||||
|
setIsModalClosed(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
useElementRemovalObserver("CollectJSIframe", updatePaymentModalState)
|
||||||
|
|
||||||
const isLoading = useMemo(() => {
|
const isLoading = useMemo(() => {
|
||||||
return isSubmitting
|
return isSubmitting
|
||||||
@ -38,9 +48,9 @@ export const usePayment = ({ placementKey, activeProduct }: IUsePaymentProps) =>
|
|||||||
}, [products]);
|
}, [products]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!activeProduct) return;
|
||||||
window.CollectJS.configure({
|
window.CollectJS.configure({
|
||||||
variant: 'lightbox',
|
variant: 'lightbox',
|
||||||
// styleSniffer: true,
|
|
||||||
callback: (token: any) => {
|
callback: (token: any) => {
|
||||||
finishSubmit(token);
|
finishSubmit(token);
|
||||||
},
|
},
|
||||||
@ -64,7 +74,7 @@ export const usePayment = ({ placementKey, activeProduct }: IUsePaymentProps) =>
|
|||||||
// country: "US",
|
// country: "US",
|
||||||
// currency: "USD",
|
// currency: "USD",
|
||||||
});
|
});
|
||||||
}, [placementId, paywallId]);
|
}, [placementId, paywallId, activeProduct]);
|
||||||
|
|
||||||
const finishSubmit = async (response: any) => {
|
const finishSubmit = async (response: any) => {
|
||||||
try {
|
try {
|
||||||
@ -79,6 +89,9 @@ export const usePayment = ({ placementKey, activeProduct }: IUsePaymentProps) =>
|
|||||||
});
|
});
|
||||||
setPaymentResponse(res);
|
setPaymentResponse(res);
|
||||||
setIsPaymentSuccess(res.status === "paid");
|
setIsPaymentSuccess(res.status === "paid");
|
||||||
|
if (res.status !== "paid") {
|
||||||
|
setError("message" in res ? res.message : "Something went wrong")
|
||||||
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Payment error:', error);
|
console.error('Payment error:', error);
|
||||||
setError(error?.message);
|
setError(error?.message);
|
||||||
@ -87,10 +100,11 @@ export const usePayment = ({ placementKey, activeProduct }: IUsePaymentProps) =>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const showCreditCardForm = () => {
|
const showCreditCardForm = async () => {
|
||||||
window.CollectJS.startPaymentRequest({
|
await window.CollectJS.startPaymentRequest({
|
||||||
amount: formPrice,
|
amount: formPrice,
|
||||||
});
|
});
|
||||||
|
setIsOpenModal(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
return useMemo(() => ({
|
return useMemo(() => ({
|
||||||
@ -98,12 +112,16 @@ export const usePayment = ({ placementKey, activeProduct }: IUsePaymentProps) =>
|
|||||||
paymentResponse,
|
paymentResponse,
|
||||||
error,
|
error,
|
||||||
isPaymentSuccess,
|
isPaymentSuccess,
|
||||||
|
isOpenModal,
|
||||||
|
isModalClosed,
|
||||||
showCreditCardForm
|
showCreditCardForm
|
||||||
}), [
|
}), [
|
||||||
isLoading,
|
isLoading,
|
||||||
paymentResponse,
|
paymentResponse,
|
||||||
error,
|
error,
|
||||||
isPaymentSuccess,
|
isPaymentSuccess,
|
||||||
|
isOpenModal,
|
||||||
|
isModalClosed,
|
||||||
showCreditCardForm
|
showCreditCardForm
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ import App from "./components/App";
|
|||||||
import metricService from "./services/metric/metricService";
|
import metricService from "./services/metric/metricService";
|
||||||
import "core-js/actual";
|
import "core-js/actual";
|
||||||
import { pdfjs } from "react-pdf";
|
import { pdfjs } from "react-pdf";
|
||||||
import MetaPixel from "./utils/FBMetaPixel";
|
import HeadData from "./utils/Helmet";
|
||||||
|
|
||||||
pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.js`;
|
pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.js`;
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ const init = async () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<MetaPixel />
|
<HeadData />
|
||||||
<I18nextProvider i18n={i18nextInstance}>
|
<I18nextProvider i18n={i18nextInstance}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
|
|||||||
@ -383,6 +383,7 @@ const routes = {
|
|||||||
|
|
||||||
// Payment
|
// Payment
|
||||||
makePayment: () => [dApiHost, dApiPrefix, "payment", "checkout"].join("/"),
|
makePayment: () => [dApiHost, dApiPrefix, "payment", "checkout"].join("/"),
|
||||||
|
getPaymentConfig: () => [dApiHost, dApiPrefix, "payment", "config"].join("/"),
|
||||||
|
|
||||||
// User videos
|
// User videos
|
||||||
getUserVideos: () => [dApiHost, "users", "videos", "combined"].join("/"),
|
getUserVideos: () => [dApiHost, "users", "videos", "combined"].join("/"),
|
||||||
|
|||||||
@ -20,7 +20,7 @@ const isRouteInclude = (url: string, routes: string[]) => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MetaPixel = () => {
|
const HeadData = () => {
|
||||||
const locale = getDefaultLocaleByLanguage(language);
|
const locale = getDefaultLocaleByLanguage(language);
|
||||||
const isPalmistry = isRouteInclude(window.location.pathname, routesPalmistry);
|
const isPalmistry = isRouteInclude(window.location.pathname, routesPalmistry);
|
||||||
const isChats = isRouteInclude(window.location.pathname, routesChats);
|
const isChats = isRouteInclude(window.location.pathname, routesChats);
|
||||||
@ -166,13 +166,7 @@ fbq('track', 'PageView');`;
|
|||||||
{isPalmistry && <script>{FBScriptPalmistry2}</script>}
|
{isPalmistry && <script>{FBScriptPalmistry2}</script>}
|
||||||
{isPalmistry && <script>{FBScriptPalmistry3}</script>}
|
{isPalmistry && <script>{FBScriptPalmistry3}</script>}
|
||||||
{isPalmistry && locale === "es" && (
|
{isPalmistry && locale === "es" && (
|
||||||
<>
|
<script>{FBScriptPalmistryES1}</script>
|
||||||
<script>{FBScriptPalmistryES1}</script>
|
|
||||||
<script>{FBScriptPalmistryES2}</script>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{isPalmistry && locale === "es" && (
|
|
||||||
<script>{FBScriptPalmistryES2}</script>
|
|
||||||
)}
|
)}
|
||||||
{isPalmistry && locale === "es" && (
|
{isPalmistry && locale === "es" && (
|
||||||
<script>{FBScriptPalmistryES2}</script>
|
<script>{FBScriptPalmistryES2}</script>
|
||||||
@ -181,13 +175,7 @@ fbq('track', 'PageView');`;
|
|||||||
<script>{FBScriptPalmistryPT1}</script>
|
<script>{FBScriptPalmistryPT1}</script>
|
||||||
)}
|
)}
|
||||||
{isPalmistry && locale === "en" && (
|
{isPalmistry && locale === "en" && (
|
||||||
<>
|
<script>{FBScriptPalmistryEN1}</script>
|
||||||
<script>{FBScriptPalmistryEN1}</script>
|
|
||||||
<script>{FBScriptPalmistryEN2}</script>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{isPalmistry && locale === "en" && (
|
|
||||||
<script>{FBScriptPalmistryEN2}</script>
|
|
||||||
)}
|
)}
|
||||||
{isPalmistry && locale === "en" && (
|
{isPalmistry && locale === "en" && (
|
||||||
<script>{FBScriptPalmistryEN2}</script>
|
<script>{FBScriptPalmistryEN2}</script>
|
||||||
@ -205,4 +193,4 @@ fbq('track', 'PageView');`;
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MetaPixel;
|
export default HeadData;
|
||||||
Loading…
Reference in New Issue
Block a user