275 lines
9.7 KiB
TypeScript
275 lines
9.7 KiB
TypeScript
import MainButton from "@/components/MainButton";
|
|
import { useEffect, useState } from "react";
|
|
import styles from "./styles.module.scss";
|
|
import { usePayment } from "@/hooks/payment/nmi/usePayment";
|
|
import SecurityPayments from "../../SecurityPayments";
|
|
import { useTranslations } from "@/hooks/translations";
|
|
import { ELocalesPlacement } from "@/locales";
|
|
import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash";
|
|
import Loader, { LoaderColor } from "@/components/Loader";
|
|
import { IFunnelPaymentVariant } from "@/api/resources/Session";
|
|
|
|
export type TConfirmType = "payment" | "setup";
|
|
|
|
interface ICheckoutFormProps {
|
|
subscriptionReceiptId?: string;
|
|
returnUrl?: string;
|
|
confirmType?: TConfirmType;
|
|
isHide?: boolean;
|
|
activeProduct: IFunnelPaymentVariant;
|
|
isAnonymous?: boolean;
|
|
sessionId?: string;
|
|
funnel: ELocalesPlacement;
|
|
paymentPlacement: string;
|
|
onSuccess?: () => void;
|
|
onError?: (error?: string | null) => void;
|
|
onModalClosed?: () => void;
|
|
}
|
|
|
|
export default function CheckoutForm({
|
|
activeProduct,
|
|
isAnonymous = false,
|
|
sessionId = "",
|
|
funnel,
|
|
paymentPlacement,
|
|
onError,
|
|
onSuccess,
|
|
onModalClosed,
|
|
isHide = false,
|
|
}: ICheckoutFormProps) {
|
|
const { translate } = useTranslations(ELocalesPlacement.V1);
|
|
const [payButtonClicked, setPayButtonClicked] = useState(false);
|
|
const { variant, isReady } = useUnleash({
|
|
flag: EUnleashFlags.paymentButtonLogic,
|
|
});
|
|
const isNewPaymentButton = variant === "new";
|
|
const [isCardTypeError, setIsCardTypeError] = useState(false);
|
|
|
|
// const address = useAddressFields(language);
|
|
|
|
const {
|
|
isLoading,
|
|
error,
|
|
isPaymentSuccess,
|
|
submitInlineForm,
|
|
formValidation,
|
|
isFormValid,
|
|
isModalClosed,
|
|
cardType,
|
|
} = usePayment({
|
|
activeProduct,
|
|
paymentFormType: "inline",
|
|
isAnonymous,
|
|
sessionId,
|
|
funnel,
|
|
paymentPlacement,
|
|
});
|
|
|
|
useEffect(() => {
|
|
// if (error) {
|
|
console.log(error);
|
|
if (error === "card_type_error") {
|
|
return setIsCardTypeError(true);
|
|
} else {
|
|
setIsCardTypeError(false);
|
|
}
|
|
onError?.(error);
|
|
// }
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [error]);
|
|
|
|
useEffect(() => {
|
|
if (isModalClosed && onModalClosed) {
|
|
onModalClosed();
|
|
}
|
|
}, [isModalClosed, onModalClosed]);
|
|
|
|
useEffect(() => {
|
|
if (isPaymentSuccess && onSuccess) {
|
|
onSuccess();
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [isPaymentSuccess]);
|
|
|
|
const handleSubmit = (
|
|
e: React.FormEvent<HTMLFormElement> | React.MouseEvent<HTMLButtonElement>
|
|
) => {
|
|
e.preventDefault();
|
|
setPayButtonClicked(true);
|
|
|
|
// const isAddressValid = address.validateAll();
|
|
if (!isFormValid) {
|
|
return;
|
|
}
|
|
submitInlineForm();
|
|
};
|
|
|
|
if (!isReady) {
|
|
return (
|
|
<div className={styles.loaderContainer}>
|
|
<Loader color={LoaderColor.Black} />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<form
|
|
className={`${styles.form} ${isHide ? styles.hide : ""}`}
|
|
id="payment-form"
|
|
onSubmit={handleSubmit}
|
|
>
|
|
<div className={styles.formContainer}>
|
|
<img
|
|
className={styles.cardIcon}
|
|
src="/payment-form/credit-card.svg"
|
|
alt="card"
|
|
/>
|
|
{isCardTypeError && (
|
|
<div className={styles.cardTypeError}>
|
|
<svg
|
|
width="14"
|
|
height="20"
|
|
viewBox="0 0 14 20"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path d="M14 20H0V0H14V20Z" stroke="#E5E7EB" />
|
|
<g clipPath="url(#clip0_1_46)">
|
|
<path
|
|
d="M7 3.625C7.38828 3.625 7.74648 3.83008 7.94336 4.16641L13.8496 14.2289C14.0492 14.568 14.0492 14.9863 13.8551 15.3254C13.6609 15.6645 13.2973 15.875 12.9062 15.875H1.09375C0.702734 15.875 0.339062 15.6645 0.144922 15.3254C-0.049219 14.9863 -0.0464846 14.5652 0.15039 14.2289L6.05664 4.16641C6.25352 3.83008 6.61172 3.625 7 3.625ZM7 7.125C6.63633 7.125 6.34375 7.41758 6.34375 7.78125V10.8438C6.34375 11.2074 6.63633 11.5 7 11.5C7.36367 11.5 7.65625 11.2074 7.65625 10.8438V7.78125C7.65625 7.41758 7.36367 7.125 7 7.125ZM7.875 13.25C7.875 13.0179 7.78281 12.7954 7.61872 12.6313C7.45462 12.4672 7.23206 12.375 7 12.375C6.76794 12.375 6.54538 12.4672 6.38128 12.6313C6.21719 12.7954 6.125 13.0179 6.125 13.25C6.125 13.4821 6.21719 13.7046 6.38128 13.8687C6.54538 14.0328 6.76794 14.125 7 14.125C7.23206 14.125 7.45462 14.0328 7.61872 13.8687C7.78281 13.7046 7.875 13.4821 7.875 13.25Z"
|
|
fill="#EF4444"
|
|
/>
|
|
</g>
|
|
<defs>
|
|
<clipPath id="clip0_1_46">
|
|
<path d="M0 2.75H14V16.75H0V2.75Z" fill="white" />
|
|
</clipPath>
|
|
</defs>
|
|
</svg>
|
|
<div className={styles.textContainer}>
|
|
<p className={styles.title}>
|
|
{translate("payment_modal.card_type_error.title", {
|
|
cardType:
|
|
cardType?.charAt(0)?.toUpperCase() + cardType?.slice(1),
|
|
})}
|
|
</p>
|
|
<p className={styles.description}>
|
|
{translate("payment_modal.card_type_error.description")}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
<div className={`${styles.formRow} ${styles.cardNumberRow}`}>
|
|
<div className={styles.cardNumberLabelContainer}>
|
|
<label htmlFor="card-number">
|
|
{translate("payment_modal.card_number")}
|
|
</label>
|
|
<svg
|
|
width="40"
|
|
height="25"
|
|
viewBox="0 0 40 25"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M19.9286 21.5352C17.8178 23.3566 15.0797 24.4563 12.0879 24.4563C5.41189 24.4563 0 18.9816 0 12.2282C0 5.47469 5.41189 0 12.0879 0C15.0797 0 17.8178 1.09961 19.9286 2.92118C22.0394 1.09961 24.7774 0 27.7694 0C34.4453 0 39.8571 5.47469 39.8571 12.2282C39.8571 18.9816 34.4453 24.4563 27.7694 24.4563C24.7774 24.4563 22.0394 23.3566 19.9286 21.5352Z"
|
|
fill="#ED0006"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M19.9286 21.5352C22.5276 19.2923 24.1757 15.9549 24.1757 12.2282C24.1757 8.50135 22.5276 5.16398 19.9286 2.92118C22.0394 1.09961 24.7774 0 27.7694 0C34.4453 0 39.8572 5.47469 39.8572 12.2282C39.8572 18.9816 34.4453 24.4563 27.7694 24.4563C24.7774 24.4563 22.0394 23.3566 19.9286 21.5352Z"
|
|
fill="#F9A000"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M19.9287 2.92114C22.5277 5.16404 24.1758 8.50132 24.1758 12.2281C24.1758 15.9549 22.5277 19.2922 19.9287 21.535C17.3297 19.2922 15.6817 15.9549 15.6817 12.2281C15.6817 8.50132 17.3297 5.16404 19.9287 2.92114Z"
|
|
fill="#FF5E00"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<div
|
|
id="card-number"
|
|
className={`${styles.fieldContainer} ${styles.cardNumber} ${
|
|
formValidation.ccnumber.message || isCardTypeError
|
|
? styles.invalid
|
|
: ""
|
|
} ${formValidation.ccnumber.isValid ? styles.valid : ""}`}
|
|
/>
|
|
{formValidation.ccnumber.message && (
|
|
<div className={styles.errorMessage}>
|
|
{formValidation.ccnumber.message}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className={styles.formGroup}>
|
|
<div className={styles.formRow}>
|
|
<label htmlFor="card-expiry">
|
|
{translate("payment_modal.expiration_date")}
|
|
</label>
|
|
<div
|
|
id="card-expiry"
|
|
className={`${styles.fieldContainer} ${styles.cardExpiry} ${
|
|
formValidation.ccexp.message ? styles.invalid : ""
|
|
} ${formValidation.ccexp.isValid ? styles.valid : ""}`}
|
|
/>
|
|
{formValidation.ccexp.message && (
|
|
<div className={styles.errorMessage}>
|
|
{formValidation.ccexp.message}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className={styles.formRow} style={{ marginLeft: "auto" }}>
|
|
<label htmlFor="card-cvv">{translate("payment_modal.cvv")}</label>
|
|
<div
|
|
id="card-cvv"
|
|
className={`${styles.fieldContainer} ${styles.cardCvv} ${
|
|
formValidation.cvv.message ? styles.invalid : ""
|
|
} ${formValidation.cvv.isValid ? styles.valid : ""}`}
|
|
/>
|
|
{formValidation.cvv.message && (
|
|
<div className={styles.errorMessage}>
|
|
{formValidation.cvv.message}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
{/* <AddressFields
|
|
fields={address.fields}
|
|
errors={address.errors}
|
|
onChange={address.handleChange}
|
|
countryList={address.countryList}
|
|
/> */}
|
|
</div>
|
|
{isNewPaymentButton && payButtonClicked && !isFormValid && (
|
|
<p className={styles.errorMessage} style={{ marginBottom: "16px" }}>
|
|
{translate("payment_modal.form_error")}
|
|
</p>
|
|
)}
|
|
|
|
<SecurityPayments />
|
|
|
|
<MainButton
|
|
color="blue"
|
|
// disabled={isLoading || !isFormValid}
|
|
disabled={isNewPaymentButton ? isLoading : isLoading || !isFormValid}
|
|
id="submit"
|
|
className={styles.button}
|
|
onClick={handleSubmit}
|
|
>
|
|
<img src="/payment-form/lock.svg" alt="Secure" />
|
|
<span>
|
|
{isLoading
|
|
? translate("payment_modal.processing")
|
|
: translate("payment_modal.pay_now")}
|
|
</span>
|
|
</MainButton>
|
|
</form>
|
|
);
|
|
}
|