@godaddy/react
Version:
The `createCheckoutSession` function creates a new checkout session with GoDaddy's commerce API.
214 lines (211 loc) • 7.21 kB
JavaScript
import { H as Button, O as PaymentMethodType, Q as useIsPaymentDisabled, S as formatCurrency, _ as useConfirmCheckout, et as useDraftOrderTotals, g as PaymentProvider, o as useCheckoutContext, rt as useGoDaddyContext } from "./checkout-CCruxHvk.js";
import { k as GraphQLErrorWithCodes } from "./utils-DWBfAHfx.js";
import { LoaderCircle } from "lucide-react";
import React, { useCallback, useEffect, useLayoutEffect, useState } from "react";
import { useFormContext } from "react-hook-form";
import { jsx, jsxs } from "react/jsx-runtime";
//#region src/components/checkout/payment/utils/use-load-mercadopago.ts
let isMercadoPagoLoaded = false;
let isMercadoPagoCDNLoaded = false;
const listeners = /* @__PURE__ */ new Set();
const MERCADOPAGO_SDK_ID = "mercadopago-sdk";
function useLoadMercadoPago() {
const { mercadoPagoConfig } = useCheckoutContext();
const [loaded, setLoaded] = useState(isMercadoPagoLoaded);
const mercadoPagoCDN = "https://sdk.mercadopago.com/js/v2";
useEffect(() => {
const updateLoaded = (newLoaded) => setLoaded(newLoaded);
listeners.add(updateLoaded);
if (isMercadoPagoLoaded) setLoaded(true);
return () => {
listeners.delete(updateLoaded);
};
}, []);
useEffect(() => {
if (isMercadoPagoLoaded || isMercadoPagoCDNLoaded || !mercadoPagoConfig || false) return;
if (document.getElementById(MERCADOPAGO_SDK_ID)) {
isMercadoPagoCDNLoaded = true;
return;
}
isMercadoPagoCDNLoaded = true;
const script = document.createElement("script");
script.id = MERCADOPAGO_SDK_ID;
script.src = mercadoPagoCDN;
script.async = true;
script.onload = () => {
isMercadoPagoLoaded = true;
listeners.forEach((listener) => listener(true));
};
document.body.appendChild(script);
}, [mercadoPagoConfig, mercadoPagoCDN]);
return { isMercadoPagoLoaded: loaded };
}
//#endregion
//#region src/components/checkout/payment/checkout-buttons/mercadopago/mercadopago.tsx
let mpInstance = null;
let bricksBuilderInstance = null;
let brickController = null;
let brickCreationPromise = null;
let isSubmitting = false;
function getMercadoPagoInstance(publicKey) {
if (!mpInstance) {
mpInstance = new window.MercadoPago(publicKey);
bricksBuilderInstance = mpInstance.bricks();
}
return {
mpInstance,
bricksBuilderInstance
};
}
function MercadoPagoCheckoutButton() {
const { t } = useGoDaddyContext();
const { mercadoPagoConfig, setCheckoutErrors, isConfirmingCheckout } = useCheckoutContext();
const isPaymentDisabled = useIsPaymentDisabled();
const { data: totals } = useDraftOrderTotals();
const form = useFormContext();
const { isMercadoPagoLoaded: isMercadoPagoLoaded$1 } = useLoadMercadoPago();
const confirmCheckout = useConfirmCheckout();
const [error, setError] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [isBrickReady, setIsBrickReady] = useState(!!brickController);
const elementId = "mercadopago-brick-container";
const handleSubmit = useCallback(async ({ formData }) => {
isSubmitting = true;
if (!await form.trigger()) {
const firstError = Object.keys(form.formState.errors)[0];
if (firstError) form.setFocus(firstError);
isSubmitting = false;
return;
}
try {
const paymentToken = formData?.token;
if (!paymentToken) throw new Error("No payment token received from MercadoPago");
await confirmCheckout.mutateAsync({
paymentToken,
paymentType: PaymentMethodType.MERCADOPAGO,
paymentProvider: PaymentProvider.MERCADOPAGO
});
setError("");
} catch (err) {
if (err instanceof GraphQLErrorWithCodes) setCheckoutErrors(err.codes);
else setError(t.errors.errorProcessingPayment);
isSubmitting = false;
}
}, [
confirmCheckout,
form,
setCheckoutErrors,
t.errors.errorProcessingPayment
]);
useLayoutEffect(() => {
if (isMercadoPagoLoaded$1 && mercadoPagoConfig?.publicKey) if (brickController) setIsBrickReady(true);
else if (brickCreationPromise) brickCreationPromise.then(() => setIsBrickReady(true));
else {
const renderBrick = async () => {
const total = parseFloat(formatCurrency({
amount: totals?.total?.value || 0,
currencyCode: totals?.total?.currencyCode || "USD",
inputInMinorUnits: true,
returnRaw: true
}));
try {
const container = document.getElementById(elementId);
if (container) container.innerHTML = "";
const { bricksBuilderInstance: bricksBuilder } = getMercadoPagoInstance(mercadoPagoConfig.publicKey);
brickController = await bricksBuilder.create("payment", elementId, {
initialization: {
amount: total,
payer: { email: "dummy@testuser.com" }
},
customization: {
visual: {
hideFormTitle: true,
hidePaymentButton: true,
style: { theme: "default" }
},
paymentMethods: {
creditCard: "all",
debitCard: "all",
maxInstallments: 1
}
},
callbacks: {
onReady: () => {
setIsLoading(false);
const formElement = document.getElementById(elementId)?.querySelector("form");
if (formElement) {
formElement.style.padding = "0";
const childDiv = formElement.querySelector(":scope > div");
if (childDiv instanceof HTMLElement) childDiv.style.margin = "0";
}
},
onError: () => {
setError(t.errors.errorProcessingPayment);
setIsLoading(false);
}
}
});
setIsBrickReady(true);
} catch (_err) {
setError(t.errors.errorProcessingPayment);
setIsBrickReady(false);
brickCreationPromise = null;
}
};
brickCreationPromise = renderBrick();
brickCreationPromise.finally(() => {
brickCreationPromise = null;
});
}
return () => {
if (brickController && !brickCreationPromise && !isSubmitting) {
try {
brickController.unmount();
} catch (_e) {}
brickController = null;
}
};
}, [
isMercadoPagoLoaded$1,
mercadoPagoConfig?.publicKey,
elementId,
t.errors.errorProcessingPayment
]);
const handleClick = async () => {
if (!await form.trigger()) {
const firstError = Object.keys(form.formState.errors)[0];
if (firstError) form.setFocus(firstError);
return;
}
if (brickController) {
const { formData } = await brickController.getFormData();
await handleSubmit({ formData });
}
};
return /* @__PURE__ */ jsxs("div", {
className: "flex flex-col gap-2",
children: [
/* @__PURE__ */ jsx("div", { id: elementId }),
error ? /* @__PURE__ */ jsx("p", {
className: "text-[0.8rem] font-medium text-destructive",
children: error
}) : null,
!isConfirmingCheckout ? /* @__PURE__ */ jsx(Button, {
className: "w-full mt-4",
size: "lg",
type: "button",
onClick: handleClick,
disabled: isPaymentDisabled || isLoading || !isBrickReady,
children: t.payment.payNow
}) : /* @__PURE__ */ jsxs(Button, {
type: "button",
size: "lg",
className: "w-full flex items-center justify-center gap-2 px-8 h-13 mt-4",
disabled: true,
children: [/* @__PURE__ */ jsx(LoaderCircle, { className: "h-5 w-5 animate-spin" }), t.payment.processingPayment]
})
]
});
}
//#endregion
export { MercadoPagoCheckoutButton };