diff --git a/plugins/woocommerce-blocks/assets/js/base/components/payment-methods/express-payment-methods.js b/plugins/woocommerce-blocks/assets/js/base/components/payment-methods/express-payment-methods.js
index 676e9f47edf..5cb719f652e 100644
--- a/plugins/woocommerce-blocks/assets/js/base/components/payment-methods/express-payment-methods.js
+++ b/plugins/woocommerce-blocks/assets/js/base/components/payment-methods/express-payment-methods.js
@@ -2,34 +2,30 @@
* External dependencies
*/
import {
- useCheckoutData,
- usePaymentEvents,
useExpressPaymentMethods,
+ usePaymentMethodInterface,
} from '@woocommerce/base-hooks';
import { cloneElement, isValidElement } from '@wordpress/element';
import { useCheckoutContext } from '@woocommerce/base-context';
const ExpressPaymentMethods = () => {
- const [ checkoutData ] = useCheckoutData();
const { isEditor } = useCheckoutContext();
- const { dispatch, select } = usePaymentEvents();
+ const paymentMethodInterface = usePaymentMethodInterface();
// not implementing isInitialized here because it's utilized further
// up in the tree for express payment methods. We won't even get here if
// there's no payment methods after initialization.
const { paymentMethods } = useExpressPaymentMethods();
- const paymentMethodSlugs = Object.keys( paymentMethods );
+ const paymentMethodIds = Object.keys( paymentMethods );
const content =
- paymentMethodSlugs.length > 0 ? (
- paymentMethodSlugs.map( ( slug ) => {
+ paymentMethodIds.length > 0 ? (
+ paymentMethodIds.map( ( id ) => {
const expressPaymentMethod = isEditor
- ? paymentMethods[ slug ].edit
- : paymentMethods[ slug ].activeContent;
- const paymentEvents = { dispatch, select };
+ ? paymentMethods[ id ].edit
+ : paymentMethods[ id ].activeContent;
return isValidElement( expressPaymentMethod ) ? (
-
+
{ cloneElement( expressPaymentMethod, {
- checkoutData,
- paymentEvents,
+ ...paymentMethodInterface,
} ) }
) : null;
diff --git a/plugins/woocommerce-blocks/assets/js/base/components/payment-methods/payment-methods.js b/plugins/woocommerce-blocks/assets/js/base/components/payment-methods/payment-methods.js
index 345ffa1dd97..1ccc01d4c64 100644
--- a/plugins/woocommerce-blocks/assets/js/base/components/payment-methods/payment-methods.js
+++ b/plugins/woocommerce-blocks/assets/js/base/components/payment-methods/payment-methods.js
@@ -2,10 +2,8 @@
* External dependencies
*/
import {
- useCheckoutData,
- usePaymentEvents,
- useActivePaymentMethod,
usePaymentMethods,
+ usePaymentMethodInterface,
} from '@woocommerce/base-hooks';
import {
useCallback,
@@ -31,12 +29,12 @@ const noPaymentMethodTab = () => {
};
const createTabs = ( paymentMethods ) => {
- const paymentMethodsKeys = Object.keys( paymentMethods );
- return paymentMethodsKeys.length > 0
- ? paymentMethodsKeys.map( ( key ) => {
- const { label, ariaLabel } = paymentMethods[ key ];
+ const paymentMethodIds = Object.keys( paymentMethods );
+ return paymentMethodIds.length > 0
+ ? paymentMethodIds.map( ( id ) => {
+ const { label, ariaLabel } = paymentMethods[ id ];
return {
- name: key,
+ name: id,
title: () => label,
ariaLabel,
};
@@ -64,21 +62,21 @@ const getPaymentMethod = ( id, paymentMethods, isEditor ) => {
};
const PaymentMethods = () => {
- const [ checkoutData ] = useCheckoutData();
const { isEditor } = useCheckoutContext();
- const { dispatch, select } = usePaymentEvents();
const { isInitialized, paymentMethods } = usePaymentMethods();
const currentPaymentMethods = useRef( paymentMethods );
+ const {
+ activePaymentMethod,
+ setActivePaymentMethod,
+ ...paymentMethodInterface
+ } = usePaymentMethodInterface();
+ const currentPaymentMethodInterface = useRef( paymentMethodInterface );
// update ref on changes
useEffect( () => {
currentPaymentMethods.current = paymentMethods;
- }, [ paymentMethods ] );
-
- const {
- activePaymentMethod,
- setActivePaymentMethod,
- } = useActivePaymentMethod();
+ currentPaymentMethodInterface.current = paymentMethodInterface;
+ }, [ paymentMethods, paymentMethodInterface, activePaymentMethod ] );
const getRenderedTab = useCallback(
() => ( selectedTab ) => {
const paymentMethod = getPaymentMethod(
@@ -86,16 +84,14 @@ const PaymentMethods = () => {
currentPaymentMethods.current,
isEditor
);
- const paymentEvents = { dispatch, select };
return paymentMethod
? cloneElement( paymentMethod, {
- isActive: true,
- checkoutData,
- paymentEvents,
+ activePaymentMethod: paymentMethod.id,
+ ...currentPaymentMethodInterface.current,
} )
: null;
},
- [ checkoutData, dispatch, select, isEditor ]
+ [ isEditor, activePaymentMethod ]
);
if (
! isInitialized ||
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/cart/index.js b/plugins/woocommerce-blocks/assets/js/base/hooks/cart/index.js
new file mode 100644
index 00000000000..8f510164b6b
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/cart/index.js
@@ -0,0 +1,3 @@
+export * from './use-store-cart';
+export * from './use-store-cart-coupons';
+export * from './use-store-cart-item-quantity';
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/use-store-cart-coupons.js b/plugins/woocommerce-blocks/assets/js/base/hooks/cart/use-store-cart-coupons.js
similarity index 100%
rename from plugins/woocommerce-blocks/assets/js/base/hooks/use-store-cart-coupons.js
rename to plugins/woocommerce-blocks/assets/js/base/hooks/cart/use-store-cart-coupons.js
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/use-store-cart-item-quantity.js b/plugins/woocommerce-blocks/assets/js/base/hooks/cart/use-store-cart-item-quantity.js
similarity index 100%
rename from plugins/woocommerce-blocks/assets/js/base/hooks/use-store-cart-item-quantity.js
rename to plugins/woocommerce-blocks/assets/js/base/hooks/cart/use-store-cart-item-quantity.js
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/use-store-cart.js b/plugins/woocommerce-blocks/assets/js/base/hooks/cart/use-store-cart.js
similarity index 98%
rename from plugins/woocommerce-blocks/assets/js/base/hooks/use-store-cart.js
rename to plugins/woocommerce-blocks/assets/js/base/hooks/cart/use-store-cart.js
index 5a22bb556ec..1c59671c576 100644
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/use-store-cart.js
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/cart/use-store-cart.js
@@ -19,6 +19,7 @@ const defaultCartData = {
cartTotals: {},
cartIsLoading: true,
cartErrors: [],
+ shippingRates: [],
};
/**
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/index.js b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/index.js
index 1fb03f107db..ae53992083e 100644
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/index.js
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/index.js
@@ -1,4 +1,2 @@
-export { default as useCheckoutEvents } from './use-checkout-events';
-export { default as useCheckoutNotices } from './use-checkout-notices';
-export { default as useCheckoutRedirectUrls } from './use-checkout-redirect-urls';
-export { default as useCheckoutData } from './use-checkout-data';
+export * from './use-checkout-redirect-url';
+export * from './use-checkout-submit';
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-data.js b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-data.js
deleted file mode 100644
index 860565ed8f2..00000000000
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-data.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// @todo this should be a value object. Provided via wc-settings?
-const currencyObject = {
- code: 'USD',
- precision: 2,
- symbol: '$',
- symbolPosition: 'left',
- decimalSeparator: '.',
- priceFormat: '%1$s%2$s',
- thousandSeparator: ',',
-};
-
-const useCheckoutData = () => {
- // @todo this will likely be a global wp.data store state so that things
- // like shipping selection, quantity changes, etc that affect totals etc
- // will automatically update the payment data. For POC this is hardcoded
- const checkoutData = {
- // this likely should be a float.
- total: 10.123,
- currency: currencyObject,
- // @todo, should this be a standard format of items in the checkout/cart
- // provided to ALL payment methods? Line items includes taxes/shipping
- // costs? Coupons?
- lineItems: [],
- };
- const updateCheckoutData = () => {};
- return [ checkoutData, updateCheckoutData ];
-};
-
-export default useCheckoutData;
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-events.js b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-events.js
deleted file mode 100644
index 03777c8d917..00000000000
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-events.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * External dependencies
- */
-import useCheckoutContext from '@woocommerce/base-context';
-
-export const useCheckoutEvents = () => {
- const {
- isCheckoutComplete,
- setIsCheckoutComplete,
- checkoutHasError,
- setCheckoutHasError,
- isCalculating,
- setIsCalculating,
- } = useCheckoutContext();
- const setHasError = () => {
- setCheckoutHasError( true );
- };
- const cancelCheckoutError = () => {
- setCheckoutHasError( false );
- };
- const setComplete = () => {
- cancelCheckoutError();
- setIsCheckoutComplete( true );
- };
- const setCalculating = () => {
- setIsCalculating( true );
- };
- const cancelCalculating = () => {
- setIsCalculating( false );
- };
- return {
- setIsCheckoutComplete: setComplete,
- setCheckoutHasError: setHasError,
- cancelCheckoutError,
- setIsCalculating: setCalculating,
- cancelCalculating,
- isCalculating,
- isCheckoutComplete,
- checkoutHasError,
- };
-};
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-notices.js b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-notices.js
deleted file mode 100644
index ccd7f2b5906..00000000000
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-notices.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * External dependencies
- */
-import useCheckoutContext from '@woocommerce/base-context';
-
-const useCheckoutNotices = () => {
- const { notices, updateNotices } = useCheckoutContext();
- const addNotice = ( notice ) => {
- updateNotices( ( originalNotices ) => [ ...originalNotices, notice ] );
- };
- const clearAllNotices = () => {
- // @todo...figure out how notices are saved - might need unique ids?
- // Do we have a special notice creator that takes care of that?
- // Use wp notice api?
- updateNotices( [] );
- };
- return {
- notices,
- addNotice,
- clearAllNotices,
- };
-};
-
-export default useCheckoutNotices;
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-place-order-label.js b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-place-order-label.js
deleted file mode 100644
index 8a88cc102d7..00000000000
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-place-order-label.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * External dependencies
- */
-import useCheckoutContext from '@woocommerce/base-context';
-
-export const useCheckoutPlaceOrderLabel = () => {
- const { placeOrderLabel } = useCheckoutContext();
- return placeOrderLabel;
-};
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-redirect-url.js b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-redirect-url.js
new file mode 100644
index 00000000000..ba6d8ad97d8
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-redirect-url.js
@@ -0,0 +1,16 @@
+/**
+ * External dependencies
+ */
+import { useCheckoutContext } from '@woocommerce/base-context';
+
+/**
+ * Returns redirect url interface from checkout context.
+ */
+export const useCheckoutRedirectUrl = () => {
+ const { redirectUrl, dispatchActions } = useCheckoutContext();
+
+ return {
+ redirectUrl,
+ setRedirectUrl: dispatchActions.setRedirectUrl,
+ };
+};
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-redirect-urls.js b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-redirect-urls.js
deleted file mode 100644
index a68ff79e510..00000000000
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-redirect-urls.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * External dependencies
- */
-import useCheckoutContext from '@woocommerce/base-context';
-
-const useCheckoutRedirectUrls = () => {
- const {
- successRedirectUrl,
- setSuccessRedirectUrl,
- failureRedirectUrl,
- setFailureRedirectUrl,
- } = useCheckoutContext();
-
- return {
- successRedirectUrl,
- setSuccessRedirectUrl,
- failureRedirectUrl,
- setFailureRedirectUrl,
- };
-};
-
-export default useCheckoutRedirectUrls;
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-submit.js b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-submit.js
new file mode 100644
index 00000000000..abaec4731c3
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/checkout/use-checkout-submit.js
@@ -0,0 +1,12 @@
+/**
+ * External dependencies
+ */
+import { useCheckoutContext } from '@woocommerce/base-context';
+
+/**
+ * Returns the submitLabel and onSubmit interface from the checkout context
+ */
+export const useCheckoutSubmit = () => {
+ const { submitLabel, onSubmit } = useCheckoutContext();
+ return { submitLabel, onSubmit };
+};
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/index.js b/plugins/woocommerce-blocks/assets/js/base/hooks/index.js
index 2f36d841964..05f82fa0f80 100644
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/index.js
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/index.js
@@ -1,15 +1,13 @@
-export * from './use-query-state';
-export * from './use-shallow-equal';
-export * from './use-store-cart';
-export * from './use-store-cart-coupons';
-export * from './use-store-cart-item-quantity';
-export * from './use-store-products';
-export * from './use-store-notices';
+export * from './cart';
+export * from './checkout';
+export * from './order';
+export * from './payment-methods';
+export * from './shipping';
export * from './use-collection';
export * from './use-collection-header';
export * from './use-collection-data';
export * from './use-previous';
-export * from './checkout';
-export * from './payment-methods';
-export * from './use-shipping-rates';
-export * from './use-select-shipping-rate';
+export * from './use-shallow-equal';
+export * from './use-store-products';
+export * from './use-store-notices';
+export * from './use-query-state';
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/order/index.js b/plugins/woocommerce-blocks/assets/js/base/hooks/order/index.js
new file mode 100644
index 00000000000..2546ed1007f
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/order/index.js
@@ -0,0 +1,2 @@
+export * from './use-store-order';
+export * from './use-billing-data';
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/order/use-billing-data.js b/plugins/woocommerce-blocks/assets/js/base/hooks/order/use-billing-data.js
new file mode 100644
index 00000000000..5ca8dd37ceb
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/order/use-billing-data.js
@@ -0,0 +1,15 @@
+/**
+ * External dependencies
+ */
+import { usePaymentMethodDataContext } from '@woocommerce/base-context';
+
+/**
+ * Exposes billing data api interface from the payment method data context.
+ */
+export const useBillingData = () => {
+ const { billingData, setBillingData } = usePaymentMethodDataContext();
+ return {
+ billingData,
+ setBillingData,
+ };
+};
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/order/use-store-order.js b/plugins/woocommerce-blocks/assets/js/base/hooks/order/use-store-order.js
new file mode 100644
index 00000000000..d8b70c9271e
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/order/use-store-order.js
@@ -0,0 +1,10 @@
+// @todo finish out this hook which will return a store draft order id and
+// order loading (likely from payment data context).
+
+export const useStoreOrder = () => {
+ const orderId = 0;
+ return {
+ orderId,
+ isLoading: false,
+ };
+};
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/constants.js b/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/constants.js
deleted file mode 100644
index 8207038ec98..00000000000
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/constants.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export const STATUS = {
- PRISTINE: 'pristine',
- STARTED: 'started',
- ERROR: 'has_error',
- FAILED: 'failed',
- SUCCESS: 'success',
-};
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/index.js b/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/index.js
index f42576bc699..829faa6f0fc 100644
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/index.js
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/index.js
@@ -1,3 +1,2 @@
-export { default as useActivePaymentMethod } from './use-active-payment-method';
-export { default as usePaymentEvents } from './use-payment-events';
+export * from './use-payment-method-interface';
export * from './use-payment-methods';
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-active-payment-method.js b/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-active-payment-method.js
deleted file mode 100644
index 9dff8fd23a2..00000000000
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-active-payment-method.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * External dependencies
- */
-import { usePaymentMethodDataContext } from '@woocommerce/base-context';
-import { usePaymentMethods } from '@woocommerce/base-hooks';
-import { useEffect } from '@wordpress/element';
-
-const useActivePaymentMethod = () => {
- const {
- activePaymentMethod,
- setActivePaymentMethod,
- } = usePaymentMethodDataContext();
- const { paymentMethods, isInitialized } = usePaymentMethods();
- // if payment method has not been set yet, let's set it.
- useEffect( () => {
- // if not initialized yet bail
- if ( ! isInitialized ) {
- return;
- }
- if ( ! activePaymentMethod && activePaymentMethod !== null ) {
- const paymentMethodIds = Object.keys( paymentMethods );
- setActivePaymentMethod(
- paymentMethodIds.length > 0
- ? paymentMethods[ paymentMethodIds[ 0 ] ].id
- : null
- );
- }
- }, [
- activePaymentMethod,
- setActivePaymentMethod,
- isInitialized,
- paymentMethods,
- ] );
- return { activePaymentMethod, setActivePaymentMethod };
-};
-
-export default useActivePaymentMethod;
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-payment-events.js b/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-payment-events.js
deleted file mode 100644
index de59b1ab19a..00000000000
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-payment-events.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * External dependencies
- */
-import { useState, useMemo } from '@wordpress/element';
-
-/**
- * Internal dependencies
- */
-import { STATUS } from './constants';
-const { STARTED, ERROR, FAILED, SUCCESS, PRISTINE } = STATUS;
-
-const usePaymentEvents = () => {
- const { paymentStatus, setPaymentStatus } = useState( PRISTINE );
- const dispatch = useMemo(
- () => ( {
- started: () => setPaymentStatus( STARTED ),
- error: () => setPaymentStatus( ERROR ),
- failed: () => setPaymentStatus( FAILED ),
- success: () => setPaymentStatus( SUCCESS ),
- } ),
- [ setPaymentStatus ]
- );
- const select = useMemo(
- () => ( {
- isPristine: () => paymentStatus === PRISTINE,
- isStarted: () => paymentStatus === STARTED,
- isFinished: () =>
- [ ERROR, FAILED, SUCCESS ].includes( paymentStatus ),
- hasError: () => paymentStatus === ERROR,
- hasFailed: () => paymentStatus === FAILED,
- isSuccessful: () => paymentStatus === SUCCESS,
- } ),
- [ paymentStatus ]
- );
- return { dispatch, select };
-};
-
-export default usePaymentEvents;
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-payment-method-interface.js b/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-payment-method-interface.js
new file mode 100644
index 00000000000..a9bdb233917
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/payment-methods/use-payment-method-interface.js
@@ -0,0 +1,175 @@
+/**
+ * External dependencies
+ */
+import {
+ useCheckoutContext,
+ usePaymentMethodDataContext,
+ useShippingMethodDataContext,
+} from '@woocommerce/base-context';
+import { __ } from '@wordpress/i18n';
+import { getCurrencyFromPriceResponse } from '@woocommerce/base-utils';
+import { useEffect, useRef } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import {
+ useStoreOrder,
+ useStoreCartCoupons,
+ useStoreCart,
+ useBillingData,
+} from '..';
+
+/**
+ * @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[]} Array for cart total items prepared for use.
+ */
+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 (maybe?).
+/**
+ * @return {RegisteredPaymentMethodProps} Interface to use as payment method props.
+ */
+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,
+ };
+};
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/shipping/index.js b/plugins/woocommerce-blocks/assets/js/base/hooks/shipping/index.js
new file mode 100644
index 00000000000..c3f8b53b5dd
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/shipping/index.js
@@ -0,0 +1,2 @@
+export * from './use-select-shipping-rate';
+export * from './use-shipping-rates';
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/use-select-shipping-rate.js b/plugins/woocommerce-blocks/assets/js/base/hooks/shipping/use-select-shipping-rate.js
similarity index 100%
rename from plugins/woocommerce-blocks/assets/js/base/hooks/use-select-shipping-rate.js
rename to plugins/woocommerce-blocks/assets/js/base/hooks/shipping/use-select-shipping-rate.js
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/use-shipping-rates.js b/plugins/woocommerce-blocks/assets/js/base/hooks/shipping/use-shipping-rates.js
similarity index 95%
rename from plugins/woocommerce-blocks/assets/js/base/hooks/use-shipping-rates.js
rename to plugins/woocommerce-blocks/assets/js/base/hooks/shipping/use-shipping-rates.js
index 2dd81771934..9ce21cd7a3e 100644
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/use-shipping-rates.js
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/shipping/use-shipping-rates.js
@@ -10,8 +10,8 @@ import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data';
/**
* Internal dependencies
*/
-import { useStoreCart } from './use-store-cart';
-import { pluckAddress } from '../utils';
+import { useStoreCart } from '../cart/use-store-cart';
+import { pluckAddress } from '../../utils';
/**
* This is a custom hook that is wired up to the `wc/store/cart/shipping-rates` route.
* Given a a set of default fields keys, this will handle shipping form state and load
diff --git a/plugins/woocommerce-blocks/assets/js/base/hooks/test/use-shipping-rates.js b/plugins/woocommerce-blocks/assets/js/base/hooks/test/use-shipping-rates.js
index 07d78e3ee83..a8dfb74be68 100644
--- a/plugins/woocommerce-blocks/assets/js/base/hooks/test/use-shipping-rates.js
+++ b/plugins/woocommerce-blocks/assets/js/base/hooks/test/use-shipping-rates.js
@@ -8,7 +8,7 @@ import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data';
/**
* Internal dependencies
*/
-import { useShippingRates } from '../use-shipping-rates';
+import { useShippingRates } from '../shipping';
jest.mock( '@woocommerce/block-data', () => ( {
__esModule: true,
diff --git a/plugins/woocommerce-blocks/assets/js/type-defs/registered-payment-method-props.js b/plugins/woocommerce-blocks/assets/js/type-defs/registered-payment-method-props.js
new file mode 100644
index 00000000000..3f7f6c33095
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/type-defs/registered-payment-method-props.js
@@ -0,0 +1,206 @@
+/**
+ * @typedef {import('@woocommerce/type-defs/cart').CartTotalItem} CartTotalItem
+ * @typedef {import('@woocommerce/type-defs/cart').CartShippingOption} CartShippingOption
+ * @typedef {import('@woocommerce/type-defs/cart').CartBillingAddress} CartBillingAddress
+ * @typedef {import('@woocommerce/type-defs/cart').CartShippingAddress} CartShippingAddress
+ * @typedef {import('@woocommerce/type-defs/contexts').PaymentMethodCurrentStatus} PaymentMethodCurrentStatus
+ * @typedef {import('@woocommerce/type-defs/contexts').PaymentStatusDispatch} PaymentStatusDispatch
+ * @typedef {import('@woocommerce/type-defs/contexts').ShippingErrorTypes} ShippingErrorTypes
+ * @typedef {import('@woocommerce/type-defs/settings').WooCommerceSiteCurrency} SiteCurrency
+ */
+
+/**
+ * Payment Event Status Action Creators
+ *
+ * @typedef {Object} PaymentStatusActions
+ *
+ * @property {Function} started
+ * @property {Function} processing
+ * @property {Function} completed
+ * @property {Function} error
+ * @property {Function} failed
+ * @property {Function} success
+ */
+
+/**
+ * @typedef {Object} PaymentMethodShipping
+ *
+ * @property {boolean} required If shipping is required this
+ * will be true.
+ * @property {CartShippingOption[]} options Available shipping options.
+ * @property {Function} selectOptions Used to set the selected
+ * shipping options.
+ * @property {Function} updateAddress Used to update the shipping
+ * address.
+ * @property {Function} setStatus Used to set the current
+ * shipping options status.
+ * @property {Function} selectStatus Returns helpers for
+ * determining the current
+ * shipping options status.
+ * @property {string} status What the current shipping
+ * options status is.
+ */
+
+/**
+ * @typedef {Object} PaymentMethodEvents
+ *
+ * @property {boolean} isCalculating If true, means the cart/checkout is
+ * currently calculating totals.
+ * @property {boolean} isCheckoutComplete If true, means the checkout process
+ * is complete (useful if the payment
+ * method has something to do after
+ * checkout is complete before setting
+ * payment status to complete. Redirect
+ * doesn't happen until both checkout
+ * and payment status is complete)
+ * @property {PaymentStatusActions} dispatchStatus Used to dispatch a payment event.
+ * @property {Function} selectStatus Returns helpers for determining
+ * current payment event status.
+ * @property {string} status What the current payment event status
+ * is.
+ */
+
+/**
+ * @typedef CheckoutStatusProps
+ *
+ * @property {boolean} isCalculating If true then totals are being calculated in
+ * the checkout.
+ * @property {boolean} isComplete If true then the checkout has completed
+ * it's processing.
+ * @property {boolean} isIdle If true then the checkout is idle (no
+ * activity happening).
+ * @property {boolean} isProcessing If true then checkout is processing
+ * (finalizing) the order with the server.
+ */
+
+/**
+ * @typedef PaymentStatusProps
+ *
+ * @property {PaymentMethodCurrentStatus} currentStatus Various status state
+ * indicators for the
+ * payment method based
+ * on it's current
+ * status.
+ * @property {PaymentStatusDispatch} setPaymentStatus Used to dispatch
+ * various payment
+ * status updates.
+ */
+
+/**
+ * @typedef ShippingStatusProps
+ *
+ * @property {string} shippingErrorStatus Current error status for
+ * shipping.
+ * @property {ShippingErrorTypes} shippingErrorTypes An object containing all
+ * the possible types for
+ * shipping error status.
+ */
+
+/**
+ * @typedef ShippingDataProps
+ *
+ * @property {CartShippingOption[]} shippingRates All the available
+ * shipping rates.
+ * @property {boolean} shippingRatesLoading Whether the rates are
+ * loading or not.
+ * @property {string[]} selectedRates An array of selected
+ * rates (rate ids).
+ * @property {Function} setSelectedRates A function for setting
+ * selected rates
+ * (recieves id)
+ * @property {CartShippingAddress} shippingAddress The current set
+ * shipping address.
+ * @property {Function} setShippingAddress A function for setting
+ * the shipping address.
+ * @property {boolean} needsShipping True if cart requires
+ * shipping.
+ */
+
+/**
+ * @typedef BillingDataProps
+ *
+ * @property {CartBillingAddress} billingData The address used for billing.
+ * @property {Function} setBillingData Used to set the cart billing
+ * address.
+ * @property {Object} order The order object for the
+ * purchase.
+ * @property {boolean} orderLoading True if the order is being
+ * loaded.
+ * @property {CartTotalItem} cartTotal The total item for the cart.
+ * @property {SiteCurrency} currency Currency object.
+ * @property {string} country ISO country code for the
+ * default country for the site.
+ * @property {CartTotalItem[]} cartItems The various subtotal amounts.
+ * @property {string[]} appliedCoupons All the coupons that were
+ * applied.
+ */
+
+/**
+ * @typedef EventRegistrationProps
+ *
+ * @property {function()} onCheckoutCompleteSuccess Used to subscribe callbacks
+ * firing when checkout has
+ * completed processing
+ * successfully.
+ * @property {function()} onCheckoutCompleteError Used to subscribe callbacks
+ * firing when checkout has
+ * completed processing with an
+ * error.
+ * @property {function()} onCheckoutProcessing Used to subscribe callbacks
+ * that will fire when checkout
+ * begins processing (as a part
+ * of the processing process).
+ * @property {function()} onShippingRateSuccess Used to subscribe callbacks
+ * that will fire when shipping
+ * rates for a given address have
+ * been received successfully.
+ * @property {function()} onShippingRateFail Used to subscribe callbacks
+ * that will fire when retrieving
+ * shipping rates failed.
+ * @property {function()} onShippingRateSelectSuccess Used to subscribe
+ * callbacks that will fire after
+ * selecting a shipping rate
+ * successfully.
+ * @property {function()} onShippingRateSelectFail Used to subscribe callbacks
+ * that will fire after selecting
+ * a shipping rate unsuccessfully.
+ */
+
+/**
+ * Registered payment method props
+ *
+ * @typedef {Object} RegisteredPaymentMethodProps
+ *
+ * @property {CheckoutStatusProps} checkoutStatus The current
+ * checkout status
+ * exposed as
+ * various boolean
+ * state.
+ * @property {PaymentStatusProps} paymentStatus Various payment
+ * status helpers.
+ * @property {ShippingStatusProps} shippingStatus Various shipping
+ * status helpers.
+ * @property {ShippingDataProps} shippingData Various data
+ * related to
+ * shipping.
+ * @property {BillingDataProps} billing Various billing
+ * data items.
+ * @property {EventRegistrationProps} eventRegistration Various event
+ * registration
+ * helpers for
+ * subscribing
+ * callbacks for
+ * events.
+ * @property {Function} [onSubmit] Used to trigger
+ * checkout
+ * processing.
+ * @property {string} [activePaymentMethod] Indicates what
+ * the active
+ * payment method
+ * is.
+ * @property {function( string )} [setActivePaymentMethod] Used to set the
+ * active payment
+ * method.
+ */
+
+export {};
diff --git a/plugins/woocommerce-blocks/tests/js/jest.config.json b/plugins/woocommerce-blocks/tests/js/jest.config.json
index 4efdbff7dcc..b1cb8520aaf 100644
--- a/plugins/woocommerce-blocks/tests/js/jest.config.json
+++ b/plugins/woocommerce-blocks/tests/js/jest.config.json
@@ -17,6 +17,7 @@
"@woocommerce/base-context(.*)$": "assets/js/base/context/$1",
"@woocommerce/base-hocs(.*)$": "assets/js/base/hocs/$1",
"@woocommerce/base-hooks(.*)$": "assets/js/base/hooks/$1",
+ "@woocommerce/base-utils(.*)$": "assets/js/base/utils",
"@woocommerce/block-data": "assets/js/data"
},
"setupFiles": [