UNPKG

@godaddy/react

Version:

The `createCheckoutSession` function creates a new checkout session with GoDaddy's commerce API.

214 lines (211 loc) 7.21 kB
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 };