147 lines
4.9 KiB
TypeScript
147 lines
4.9 KiB
TypeScript
import MainButton from "@/components/MainButton";
|
|
import { useEffect } from "react";
|
|
import styles from "./styles.module.scss";
|
|
import { usePayment } from "@/hooks/payment/nmi/usePayment";
|
|
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
|
import SecurityPayments from "../../SecurityPayments";
|
|
|
|
export type TConfirmType = "payment" | "setup";
|
|
|
|
interface ICheckoutFormProps {
|
|
subscriptionReceiptId?: string;
|
|
returnUrl?: string;
|
|
confirmType?: TConfirmType;
|
|
isHide?: boolean;
|
|
placementKey: EPlacementKeys;
|
|
activeProduct: IPaywallProduct;
|
|
isAnonymous?: boolean;
|
|
sessionId?: string;
|
|
onSuccess?: () => void;
|
|
onError?: (error?: string) => void;
|
|
onModalClosed?: () => void;
|
|
}
|
|
|
|
export default function CheckoutForm({
|
|
placementKey,
|
|
activeProduct,
|
|
isAnonymous = false,
|
|
sessionId = "",
|
|
onError,
|
|
onSuccess,
|
|
onModalClosed,
|
|
isHide = false,
|
|
}: ICheckoutFormProps) {
|
|
|
|
const {
|
|
isLoading,
|
|
error,
|
|
isPaymentSuccess,
|
|
submitInlineForm,
|
|
formValidation,
|
|
isFormValid,
|
|
isModalClosed
|
|
} = usePayment({
|
|
placementKey,
|
|
activeProduct,
|
|
paymentFormType: "inline",
|
|
isAnonymous,
|
|
sessionId
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (error && onError) {
|
|
console.log(error);
|
|
|
|
onError(error);
|
|
}
|
|
}, [error]);
|
|
|
|
useEffect(() => {
|
|
if (isModalClosed && onModalClosed) {
|
|
onModalClosed();
|
|
}
|
|
}, [isModalClosed, onModalClosed]);
|
|
|
|
useEffect(() => {
|
|
if (isPaymentSuccess && onSuccess) {
|
|
onSuccess();
|
|
}
|
|
}, [isPaymentSuccess]);
|
|
|
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement> | React.MouseEvent<HTMLButtonElement>) => {
|
|
e.preventDefault();
|
|
if (!isFormValid) {
|
|
return;
|
|
}
|
|
submitInlineForm();
|
|
};
|
|
|
|
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" />
|
|
<div className={`${styles.formRow} ${styles.cardNumberRow}`}>
|
|
<label htmlFor="card-number">Card Number</label>
|
|
<div
|
|
id="card-number"
|
|
className={`${styles.fieldContainer} ${styles.cardNumber} ${formValidation.ccnumber.message ? 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">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">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>
|
|
</div>
|
|
|
|
<SecurityPayments />
|
|
|
|
<MainButton
|
|
color="blue"
|
|
disabled={isLoading || !isFormValid}
|
|
id="submit"
|
|
className={styles.button}
|
|
onClick={handleSubmit}
|
|
>
|
|
<img src="/payment-form/lock.svg" alt="Secure" />
|
|
<span>{isLoading ? "Processing..." : "Pay Now"}</span>
|
|
</MainButton>
|
|
</form>
|
|
);
|
|
}
|