Block Checkout: Fix default shipping selection on toggle pickup (#49718)
* Default selection is blank so it can be selected on mount * Prevent notice displaying until rate selections are complete * changelog
This commit is contained in:
parent
bbdb289c84
commit
e8d899b6f3
|
@ -38,15 +38,9 @@ const PackageRates = ( {
|
|||
const previousSelectedRateId = usePrevious( selectedRateId );
|
||||
|
||||
// Store selected rate ID in local state so shipping rates changes are shown in the UI instantly.
|
||||
const [ selectedOption, setSelectedOption ] = useState( () => {
|
||||
if ( selectedRateId ) {
|
||||
return selectedRateId;
|
||||
}
|
||||
// Default to first rate if no rate is selected.
|
||||
if ( rates.length > 0 ) {
|
||||
return rates[ 0 ].rate_id;
|
||||
}
|
||||
} );
|
||||
const [ selectedOption, setSelectedOption ] = useState(
|
||||
selectedRateId ?? ''
|
||||
);
|
||||
|
||||
// Update the selected option if cart state changes in the data store.
|
||||
useEffect( () => {
|
||||
|
@ -61,7 +55,6 @@ const PackageRates = ( {
|
|||
|
||||
// Update the selected option if there is no rate selected on mount.
|
||||
useEffect( () => {
|
||||
// The useState callback run only once, so we need this to update it right fetching new rates.
|
||||
if ( ! selectedOption && rates.length > 0 ) {
|
||||
setSelectedOption( rates[ 0 ].rate_id );
|
||||
onSelectRate( rates[ 0 ].rate_id );
|
||||
|
|
|
@ -6,8 +6,6 @@ import { CART_STORE_KEY, CHECKOUT_STORE_KEY } from '@woocommerce/block-data';
|
|||
import { useEffect } from '@wordpress/element';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { hasShippingRate } from '@woocommerce/base-components/cart-checkout/totals/shipping/utils';
|
||||
import { hasCollectableRate } from '@woocommerce/base-utils';
|
||||
import { isString } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -18,64 +16,36 @@ export const useShowShippingTotalWarning = () => {
|
|||
const context = 'woocommerce/checkout-totals-block';
|
||||
const errorNoticeId = 'wc-blocks-totals-shipping-warning';
|
||||
|
||||
const { shippingRates } = useShippingData();
|
||||
const { shippingRates, hasSelectedLocalPickup } = useShippingData();
|
||||
const hasRates = hasShippingRate( shippingRates );
|
||||
const {
|
||||
prefersCollection,
|
||||
isRateBeingSelected,
|
||||
shippingNotices,
|
||||
cartData,
|
||||
} = useSelect( ( select ) => {
|
||||
return {
|
||||
cartData: select( CART_STORE_KEY ).getCartData(),
|
||||
prefersCollection: select( CHECKOUT_STORE_KEY ).prefersCollection(),
|
||||
isRateBeingSelected:
|
||||
select( CART_STORE_KEY ).isShippingRateBeingSelected(),
|
||||
shippingNotices: select( 'core/notices' ).getNotices( context ),
|
||||
};
|
||||
} );
|
||||
const { prefersCollection, isRateBeingSelected, shippingNotices } =
|
||||
useSelect( ( select ) => {
|
||||
return {
|
||||
prefersCollection:
|
||||
select( CHECKOUT_STORE_KEY ).prefersCollection(),
|
||||
isRateBeingSelected:
|
||||
select( CART_STORE_KEY ).isShippingRateBeingSelected(),
|
||||
shippingNotices: select( 'core/notices' ).getNotices( context ),
|
||||
};
|
||||
} );
|
||||
const { createInfoNotice, removeNotice } = useDispatch( 'core/notices' );
|
||||
|
||||
useEffect( () => {
|
||||
const isShowingNotice = shippingNotices.length > 0;
|
||||
const hasMismatch = ! prefersCollection && hasSelectedLocalPickup;
|
||||
|
||||
if ( ! hasRates || isRateBeingSelected ) {
|
||||
// Early return because shipping rates were not yet loaded from the cart data store, or the user is changing
|
||||
// rate, no need to alter the notice until we know what the actual rate is.
|
||||
if ( isShowingNotice ) {
|
||||
// Removes the notice in case it was already shown.
|
||||
removeNotice( errorNoticeId, context );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedRates = cartData?.shippingRates?.reduce(
|
||||
( acc: string[], rate ) => {
|
||||
const selectedRateForPackage = rate.shipping_rates.find(
|
||||
( shippingRate ) => {
|
||||
return shippingRate.selected;
|
||||
}
|
||||
);
|
||||
if (
|
||||
typeof selectedRateForPackage?.method_id !== 'undefined'
|
||||
) {
|
||||
acc.push( selectedRateForPackage?.method_id );
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
const isPickupRateSelected = Object.values( selectedRates ).some(
|
||||
( rate: unknown ) => {
|
||||
if ( isString( rate ) ) {
|
||||
return hasCollectableRate( rate );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
// There is a mismatch between the method the user chose (pickup or shipping) and the currently selected rate.
|
||||
if (
|
||||
hasRates &&
|
||||
! prefersCollection &&
|
||||
! isRateBeingSelected &&
|
||||
isPickupRateSelected &&
|
||||
shippingNotices.length === 0
|
||||
) {
|
||||
if ( hasMismatch && ! isShowingNotice ) {
|
||||
createInfoNotice(
|
||||
__(
|
||||
'Totals will be recalculated when a valid shipping method is selected.',
|
||||
|
@ -91,14 +61,11 @@ export const useShowShippingTotalWarning = () => {
|
|||
}
|
||||
|
||||
// Don't show the notice if they have selected local pickup, or if they have selected a valid regular shipping rate.
|
||||
if (
|
||||
( prefersCollection || ! isPickupRateSelected ) &&
|
||||
shippingNotices.length > 0
|
||||
) {
|
||||
if ( ! hasMismatch && isShowingNotice ) {
|
||||
removeNotice( errorNoticeId, context );
|
||||
}
|
||||
}, [
|
||||
cartData?.shippingRates,
|
||||
hasSelectedLocalPickup,
|
||||
createInfoNotice,
|
||||
hasRates,
|
||||
isRateBeingSelected,
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Fix default shipping selection when changing between pickup and shipping on block checkout.
|
Loading…
Reference in New Issue