Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
add new usePaymentMethodInterface hook and update registration api
Browse files Browse the repository at this point in the history
  • Loading branch information
nerrad committed Mar 5, 2020
1 parent 5df7852 commit 25c4631
Show file tree
Hide file tree
Showing 4 changed files with 382 additions and 4 deletions.
170 changes: 170 additions & 0 deletions assets/js/base/hooks/use-payment-method-interface.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/**
* External dependencies
*/
import {
useCheckoutContext,
usePaymentMethodDataContext,
useShippingMethodDataContext,
} from '@woocommerce/base-context';
import {
useStoreOrder,
useStoreCartCoupons,
useStoreCart,
useBillingData,
} from '@woocommerce/base-hooks';
import { __ } from '@wordpress/i18n';
import { getCurrencyFromPriceResponse } from '@woocommerce/base-utils';
import { useEffect, useRef } from '@wordpress/element';

/**
* @typedef {import('@woocommerce/type-defs/registered-payment-method-props').RegisteredPaymentMethodProps} RegisteredPaymentMethodProps
* @typedef {import('@woocommerce/type-defs/registered-payment-method-props').CartTotalItem} CartTotalItem
*/

// @todo similar logic is done in `blocks/cart-checkout/cart/full-cart/index.js`
// we should extract this to use in both places so it's consistent.
// @todo this will need to account for `DISPLAY_PRICES_INCLUDING_TAXES`.
/**
* @param {Object} totals Current cart total items
* @param {boolean} needsShipping Whether or not shipping is needed.
* @return {CartTotalItem[]}
*/
const prepareTotalItems = ( totals, needsShipping ) => {
const newTotals = [];
newTotals.push( {
label: __( 'Subtotal:', 'woo-gutenberg-products-block' ),
value: parseInt( totals.total_items, 10 ),
} );
newTotals.push( {
label: __( 'Fees:', 'woo-gutenberg-products-block' ),
value: parseInt( totals.total_fees, 10 ),
} );
newTotals.push( {
label: __( 'Discount:', 'woo-gutenberg-products-block' ),
value: parseInt( totals.total_discount, 10 ),
} );
newTotals.push( {
label: __( 'Taxes:', 'woo-gutenberg-products-block' ),
value: parseInt( totals.total_tax, 10 ),
} );
if ( needsShipping ) {
newTotals.push( {
label: __( 'Shipping:', 'woo-gutenberg-products-block' ),
value: parseInt( totals.total_shipping, 10 ),
} );
}
return newTotals;
};

// @todo This will expose the consistent properties used as the payment method
// interface pulled from the various contexts exposing data for the interface.
// @todo need to also include notices interfaces here.
/**
* @return {RegisteredPaymentMethodProps}
*/
export const usePaymentMethodInterface = () => {
const {
isCalculating,
isComplete,
isIdle,
isProcessing,
onCheckoutCompleteSuccess,
onCheckoutCompleteError,
onCheckoutProcessing,
onSubmit,
} = useCheckoutContext();
const {
setPaymentStatus,
currentStatus,
activePaymentMethod,
setActivePaymentMethod,
} = usePaymentMethodDataContext();
const {
shippingErrorStatus,
shippingErrorTypes,
shippingRates,
shippingRatesLoading,
selectedRates,
setSelectedRates,
shippingAddress,
setShippingAddress,
onShippingRateSuccess,
onShippingRateFail,
onShippingRateSelectSuccess,
onShippingRateSelectFail,
needsShipping,
} = useShippingMethodDataContext();
const { billingData, setBillingData } = useBillingData();
const { order, isLoading: orderLoading } = useStoreOrder();
const { cartTotals } = useStoreCart();
const { appliedCoupons } = useStoreCartCoupons();
const currentCartTotals = useRef(
prepareTotalItems( cartTotals, needsShipping )
);
const currentCartTotal = useRef( {
label: __( 'Total', 'woo-gutenberg-products-block' ),
value: parseInt( cartTotals.total_price, 10 ),
} );

useEffect( () => {
currentCartTotals.current = prepareTotalItems(
cartTotals,
needsShipping
);
currentCartTotal.current = {
label: __( 'Total', 'woo-gutenberg-products-block' ),
value: parseInt( cartTotals.total_price, 10 ),
};
}, [ cartTotals, needsShipping ] );

return {
checkoutStatus: {
isCalculating,
isComplete,
isIdle,
isProcessing,
},
paymentStatus: {
currentStatus,
setPaymentStatus,
},
shippingStatus: {
shippingErrorStatus,
shippingErrorTypes,
},
shippingData: {
shippingRates,
shippingRatesLoading,
selectedRates,
setSelectedRates,
shippingAddress,
setShippingAddress,
needsShipping,
},
billing: {
billingData,
setBillingData,
order,
orderLoading,
cartTotal: currentCartTotal.current,
currency: getCurrencyFromPriceResponse( cartTotals ),
// @todo need to pass along the default country set for the site
// if it's available.
country: '',
cartItems: currentCartTotals.current,
appliedCoupons,
},
eventRegistration: {
onCheckoutCompleteSuccess,
onCheckoutCompleteError,
onCheckoutProcessing,
onShippingRateSuccess,
onShippingRateFail,
onShippingRateSelectSuccess,
onShippingRateSelectFail,
},
onSubmit,
activePaymentMethod,
setActivePaymentMethod,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ export default class ExpressPaymentMethodConfig {
ExpressPaymentMethodConfig.assertValidConfig( config );
this.id = config.id;
this.activeContent = config.activeContent;
this.edit = config.edit;
this.canMakePayment = config.canMakePayment;
}

static assertValidConfig = ( config ) => {
assertConfigHasProperties( config, [ 'id', 'activeContent' ] );
assertConfigHasProperties( config, [ 'id', 'activeContent', 'edit' ] );
if ( typeof config.id !== 'string' ) {
throw new TypeError(
'The id for the express payment method must be a string'
);
}
assertValidElement( config.activeContent, 'activeContent' );
assertValidElement( config.edit, 'edit' );
if ( ! ( config.canMakePayment instanceof Promise ) ) {
throw new TypeError(
'The canMakePayment property for the express payment method must be a promise.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,27 @@ export default class PaymentMethodConfig {
PaymentMethodConfig.assertValidConfig( config );
this.id = config.id;
this.label = config.label;
this.stepContent = config.stepContent;
this.ariaLabel = config.ariaLabel;
this.activeContent = config.activeContent;
this.edit = config.edit;
this.canMakePayment = config.canMakePayment;
}

static assertValidConfig = ( config ) => {
assertConfigHasProperties( config, [
'id',
'label',
'stepContent',
'ariaLabel',
'activeContent',
'edit',
'canMakePayment',
] );
if ( typeof config.id !== 'string' ) {
throw new Error( 'The id for the payment method must be a string' );
}
assertValidElement( config.label, 'label' );
assertValidElement( config.stepContent, 'stepContent' );
assertValidElement( config.activeContent, 'activeContent' );
assertValidElement( config.edit, 'edit' );
if ( typeof config.ariaLabel !== 'string' ) {
throw new TypeError(
'The ariaLabel for the payment method must be a string'
Expand Down
Loading

0 comments on commit 25c4631

Please sign in to comment.