woocommerce/plugins/woocommerce-blocks/assets/js/base/context/cart-checkout/payment-methods/payment-method-data-context.js

154 lines
4.3 KiB
JavaScript

/**
* Internal dependencies
*/
import {
STATUS,
DEFAULT_PAYMENT_DATA,
DEFAULT_PAYMENT_METHOD_DATA,
} from './constants';
import reducer from './reducer';
import {
statusOnly,
error,
failed,
success,
setBillingData as setBilling,
} from './actions';
/**
* External dependencies
*/
import {
createContext,
useContext,
useState,
useReducer,
} from '@wordpress/element';
/**
* @typedef {import('@woocommerce/type-defs/contexts').PaymentMethodDataContext} PaymentMethodDataContext
* @typedef {import('@woocommerce/type-defs/contexts').PaymentStatusDispatch} PaymentStatusDispatch
* @typedef {import('@woocommerce/type-defs/contexts').PaymentStatusDispatchers} PaymentStatusDispatchers
* @typedef {import('@woocommerce/type-defs/cart').CartBillingAddress} CartBillingAddress
*/
const {
STARTED,
PROCESSING,
COMPLETE,
PRISTINE,
ERROR,
FAILED,
SUCCESS,
} = STATUS;
const PaymentMethodDataContext = createContext( DEFAULT_PAYMENT_METHOD_DATA );
/**
* @return {PaymentMethodDataContext} The data and functions exposed by the
* payment method context provider.
*/
export const usePaymentMethodDataContext = () => {
return useContext( PaymentMethodDataContext );
};
// @todo implement billing (and payment method) data saved to the cart data
// store. That way checkout can obtain it for processing the order.
/**
* PaymentMethodDataProvider is automatically included in the
* CheckoutDataProvider.
*
* This provides the api interface (via the context hook) for payment method
* status and data.
*
* @param {Object} props Incoming props for provider
* @param {Array} props.children The wrapped components in this
* provider.
* @param {string} props.activePaymentMethod The initial active payment method
* to set for the context.
*/
export const PaymentMethodDataProvider = ( {
children,
activePaymentMethod: initialActivePaymentMethod,
} ) => {
const [ activePaymentMethod, setActive ] = useState(
initialActivePaymentMethod
);
const [ paymentStatus, dispatch ] = useReducer(
reducer,
DEFAULT_PAYMENT_DATA
);
const setActivePaymentMethod = ( paymentMethodSlug ) => {
setActive( paymentMethodSlug );
dispatch( statusOnly( PRISTINE ) );
};
/**
* @type {PaymentStatusDispatch}
*/
const setPaymentStatus = () => ( {
started: () => dispatch( statusOnly( STARTED ) ),
processing: () => dispatch( statusOnly( PROCESSING ) ),
completed: () => dispatch( statusOnly( COMPLETE ) ),
/**
* @param {string} errorMessage An error message
*/
error: ( errorMessage ) => dispatch( error( errorMessage ) ),
/**
* @param {string} errorMessage An error message
* @param {CartBillingAddress} billingData The billing data accompanying the payment method
* @param {Object} paymentMethodData Arbitrary payment method data to accompany the checkout submission.
*/
failed: ( errorMessage, billingData, paymentMethodData ) =>
dispatch(
failed( {
errorMessage,
billingData,
paymentMethodData,
} )
),
/**
* @param {CartBillingAddress} billingData The billing data accompanying the payment method.
* @param {Object} paymentMethodData Arbitrary payment method data to accompany the checkout.
*/
success: ( billingData, paymentMethodData ) =>
dispatch(
success( {
billingData,
paymentMethodData,
} )
),
} );
const setBillingData = ( billingData ) =>
dispatch( setBilling( billingData ) );
const currentStatus = {
isPristine: paymentStatus === PRISTINE,
isStarted: paymentStatus === STARTED,
isProcessing: paymentStatus === PROCESSING,
isFinished: [ ERROR, FAILED, SUCCESS ].includes( paymentStatus ),
hasError: paymentStatus === ERROR,
hasFailed: paymentStatus === FAILED,
isSuccessful: paymentStatus === SUCCESS,
};
/**
* @type {PaymentMethodDataContext}
*/
const paymentData = {
setPaymentStatus,
currentStatus,
paymentStatuses: STATUS,
billingData: paymentStatus.billingData,
paymentMethodData: paymentStatus.paymentMethodData,
errorMessage: paymentStatus.errorMessage,
activePaymentMethod,
setActivePaymentMethod,
setBillingData,
};
return (
<PaymentMethodDataContext.Provider value={ paymentData }>
{ children }
</PaymentMethodDataContext.Provider>
);
};