woocommerce/plugins/woocommerce-blocks/assets/js/base/context/hooks/use-show-shipping-total-war...

111 lines
3.1 KiB
TypeScript
Raw Normal View History

Fix total shipping display info when no shipping method is available (https://github.com/woocommerce/woocommerce-blocks/pull/8819) * Fix total shipping info when no shipping are available * Fix a logical error for displaying shipping info * Fix failing unit tests * Run unit test for the Cart instead of the Checkout The calculator is only available for the Cart Block, so it doesn't make sense to run this test for the Checkout Block * Fix no shipping methods and incomplete address conflict When there are no shipping methods (except for local pickup), we would like to inform the shopper that there are no shipping options available even though the address is complete The solution we found is to check the address on the Cart Block only * Refactor code * Check whether rate is collectible without using hardcoded id * Correctly negate hasCollectibleRate result * Add notice when shipping is selected but no methods are available yet (https://github.com/woocommerce/woocommerce-blocks/pull/9171) * Create useShippingTotalWarning hook * Show notices above checkout sidebar * Call hook to show notice in Checkout block * Remove unused imports * Update hook name to useShowShippingTotalWarning * Move hook to its own file * Import shipping data internally (without alias) * Remove unused imports * Move import to correct place * Return early to avoid if else * Refactor useShowShippingTotalWarning * Get shipping rates directly from the cart instead of the hook * Show shipping cost when price information is available * Check if the passed rates are considered selected * Prevent errors when no rates are available --------- Co-authored-by: Thomas Roberts <thomas.roberts@automattic.com> Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> Co-authored-by: Tarun Vijwani <tarun.vijwani@automattic.com>
2023-05-25 05:31:15 +00:00
/**
* External dependencies
*/
import { useDispatch, useSelect } from '@wordpress/data';
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
*/
import { useShippingData } from './shipping/use-shipping-data';
export const useShowShippingTotalWarning = () => {
const context = 'woocommerce/checkout-totals-block';
const errorNoticeId = 'wc-blocks-totals-shipping-warning';
const { shippingRates } = 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 { createInfoNotice, removeNotice } = useDispatch( 'core/notices' );
useEffect( () => {
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.
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
) {
createInfoNotice(
__(
'Totals will be recalculated when a valid shipping method is selected.',
'woo-gutenberg-products-block'
),
{
id: 'wc-blocks-totals-shipping-warning',
isDismissible: false,
context,
}
);
return;
}
// 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
) {
removeNotice( errorNoticeId, context );
}
}, [
cartData?.shippingRates,
createInfoNotice,
hasRates,
isRateBeingSelected,
prefersCollection,
removeNotice,
shippingNotices,
shippingRates,
] );
};