@noaignite/react-centra-checkout
Version:
React components and helpers for Centra checkout api
109 lines • 4.34 kB
JavaScript
// src/PaymentEmbed.tsx
import { isPlainObject } from "@noaignite/utils";
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import isEqual from "react-fast-compare";
import { useCentraHandlers, useCentraSelection } from "./Context.js";
import { HtmlEmbed } from "./internal/HtmlEmbed.js";
import { jsx } from "react/jsx-runtime";
var PaymentEmbed = memo(function PaymentEmbed2(props) {
const { values, onPaymentError, onPaymentSuccess } = props;
const [paymentResult, setPaymentResult] = useState(null);
const [paymentCallbackError, setPaymentCallbackError] = useState(null);
const previousPaymentMethod = useRef(null);
const { selection, paymentMethods } = useCentraSelection();
const { submitPayment } = useCentraHandlers();
const paymentMethodId = selection?.paymentMethod;
const paymentMethod = useMemo(
() => paymentMethods?.find((p) => p.paymentMethod === paymentMethodId),
[paymentMethods, paymentMethodId]
);
const handlePaymentCallback = useCallback(
(event) => {
const {
addressIncluded,
billingAddress: detailsAddress,
shippingAddress: detailsShippingAddress,
paymentMethod: detailsPaymentMethod,
paymentMethodSpecificFields
} = event.detail;
const payload = {
address: values.address,
shippingAddress: values.shippingAddress,
paymentMethod: detailsPaymentMethod,
paymentMethodSpecificFields,
termsAndConditions: values.termsAndConditions
};
if (addressIncluded) {
payload.address = detailsAddress;
payload.shippingAddress = detailsShippingAddress;
}
submitPayment?.(payload).then((result) => {
if ("errors" in result && Boolean(result.errors)) {
onPaymentError?.(result.errors);
setPaymentResult(null);
setPaymentCallbackError(result.errors);
} else {
onPaymentSuccess?.(result);
setPaymentCallbackError(null);
}
}).catch((err) => {
console.error("@noaignite/react-centra-checkout: Could not submit payment");
if (isPlainObject(err)) {
setPaymentCallbackError(err);
}
console.error(err);
});
},
[submitPayment, onPaymentSuccess, onPaymentError, values]
);
useEffect(() => {
if (selection?.paymentMethod !== previousPaymentMethod.current) {
setPaymentResult(null);
}
}, [selection?.paymentMethod]);
useEffect(() => {
const shouldRequestPayment = (
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we actually want || here because we are checking for undefined, null and false
paymentMethod?.supportsInitiateOnly || paymentMethod?.providesCustomerAddressAfterPayment
);
if ((selection?.paymentMethod === previousPaymentMethod.current || !shouldRequestPayment) && !paymentCallbackError || !selection?.paymentMethod) {
return;
}
previousPaymentMethod.current = selection.paymentMethod;
submitPayment?.({ ...values, termsAndConditions: void 0 }).then((result) => {
if ("errors" in result) {
console.error(result.errors);
onPaymentError?.(result.errors);
throw new Error("@noaignite/react-centra-checkout: Error while fetching widget");
}
if (result.action === "form" && !result.formHtml) {
throw new Error("@noaignite/react-centra-checkout: No form to render");
}
setPaymentResult(result);
setPaymentCallbackError(null);
}).catch((err) => {
console.error(err);
setPaymentResult(null);
});
}, [
onPaymentError,
paymentCallbackError,
paymentMethod,
selection?.paymentMethod,
selection?.totals?.grandTotalPriceAsNumber,
submitPayment,
values
]);
useEffect(() => {
document.addEventListener("centra_checkout_payment_callback", handlePaymentCallback);
return () => {
document.removeEventListener("centra_checkout_payment_callback", handlePaymentCallback);
};
}, [handlePaymentCallback]);
const formHtml = paymentResult && "formHtml" in paymentResult && paymentResult.formHtml;
return formHtml ? /* @__PURE__ */ jsx(HtmlEmbed, { html: formHtml, id: "centra-payment-form" }) : null;
}, isEqual);
export {
PaymentEmbed
};
//# sourceMappingURL=PaymentEmbed.js.map