initial commit

This commit is contained in:
2021-12-10 12:03:04 +00:00
commit c46c7ddbf0
3643 changed files with 582794 additions and 0 deletions

View File

@ -0,0 +1,2 @@
export { usePaymentMethodInterface } from './use-payment-method-interface';
export * from './use-payment-methods';

View File

@ -0,0 +1,61 @@
/**
* Internal dependencies
*/
import { prepareTotalItems } from '../utils';
describe( 'prepareTotalItems', () => {
const fixture = {
total_items: '200',
total_items_tax: '20',
total_fees: '100',
total_fees_tax: '10',
total_discount: '350',
total_discount_tax: '50',
total_shipping: '50',
total_shipping_tax: '5',
total_tax: '30',
};
const expected = [
{
key: 'total_items',
label: 'Subtotal:',
value: 200,
valueWithTax: 220,
},
{
key: 'total_fees',
label: 'Fees:',
value: 100,
valueWithTax: 110,
},
{
key: 'total_discount',
label: 'Discount:',
value: 350,
valueWithTax: 400,
},
{
key: 'total_tax',
label: 'Taxes:',
value: 30,
valueWithTax: 30,
},
];
const expectedWithShipping = [
...expected,
{
key: 'total_shipping',
label: 'Shipping:',
value: 50,
valueWithTax: 55,
},
];
it( 'returns expected values when needsShipping is false', () => {
expect( prepareTotalItems( fixture, false ) ).toEqual( expected );
} );
it( 'returns expected values when needsShipping is true', () => {
expect( prepareTotalItems( fixture, true ) ).toEqual(
expectedWithShipping
);
} );
} );

View File

@ -0,0 +1,164 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { getCurrencyFromPriceResponse } from '@woocommerce/price-format';
import { useCallback, useEffect, useRef } from '@wordpress/element';
import PaymentMethodLabel from '@woocommerce/base-components/cart-checkout/payment-method-label';
import PaymentMethodIcons from '@woocommerce/base-components/cart-checkout/payment-method-icons';
import { getSetting } from '@woocommerce/settings';
import deprecated from '@wordpress/deprecated';
/**
* Internal dependencies
*/
import { ValidationInputError } from '../../providers/validation';
import { useStoreCart } from '../cart/use-store-cart';
import { useStoreCartCoupons } from '../cart/use-store-cart-coupons';
import { useEmitResponse } from '../use-emit-response';
import { useCheckoutContext } from '../../providers/cart-checkout/checkout-state';
import { usePaymentMethodDataContext } from '../../providers/cart-checkout/payment-methods';
import { useShippingDataContext } from '../../providers/cart-checkout/shipping';
import { useCustomerDataContext } from '../../providers/cart-checkout/customer';
import { prepareTotalItems } from './utils';
/**
* Returns am interface to use as payment method props.
*/
export const usePaymentMethodInterface = (): Record< string, unknown > => {
const {
isCalculating,
isComplete,
isIdle,
isProcessing,
onCheckoutBeforeProcessing,
onCheckoutValidationBeforeProcessing,
onCheckoutAfterProcessingWithSuccess,
onCheckoutAfterProcessingWithError,
onSubmit,
customerId,
} = useCheckoutContext();
const {
currentStatus,
activePaymentMethod,
onPaymentProcessing,
setExpressPaymentError,
shouldSavePayment,
} = usePaymentMethodDataContext();
const {
shippingErrorStatus,
shippingErrorTypes,
shippingRates,
shippingRatesLoading,
selectedRates,
setSelectedRates,
isSelectingRate,
onShippingRateSuccess,
onShippingRateFail,
onShippingRateSelectSuccess,
onShippingRateSelectFail,
needsShipping,
} = useShippingDataContext();
const {
billingData,
shippingAddress,
setShippingAddress,
} = useCustomerDataContext();
const { cartTotals } = useStoreCart();
const { appliedCoupons } = useStoreCartCoupons();
const { noticeContexts, responseTypes } = useEmitResponse();
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 ] );
const deprecatedSetExpressPaymentError = useCallback(
( errorMessage = '' ) => {
deprecated(
'setExpressPaymentError should only be used by Express Payment Methods (using the provided onError handler).',
{
alternative: '',
plugin: 'woocommerce-gutenberg-products-block',
link:
'https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/4228',
}
);
setExpressPaymentError( errorMessage );
},
[ setExpressPaymentError ]
);
return {
activePaymentMethod,
billing: {
billingData,
cartTotal: currentCartTotal.current,
currency: getCurrencyFromPriceResponse( cartTotals ),
cartTotalItems: currentCartTotals.current,
displayPricesIncludingTax: getSetting(
'displayCartPricesIncludingTax',
false
) as boolean,
appliedCoupons,
customerId,
},
checkoutStatus: {
isCalculating,
isComplete,
isIdle,
isProcessing,
},
components: {
ValidationInputError,
PaymentMethodIcons,
PaymentMethodLabel,
},
emitResponse: {
noticeContexts,
responseTypes,
},
eventRegistration: {
onCheckoutBeforeProcessing,
onCheckoutValidationBeforeProcessing,
onCheckoutAfterProcessingWithSuccess,
onCheckoutAfterProcessingWithError,
onShippingRateSuccess,
onShippingRateFail,
onShippingRateSelectSuccess,
onShippingRateSelectFail,
onPaymentProcessing,
},
onSubmit,
paymentStatus: currentStatus,
setExpressPaymentError: deprecatedSetExpressPaymentError,
shippingData: {
shippingRates,
shippingRatesLoading,
selectedRates,
setSelectedRates,
isSelectingRate,
shippingAddress,
setShippingAddress,
needsShipping,
},
shippingStatus: {
shippingErrorStatus,
shippingErrorTypes,
},
shouldSavePayment,
};
};

