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:
Mike Jolley 2024-07-23 16:25:35 +01:00 committed by GitHub
parent bbdb289c84
commit e8d899b6f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 64 deletions

View File

@ -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 );

View File

@ -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,

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Fix default shipping selection when changing between pickup and shipping on block checkout.