diff --git a/plugins/woocommerce-blocks/assets/js/base/context/providers/cart-checkout/checkout-processor.ts b/plugins/woocommerce-blocks/assets/js/base/context/providers/cart-checkout/checkout-processor.ts index 6d9de6979af..701e4a635dc 100644 --- a/plugins/woocommerce-blocks/assets/js/base/context/providers/cart-checkout/checkout-processor.ts +++ b/plugins/woocommerce-blocks/assets/js/base/context/providers/cart-checkout/checkout-processor.ts @@ -14,7 +14,7 @@ import { emptyHiddenAddressFields, removeAllNotices, } from '@woocommerce/base-utils'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch, useSelect, select as selectStore } from '@wordpress/data'; import { CHECKOUT_STORE_KEY, PAYMENT_STORE_KEY, @@ -160,6 +160,19 @@ const CheckoutProcessor = () => { const checkValidation = useCallback( () => { if ( hasValidationErrors() ) { + // If there is a shipping rates validation error, return the error message to be displayed. + if ( + selectStore( VALIDATION_STORE_KEY ).getValidationError( + 'shipping-rates-error' + ) !== undefined + ) { + return { + errorMessage: __( + 'Sorry, this order requires a shipping option.', + 'woo-gutenberg-products-block' + ), + }; + } return false; } if ( hasPaymentError ) { diff --git a/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-method-block/block.tsx b/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-method-block/block.tsx index d6bbbfac0de..7cd95fba945 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-method-block/block.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-method-block/block.tsx @@ -9,6 +9,9 @@ import { } from 'wordpress-components'; import classnames from 'classnames'; import { Icon, store, shipping } from '@wordpress/icons'; +import { useEffect } from '@wordpress/element'; +import { VALIDATION_STORE_KEY } from '@woocommerce/block-data'; +import { useDispatch } from '@wordpress/data'; /** * Internal dependencies @@ -19,6 +22,14 @@ import type { minMaxPrices } from './shared'; import { defaultLocalPickupText, defaultShippingText } from './constants'; import { shippingAddressHasValidationErrors } from '../../../../data/cart/utils'; +const SHIPPING_RATE_ERROR = { + hidden: true, + message: __( + 'Shipping options are not available', + 'woo-gutenberg-products-block' + ), +}; + const LocalPickupSelector = ( { checked, rate, @@ -83,6 +94,23 @@ const ShippingSelector = ( { } ) => { const rateShouldBeHidden = shippingCostRequiresAddress && shippingAddressHasValidationErrors(); + const hasShippingPrices = rate.min !== undefined && rate.max !== undefined; + const { setValidationErrors, clearValidationError } = + useDispatch( VALIDATION_STORE_KEY ); + useEffect( () => { + if ( checked === 'shipping' && ! hasShippingPrices ) { + setValidationErrors( { + 'shipping-rates-error': SHIPPING_RATE_ERROR, + } ); + } else { + clearValidationError( 'shipping-rates-error' ); + } + }, [ + checked, + clearValidationError, + hasShippingPrices, + setValidationErrors, + ] ); const Price = rate.min === undefined || rateShouldBeHidden ? ( diff --git a/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-method-block/shared/rate-price.tsx b/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-method-block/shared/rate-price.tsx index fb96f8dca7c..30e2395154c 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-method-block/shared/rate-price.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-method-block/shared/rate-price.tsx @@ -16,7 +16,7 @@ export const RatePrice = ( { }: { minRate: CartShippingPackageShippingRate | undefined; maxRate: CartShippingPackageShippingRate | undefined; - multiple: boolean; + multiple?: boolean; } ) => { if ( minRate === undefined || maxRate === undefined ) { return null;