View File

@ -0,0 +1,53 @@
/**
* External dependencies
*/
import { useShallowEqual } from '@woocommerce/base-hooks';
import type {
PaymentMethods,
ExpressPaymentMethods,
} from '@woocommerce/type-defs/payments';
/**
* Internal dependencies
*/
import { usePaymentMethodDataContext } from '../../providers/cart-checkout/payment-methods';
interface PaymentMethodState {
paymentMethods: PaymentMethods;
isInitialized: boolean;
}
interface ExpressPaymentMethodState {
paymentMethods: ExpressPaymentMethods;
isInitialized: boolean;
}
const usePaymentMethodState = (
express = false
): PaymentMethodState | ExpressPaymentMethodState => {
const {
paymentMethods,
expressPaymentMethods,
paymentMethodsInitialized,
expressPaymentMethodsInitialized,
} = usePaymentMethodDataContext();
const currentPaymentMethods = useShallowEqual( paymentMethods );
const currentExpressPaymentMethods = useShallowEqual(
expressPaymentMethods
);
return {
paymentMethods: express
? currentExpressPaymentMethods
: currentPaymentMethods,
isInitialized: express
? expressPaymentMethodsInitialized
: paymentMethodsInitialized,
};
};
export const usePaymentMethods = ():
| PaymentMethodState
| ExpressPaymentMethodState => usePaymentMethodState( false );
export const useExpressPaymentMethods = (): ExpressPaymentMethodState =>
usePaymentMethodState( true );

View File

@ -0,0 +1,85 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import {
CartResponseTotals,
objectHasProp,
isString,
} from '@woocommerce/types';
export interface CartTotalItem {
key: string;
label: string;
value: number;
valueWithTax: number;
}
/**
* Prepares the total items into a shape usable for display as passed on to
* registered payment methods.
*
* @param {Object} totals Current cart total items
* @param {boolean} needsShipping Whether or not shipping is needed.
*/
export const prepareTotalItems = (
totals: CartResponseTotals,
needsShipping: boolean
): CartTotalItem[] => {
const newTotals = [];
const factory = ( label: string, property: string ): CartTotalItem => {
const taxProperty = property + '_tax';
const value =
objectHasProp( totals, property ) && isString( totals[ property ] )
? parseInt( totals[ property ] as string, 10 )
: 0;
const tax =
objectHasProp( totals, taxProperty ) &&
isString( totals[ taxProperty ] )
? parseInt( totals[ taxProperty ] as string, 10 )
: 0;
return {
key: property,
label,
value,
valueWithTax: value + tax,
};
};
newTotals.push(
factory(
__( 'Subtotal:', 'woo-gutenberg-products-block' ),
'total_items'
)
);
newTotals.push(
factory( __( 'Fees:', 'woo-gutenberg-products-block' ), 'total_fees' )
);
newTotals.push(
factory(
__( 'Discount:', 'woo-gutenberg-products-block' ),
'total_discount'
)
);
newTotals.push( {
key: 'total_tax',
label: __( 'Taxes:', 'woo-gutenberg-products-block' ),
value: parseInt( totals.total_tax, 10 ),
valueWithTax: parseInt( totals.total_tax, 10 ),
} );
if ( needsShipping ) {
newTotals.push(
factory(
__( 'Shipping:', 'woo-gutenberg-products-block' ),
'total_shipping'
)
);
}
return newTotals;
};