Checkout/Store API - Allow partial pushes without country (https://github.com/woocommerce/woocommerce-blocks/pull/8425)

* Support partial push without country field

* Increase timeout to prevent excessive pushes

* Push on focusout

* Only flush inputs

* change debounce timer to 1s

---------

Co-authored-by: Nadir Seghir <nadir.seghir@gmail.com>
This commit is contained in:
Mike Jolley 2023-02-15 12:00:16 +00:00 committed by Saad Tarhi
parent bc045a1d57
commit a6b6d1c251
3 changed files with 40 additions and 31 deletions

View File

@ -13,7 +13,7 @@ import * as actions from './actions';
import * as resolvers from './resolvers';
import reducer, { State } from './reducers';
import type { SelectFromMap, DispatchFromMap } from '../mapped-types';
import { pushChanges } from './push-changes';
import { pushChanges, flushChanges } from './push-changes';
import {
updatePaymentMethods,
debouncedUpdatePaymentMethods,
@ -34,6 +34,17 @@ const registeredStore = registerStore< State >( STORE_KEY, {
registeredStore.subscribe( pushChanges );
// This will skip the debounce and immediately push changes to the server when a field is blurred.
document.body.addEventListener( 'focusout', ( event: FocusEvent ) => {
if (
event.target &&
event.target instanceof Element &&
event.target.tagName.toLowerCase() === 'input'
) {
flushChanges();
}
} );
// First we will run the updatePaymentMethods function without any debounce to ensure payment methods are ready as soon
// as the cart is loaded. After that, we will unsubscribe this function and instead run the
// debouncedUpdatePaymentMethods function on subsequent cart updates.

View File

@ -34,25 +34,28 @@ const isBillingAddress = (
return 'email' in address;
};
export const trimAddress = ( address: BillingOrShippingAddress ) => {
const trimmedAddress = {
...address,
};
Object.keys( address ).forEach( ( key ) => {
trimmedAddress[ key as keyof BillingOrShippingAddress ] =
address[ key as keyof BillingOrShippingAddress ].trim();
} );
trimmedAddress.postcode = trimmedAddress.postcode
? trimmedAddress.postcode.replace( ' ', '' ).toUpperCase()
: '';
/**
* Trims and normalizes address data for comparison.
*/
export const normalizeAddress = ( address: BillingOrShippingAddress ) => {
const trimmedAddress = Object.entries( address ).reduce(
( acc, [ key, value ] ) => {
if ( key === 'postcode' ) {
acc[ key as keyof BillingOrShippingAddress ] = value
.replace( ' ', '' )
.toUpperCase();
} else {
acc[ key as keyof BillingOrShippingAddress ] = value.trim();
}
return acc;
},
{} as BillingOrShippingAddress
);
return trimmedAddress;
};
/**
* Does a shallow compare of important address data to determine if the cart needs updating on the server. This takes
* the current and previous address into account, as well as the billing email field.
* Does a shallow compare of all address data to determine if the cart needs updating on the server.
*/
const isAddressDirty = < T extends CartBillingAddress | CartShippingAddress >(
// An object containing all previous address information
@ -68,13 +71,12 @@ const isAddressDirty = < T extends CartBillingAddress | CartShippingAddress >(
return true;
}
return (
!! address.country &&
! isShallowEqual(
trimAddress( previousAddress ),
trimAddress( address )
)
const addressMatches = isShallowEqual(
normalizeAddress( previousAddress ),
normalizeAddress( address )
);
return ! addressMatches;
};
type BaseAddressKey = keyof CartBillingAddress | keyof CartShippingAddress;
@ -239,3 +241,7 @@ export const pushChanges = (): void => {
updateCustomerData();
}
};
export const flushChanges = (): void => {
updateCustomerData.flush();
};

View File

@ -167,15 +167,7 @@ abstract class AbstractAddressSchema extends AbstractSchema {
$errors = new \WP_Error();
$address = $this->sanitize_callback( $address, $request, $param );
if ( empty( $address['country'] ) ) {
$errors->add(
'missing_country',
__( 'Country is required', 'woo-gutenberg-products-block' )
);
return $errors;
}
if ( ! in_array( $address['country'], array_keys( wc()->countries->get_countries() ), true ) ) {
if ( ! empty( $address['country'] ) && ! in_array( $address['country'], array_keys( wc()->countries->get_countries() ), true ) ) {
$errors->add(
'invalid_country',
sprintf(