feat: Change payment window on palmistry/payment
This commit is contained in:
parent
55c2207a41
commit
5ca0a636cc
@ -0,0 +1,9 @@
|
|||||||
|
export default function CreditCardIcon() {
|
||||||
|
return (
|
||||||
|
<svg width="23" height="16" viewBox="0 0 23 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="0.5" width="22" height="16" rx="2" fill="white"></rect>
|
||||||
|
<rect x="0.5" y="2.66406" width="22" height="2.66667" fill="#9FB8FF"></rect>
|
||||||
|
<rect x="3" y="7.35938" width="17" height="2" rx="1" fill="#CEDBFF"></rect>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
39
src/components/PaymentModalNew/PaymentCardModal/index.tsx
Normal file
39
src/components/PaymentModalNew/PaymentCardModal/index.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { Elements } from '@stripe/react-stripe-js';
|
||||||
|
import CheckoutForm, { TConfirmType } from '@/components/PaymentPage/methods/CheckoutForm';
|
||||||
|
import Modal from '@/components/Modal';
|
||||||
|
import { Stripe } from '@stripe/stripe-js';
|
||||||
|
import { Dispatch, SetStateAction } from 'react';
|
||||||
|
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
interface IPaymentCardModalProps {
|
||||||
|
clientSecret?: string;
|
||||||
|
stripePromise: Promise<Stripe | null> | null;
|
||||||
|
paymentType?: TConfirmType;
|
||||||
|
paymentIntentId?: string;
|
||||||
|
returnUrl?: string;
|
||||||
|
isOpen: boolean;
|
||||||
|
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PaymentCardModal({
|
||||||
|
clientSecret,
|
||||||
|
stripePromise,
|
||||||
|
paymentType,
|
||||||
|
paymentIntentId,
|
||||||
|
returnUrl,
|
||||||
|
isOpen,
|
||||||
|
setIsOpen,
|
||||||
|
}: IPaymentCardModalProps) {
|
||||||
|
return (
|
||||||
|
<Modal open={isOpen} onClose={() => setIsOpen(false)}>
|
||||||
|
<Elements stripe={stripePromise} options={{clientSecret}}>
|
||||||
|
<CheckoutForm
|
||||||
|
confirmType={paymentType}
|
||||||
|
subscriptionReceiptId={paymentIntentId}
|
||||||
|
returnUrl={returnUrl}
|
||||||
|
/>
|
||||||
|
</Elements>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
:global(.paymentCardModalContainer) {
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
.p-PaymentMethodSelector {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
155
src/components/PaymentModalNew/index.tsx
Normal file
155
src/components/PaymentModalNew/index.tsx
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import Loader from '@/components/Loader';
|
||||||
|
|
||||||
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
|
import cn from 'classnames';
|
||||||
|
import { EPlacementKeys, IPaywallProduct } from '@/api/resources/Paywall';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { Dispatch, LegacyRef, SetStateAction, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import { loadStripe, Stripe } from '@stripe/stripe-js';
|
||||||
|
import { usePaywall } from '@/hooks/paywall/usePaywall';
|
||||||
|
import { useMakePayment } from '@/hooks/payment/useMakePayment';
|
||||||
|
import { getFormattedPrice } from '@/utils/price.utils';
|
||||||
|
import routes from '@/routes';
|
||||||
|
import Title from '@/components/Title';
|
||||||
|
import { Elements } from '@stripe/react-stripe-js';
|
||||||
|
import ExpressCheckoutStripe from '@/components/PaymentPage/methods/ExpressCheckoutStripe';
|
||||||
|
import SecurityPayments from '@/components/pages/TrialPayment/components/SecurityPayments';
|
||||||
|
import PaymentCardModal from '@/components/PaymentModalNew/PaymentCardModal';
|
||||||
|
import CreditCardIcon from '@/components/PaymentModalNew/PaymentCardModal/CreditCardIcon';
|
||||||
|
|
||||||
|
interface IPaymentModalNewProps {
|
||||||
|
returnUrl: string;
|
||||||
|
placementKey: EPlacementKeys;
|
||||||
|
activeProduct: IPaywallProduct;
|
||||||
|
setHeight?: Dispatch<SetStateAction<number>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PaymentModalNew({
|
||||||
|
returnUrl,
|
||||||
|
activeProduct,
|
||||||
|
placementKey,
|
||||||
|
setHeight,
|
||||||
|
}: IPaymentModalNewProps) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const ref = useRef<HTMLDivElement>();
|
||||||
|
const [stripePromise, setStripePromise] =
|
||||||
|
useState<Promise<Stripe | null> | null>(null);
|
||||||
|
|
||||||
|
const {products, placementId, paywallId} = usePaywall({
|
||||||
|
placementKey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [isOpenCardModal, setIsOpenCardModal] = useState(false);
|
||||||
|
|
||||||
|
const {
|
||||||
|
paymentIntentId,
|
||||||
|
clientSecret,
|
||||||
|
returnUrl: checkoutUrl,
|
||||||
|
paymentType,
|
||||||
|
publicKey,
|
||||||
|
isLoading: isLoadingPayment,
|
||||||
|
error,
|
||||||
|
} = useMakePayment({
|
||||||
|
productId: activeProduct?._id || '',
|
||||||
|
placementId,
|
||||||
|
paywallId,
|
||||||
|
returnPaidUrl: returnUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [isLoadingExpressCheckout, setIsLoadingExpressCheckout] =
|
||||||
|
useState(true);
|
||||||
|
|
||||||
|
const isLoading = useMemo(() => {
|
||||||
|
return isLoadingPayment || isLoadingExpressCheckout;
|
||||||
|
}, [isLoadingPayment, isLoadingExpressCheckout]);
|
||||||
|
|
||||||
|
if (checkoutUrl?.length) {
|
||||||
|
window.location.href = checkoutUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.trialChoice());
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [activeProduct, navigate, products, publicKey]);
|
||||||
|
|
||||||
|
const resizeHandler = () => {
|
||||||
|
setHeight?.(ref?.current?.clientHeight || 32);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (error?.length) {
|
||||||
|
setTimeout(resizeHandler, 300);
|
||||||
|
return (
|
||||||
|
<div ref={ref as LegacyRef<HTMLDivElement>} className={styles['payment-modal']}>
|
||||||
|
<Title variant="h3" className={styles.title}>
|
||||||
|
Something went wrong
|
||||||
|
</Title>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={ref as LegacyRef<HTMLDivElement>}
|
||||||
|
className={cn(styles.paymentModalContainer, isLoading && styles.paymentModalContainerLoading)}>
|
||||||
|
{isLoading && <div className={cn(styles.paymentModalLoader)}>
|
||||||
|
<Loader/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className={styles.paymentModalPrice}>Total due today:
|
||||||
|
${getFormattedPrice(activeProduct.trialPrice)}</div>
|
||||||
|
|
||||||
|
{!isLoadingPayment &&
|
||||||
|
<>
|
||||||
|
{!isLoading &&
|
||||||
|
<div className={styles.paymentCreditCard} onClick={() => setIsOpenCardModal(true)}>
|
||||||
|
<CreditCardIcon/>
|
||||||
|
<div>Credit / Debit Card</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<Elements stripe={stripePromise} options={{clientSecret}}>
|
||||||
|
<ExpressCheckoutStripe
|
||||||
|
clientSecret={clientSecret!}
|
||||||
|
returnUrl={returnUrl}
|
||||||
|
paymentMethodOrderList={['google_pay', 'apple_pay', 'link']}
|
||||||
|
onChangeLoading={(isLoading) => {
|
||||||
|
setIsLoadingExpressCheckout(isLoading);
|
||||||
|
setTimeout(resizeHandler, 300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Elements>
|
||||||
|
|
||||||
|
<PaymentCardModal
|
||||||
|
isOpen={isOpenCardModal}
|
||||||
|
setIsOpen={setIsOpenCardModal}
|
||||||
|
clientSecret={clientSecret}
|
||||||
|
stripePromise={stripePromise}
|
||||||
|
paymentType={paymentType}
|
||||||
|
paymentIntentId={paymentIntentId}
|
||||||
|
returnUrl={returnUrl}
|
||||||
|
/>
|
||||||
|
{!isLoading &&
|
||||||
|
<>
|
||||||
|
<div className={styles.infoContainer}>
|
||||||
|
<SecurityPayments/>
|
||||||
|
<p className={styles.address}>1123 Rimer Dr Moraga, California 94556</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
60
src/components/PaymentModalNew/styles.module.scss
Normal file
60
src/components/PaymentModalNew/styles.module.scss
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
.paymentModalContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
margin: -12px -20px;
|
||||||
|
padding: 12px 20px;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
transition: height 1s ease-out;
|
||||||
|
|
||||||
|
.address {
|
||||||
|
color: gray;
|
||||||
|
font-size: 10px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoContainer > * {
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paymentCreditCard {
|
||||||
|
background: #066fde;
|
||||||
|
color: #fff !important;
|
||||||
|
gap: 6px;
|
||||||
|
display: flex;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 18px;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 400;
|
||||||
|
min-height: 48px;
|
||||||
|
border-radius: 5px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&Loading {
|
||||||
|
background: rgba(215, 213, 213, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.paymentModalLoader {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 25px;
|
||||||
|
color: #2f2e37;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
margin-left: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paymentModalPrice {
|
||||||
|
color: #066fde;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 25px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,11 +12,13 @@ import { useDispatch } from "react-redux";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
|
|
||||||
|
export type TConfirmType = "payment" | "setup";
|
||||||
|
|
||||||
interface ICheckoutFormProps {
|
interface ICheckoutFormProps {
|
||||||
children?: JSX.Element | null;
|
children?: JSX.Element | null;
|
||||||
subscriptionReceiptId?: string;
|
subscriptionReceiptId?: string;
|
||||||
returnUrl?: string;
|
returnUrl?: string;
|
||||||
confirmType?: "payment" | "setup";
|
confirmType?: TConfirmType;
|
||||||
isHide?: boolean;
|
isHide?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@ interface IExpressCheckoutStripeProps {
|
|||||||
availableMethods: AvailablePaymentMethods | undefined
|
availableMethods: AvailablePaymentMethods | undefined
|
||||||
) => void;
|
) => void;
|
||||||
onChangeLoading?: (isLoading: boolean) => void;
|
onChangeLoading?: (isLoading: boolean) => void;
|
||||||
|
paymentMethodOrderList?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function ExpressCheckoutStripe({
|
function ExpressCheckoutStripe({
|
||||||
@ -29,6 +30,7 @@ function ExpressCheckoutStripe({
|
|||||||
isHide = false,
|
isHide = false,
|
||||||
onAvailable,
|
onAvailable,
|
||||||
onChangeLoading,
|
onChangeLoading,
|
||||||
|
paymentMethodOrderList
|
||||||
}: IExpressCheckoutStripeProps) {
|
}: IExpressCheckoutStripeProps) {
|
||||||
const stripe = useStripe();
|
const stripe = useStripe();
|
||||||
const elements = useElements();
|
const elements = useElements();
|
||||||
@ -104,7 +106,7 @@ function ExpressCheckoutStripe({
|
|||||||
maxColumns: 1,
|
maxColumns: 1,
|
||||||
overflow: "never",
|
overflow: "never",
|
||||||
},
|
},
|
||||||
paymentMethodOrder: ["apple_pay", "google_pay", "amazon_pay", "link"],
|
paymentMethodOrder: paymentMethodOrderList || ["apple_pay", "google_pay", "amazon_pay", "link"],
|
||||||
wallets: {
|
wallets: {
|
||||||
googlePay: "always",
|
googlePay: "always",
|
||||||
applePay: "always",
|
applePay: "always",
|
||||||
|
|||||||
@ -1,228 +1,247 @@
|
|||||||
.payment-screen {
|
.payment-screen {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 428px;
|
max-width: 428px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__header {
|
.payment-screen__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 24px 0 11px;
|
padding: 24px 0 11px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__content {
|
.payment-screen__content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__content * {
|
.payment-screen__content * {
|
||||||
font-family: OpenSans Regular;
|
font-family: OpenSans Regular;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__about-us {
|
.payment-screen__about-us {
|
||||||
display: flex;
|
display: flex;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__about-us > span {
|
.payment-screen__about-us > span {
|
||||||
padding: 0 60px;
|
padding: 0 60px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__about-us span {
|
.payment-screen__about-us span {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
font-family: Alata Regular !important;
|
font-family: Alata Regular !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__about-us-accent {
|
.payment-screen__about-us-accent {
|
||||||
color: #066fde;
|
color: #066fde;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__timer {
|
.payment-screen__timer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #eff2fd;
|
background: #eff2fd;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__timer-title {
|
.payment-screen__timer-title {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__timer-time {
|
.payment-screen__timer-time {
|
||||||
gap: 1px;
|
gap: 1px;
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__timer-time span {
|
.payment-screen__timer-time span {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
display: flex;
|
display: flex;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border: 1px solid #dee5f9;
|
border: 1px solid #dee5f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__title {
|
.payment-screen__title {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #121620;
|
color: #121620;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-family: Alata Regular !important;
|
font-family: Alata Regular !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__total-today {
|
.payment-screen__total-today {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-top: 1px solid #dee5f9;
|
border-top: 1px solid #dee5f9;
|
||||||
border-bottom: 1px solid #dee5f9;
|
border-bottom: 1px solid #dee5f9;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__total-today span {
|
.payment-screen__total-today span {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__total-today .payment-screen__trial-price {
|
.payment-screen__total-today .payment-screen__trial-price {
|
||||||
color: #066fde;
|
color: #066fde;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__promocode {
|
.payment-screen__promocode {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 0 16px;
|
padding: 12px 0 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__promocode span {
|
.payment-screen__promocode span {
|
||||||
color: #04a777;
|
color: #04a777;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__prices {
|
.payment-screen__prices {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__prices span {
|
.payment-screen__prices span {
|
||||||
color: #4b536a;
|
color: #4b536a;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__prices s {
|
.payment-screen__prices s {
|
||||||
color: #858da5;
|
color: #858da5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__guarantees {
|
.payment-screen__guarantees {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 30px;
|
gap: 30px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__guarantee {
|
.payment-screen__guarantee {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
max-width: 155px;
|
max-width: 155px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__guarantee svg {
|
.payment-screen__guarantee svg {
|
||||||
min-width: 24px;
|
min-width: 24px;
|
||||||
min-height: 24px;
|
min-height: 24px;
|
||||||
max-width: 24px;
|
max-width: 24px;
|
||||||
max-height: 24px;
|
max-height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__guarantee span {
|
.payment-screen__guarantee span {
|
||||||
color: #4b536a;
|
color: #4b536a;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__widget {
|
.payment-screen__widget {
|
||||||
background: #fff;
|
position: fixed;
|
||||||
bottom: 0;
|
background: #fff;
|
||||||
box-shadow: 0 -2px 16px rgba(18, 22, 32, .1);
|
bottom: 0;
|
||||||
max-width: 428px;
|
box-shadow: 0 -2px 16px rgba(18, 22, 32, .1);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 40px;
|
padding: 12px 20px;
|
||||||
position: relative;
|
text-align: center;
|
||||||
|
text-align: -webkit-center;
|
||||||
|
transition: .5s height;
|
||||||
|
max-width: 560px;
|
||||||
|
margin-left: -66px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__widget_success {
|
.payment-screen__widget_success {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__success {
|
.payment-screen__success {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
background: #fff;
|
||||||
left: 0;
|
z-index: 99;
|
||||||
top: 0;
|
display: flex;
|
||||||
background: #fff;
|
flex-direction: column;
|
||||||
z-index: 99;
|
align-items: center;
|
||||||
display: flex;
|
justify-content: center;
|
||||||
flex-direction: column;
|
gap: 30px;
|
||||||
align-items: center;
|
padding: 40px;
|
||||||
justify-content: center;
|
|
||||||
gap: 30px;
|
|
||||||
padding: 40px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__success-icon {
|
.payment-screen__success-icon {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.payment-screen__success-text {
|
.payment-screen__success-text {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #121620;
|
color: #121620;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.payment-screen__widget_modal_container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: 560px) {
|
||||||
|
.payment-screen__widget {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 20px;
|
||||||
|
text-align: center;
|
||||||
|
text-align: -webkit-center;
|
||||||
|
transition: height 1s linear;
|
||||||
|
max-width: 560px;
|
||||||
|
margin-left: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,20 +1,17 @@
|
|||||||
import React from "react";
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import "./payment-screen.css";
|
import './payment-screen.css';
|
||||||
|
|
||||||
import useSteps, { Step } from "@/hooks/palmistry/use-steps";
|
import useSteps, { Step } from '@/hooks/palmistry/use-steps';
|
||||||
import useTimer from "@/hooks/palmistry/use-timer";
|
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/PaymentModal";
|
import { selectors } from '@/store';
|
||||||
import { selectors } from "@/store";
|
import { EPlacementKeys } from '@/api/resources/Paywall';
|
||||||
import { EPlacementKeys } from "@/api/resources/Paywall";
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { useSearchParams } from "react-router-dom";
|
import PaymentModalNew from '@/components/PaymentModalNew';
|
||||||
|
import { getFormattedPrice } from '@/utils/price.utils';
|
||||||
const getFormattedPrice = (price: number) => {
|
|
||||||
return (price / 100).toFixed(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function PaymentScreen() {
|
export default function PaymentScreen() {
|
||||||
const time = useTimer();
|
const time = useTimer();
|
||||||
@ -24,7 +21,7 @@ export default function PaymentScreen() {
|
|||||||
searchParams.get("redirect_status") === "succeeded"
|
searchParams.get("redirect_status") === "succeeded"
|
||||||
? "subscribed"
|
? "subscribed"
|
||||||
: "lead";
|
: "lead";
|
||||||
// const subscriptionStatus = useSelector(selectors.selectStatus);
|
const [height, setHeight] = useState(subscriptionStatus === "subscribed" ? 246 : 146);
|
||||||
|
|
||||||
const steps = useSteps();
|
const steps = useSteps();
|
||||||
|
|
||||||
@ -52,7 +49,7 @@ export default function PaymentScreen() {
|
|||||||
return (
|
return (
|
||||||
<div className="payment-screen">
|
<div className="payment-screen">
|
||||||
<div className="payment-screen__header">
|
<div className="payment-screen__header">
|
||||||
<HeaderLogo />
|
<HeaderLogo/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="payment-screen__content">
|
<div className="payment-screen__content">
|
||||||
@ -246,40 +243,45 @@ export default function PaymentScreen() {
|
|||||||
<style>{`.palmistry-payment-modal { max-height: calc(100dvh - 40px) }`}</style>
|
<style>{`.palmistry-payment-modal { max-height: calc(100dvh - 40px) }`}</style>
|
||||||
|
|
||||||
{activeProductFromStore && (
|
{activeProductFromStore && (
|
||||||
<div
|
<div className="payment-screen__widget_modal_container"
|
||||||
className={`payment-screen__widget${
|
style={{minHeight: `${height}px`}}>
|
||||||
subscriptionStatus === "subscribed"
|
<div
|
||||||
? " payment-screen__widget_success"
|
className={`payment-screen__widget${
|
||||||
: ""
|
subscriptionStatus === "subscribed"
|
||||||
}`}
|
? " payment-screen__widget_success"
|
||||||
>
|
: ""
|
||||||
{subscriptionStatus !== "subscribed" && (
|
}`}
|
||||||
<PaymentModal
|
>
|
||||||
returnUrl={window.location.href}
|
{subscriptionStatus !== "subscribed" && (
|
||||||
placementKey={EPlacementKeys["aura.placement.palmistry.main"]}
|
<PaymentModalNew
|
||||||
/>
|
setHeight={setHeight}
|
||||||
)}
|
activeProduct={activeProductFromStore}
|
||||||
|
returnUrl={window.location.href}
|
||||||
|
placementKey={EPlacementKeys["aura.placement.palmistry.main"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{subscriptionStatus === "subscribed" && (
|
{subscriptionStatus === "subscribed" && (
|
||||||
<div className="payment-screen__success">
|
<div className="payment-screen__success">
|
||||||
<svg
|
<svg
|
||||||
className="payment-screen__success-icon"
|
className="payment-screen__success-icon"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="512"
|
width="512"
|
||||||
height="512"
|
height="512"
|
||||||
viewBox="0 0 52 52"
|
viewBox="0 0 52 52"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
fill="#4ec794"
|
fill="#4ec794"
|
||||||
d="M26 0C11.664 0 0 11.663 0 26s11.664 26 26 26 26-11.663 26-26S40.336 0 26 0zm14.495 17.329-16 18a1.997 1.997 0 0 1-2.745.233l-10-8a2 2 0 0 1 2.499-3.124l8.517 6.813L37.505 14.67a2.001 2.001 0 0 1 2.99 2.659z"
|
d="M26 0C11.664 0 0 11.663 0 26s11.664 26 26 26 26-11.663 26-26S40.336 0 26 0zm14.495 17.329-16 18a1.997 1.997 0 0 1-2.745.233l-10-8a2 2 0 0 1 2.499-3.124l8.517 6.813L37.505 14.67a2.001 2.001 0 0 1 2.99 2.659z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div className="payment-screen__success-text">
|
<div className="payment-screen__success-text">
|
||||||
Payment success
|
Payment success
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
3
src/utils/price.utils.tsx
Normal file
3
src/utils/price.utils.tsx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const getFormattedPrice = (price: number) => {
|
||||||
|
return (price / 100).toFixed(2);
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user