w-aura/src/components/PaymentModalNew/index.tsx

156 lines
4.9 KiB
TypeScript

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>
);
}