UNPKG

@shopgate/engage

Version:
126 lines (122 loc) 3.84 kB
import React, { useLayoutEffect, useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { css } from 'glamor'; import { getThemeSettings, showModal, MODAL_PIPELINE_ERROR } from '@shopgate/engage/core'; import { connect } from 'react-redux'; import { i18n } from "../../../core/helpers/i18n"; import { useCheckoutContext } from "../../hooks/common"; import { usePaypal } from "./sdk"; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; const styles = { headline: css({ fontSize: '1.25rem', fontWeight: 'normal', margin: '12px 0 12px 0', color: 'var(--color-text-high-emphasis)', textTransform: 'none' }).toString() }; /** * Paypal Pay button * @returns {JSX} */ const PaypalPayButton = ({ // eslint-disable-next-line no-shadow disabled, onSubmit, onValidate, showModal }) => { const { paymentData, paymentTransactions } = useCheckoutContext(); const [paypalActions, setPaypalActions] = useState(null); const paypal = usePaypal(); const paypalButton = useRef(null); const button = useRef(null); const fundingSource = paymentData?.meta; // Store form actions inside ref as they would trigger // rerenders everytime the form changes, but here we // only need them once validating. // paypal unfortunately doesn't allow updating button props. const formActions = useRef({}); useEffect(() => { formActions.current = { onSubmit, onValidate }; }, [onSubmit, onValidate]); // Trigger rendering the paypal button whenever a property changes. useLayoutEffect(() => { if (!paypal) return; if (typeof fundingSource === 'object') return; if (paypalButton.current) { paypalButton.current.close(); } const customSettings = getThemeSettings('PayPal') || {}; paypalButton.current = paypal.Buttons({ fundingSource: fundingSource || paypal.FUNDING.PAYPAL, createOrder: () => { const externalCode = paymentTransactions[0]?.externalCode; return externalCode; }, onInit: (_, actions) => { // Here again thanks paypal, there is no way access the actions outside these handlers. setPaypalActions(actions); }, onClick: (_, actions) => { // Trigger manual form validation to comply to paypal standards. const isValid = formActions.current.onValidate(); if (isValid && !disabled) { return actions.resolve(); } return actions.reject(); }, onApprove: async (_, actions) => { const redirect = await formActions.current.onSubmit(); if (redirect) { showModal({ type: MODAL_PIPELINE_ERROR, title: null, confirm: null, dismiss: 'modal.ok', message: 'checkout.errors.paypalFunding' }); actions.restart(); } }, style: { label: 'pay', color: 'white', ...customSettings } }); paypalButton.current.render(button.current); }, [disabled, fundingSource, paymentTransactions, paypal, showModal]); // Sync our internal disabled state with paypals disabled state. useEffect(() => { if (!paypalActions) return; if (disabled) { paypalActions.disable(); return; } paypalActions.enable(); }, [disabled, paypalActions]); if (typeof fundingSource === 'object') return null; if (!paypal) { return null; } return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx("h3", { className: styles.headline, children: i18n.text('checkout.finalizePayment') }), /*#__PURE__*/_jsx("div", { ref: button })] }); }; const mapDispatchToProps = { showModal }; export default connect(null, mapDispatchToProps)(PaypalPayButton);