diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/shipping-location/index.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/shipping-location/index.tsx
index b57fc0985d1..4f0c4f0b5b0 100644
--- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/shipping-location/index.tsx
+++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/shipping-location/index.tsx
@@ -2,56 +2,15 @@
* External dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
-import { ShippingAddress, getSetting } from '@woocommerce/settings';
-import { decodeEntities } from '@wordpress/html-entities';
interface ShippingLocationProps {
- address: ShippingAddress;
+ formattedLocation: string | null;
}
-/**
- * Shows a formatted shipping location.
- *
- * @param {Object} props Incoming props for the component.
- * @param {Object} props.address Incoming address information.
- */
+// Shows a formatted shipping location.
const ShippingLocation = ( {
- address,
+ formattedLocation,
}: ShippingLocationProps ): JSX.Element | null => {
- // we bail early if we don't have an address.
- if ( Object.values( address ).length === 0 ) {
- return null;
- }
- const shippingCountries = getSetting( 'shippingCountries', {} ) as Record<
- string,
- string
- >;
- const shippingStates = getSetting( 'shippingStates', {} ) as Record<
- string,
- Record< string, string >
- >;
- const formattedCountry =
- typeof shippingCountries[ address.country ] === 'string'
- ? decodeEntities( shippingCountries[ address.country ] )
- : '';
-
- const formattedState =
- typeof shippingStates[ address.country ] === 'object' &&
- typeof shippingStates[ address.country ][ address.state ] === 'string'
- ? decodeEntities(
- shippingStates[ address.country ][ address.state ]
- )
- : address.state;
-
- const addressParts = [];
-
- addressParts.push( address.postcode.toUpperCase() );
- addressParts.push( address.city );
- addressParts.push( formattedState );
- addressParts.push( formattedCountry );
-
- const formattedLocation = addressParts.filter( Boolean ).join( ', ' );
-
if ( ! formattedLocation ) {
return null;
}
diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx
index 9607ab9fd7f..887f34dbe31 100644
--- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx
+++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx
@@ -15,15 +15,20 @@ export const CalculatorButton = ( {
setIsShippingCalculatorOpen,
}: CalculatorButtonProps ): JSX.Element => {
return (
-
+
);
};
diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/index.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/index.tsx
index 06febfcafd9..5b2fade1a9e 100644
--- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/index.tsx
+++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/index.tsx
@@ -10,6 +10,7 @@ import type { Currency } from '@woocommerce/price-format';
import { ShippingVia } from '@woocommerce/base-components/cart-checkout/totals/shipping/shipping-via';
import { useSelect } from '@wordpress/data';
import { CHECKOUT_STORE_KEY } from '@woocommerce/block-data';
+import { isAddressComplete } from '@woocommerce/base-utils';
/**
* Internal dependencies
@@ -67,6 +68,8 @@ export const TotalsShipping = ( {
}
);
+ const addressComplete = isAddressComplete( shippingAddress );
+
return (
- )
+ hasRates && cartHasCalculatedShipping
+ ? totalShippingValue
+ : // if address is not complete, display the link to add an address.
+ ! addressComplete && (
+
+ )
}
description={
- hasRates && cartHasCalculatedShipping ? (
+ // If address is complete, display the shipping address.
+ ( hasRates && cartHasCalculatedShipping ) ||
+ addressComplete ? (
<>
) }
diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx
index 0df38408184..c2be8f15954 100644
--- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx
+++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx
@@ -3,6 +3,11 @@
*/
import { __ } from '@wordpress/i18n';
import { EnteredAddress } from '@woocommerce/settings';
+import {
+ formatShippingAddress,
+ isAddressComplete,
+} from '@woocommerce/base-utils';
+import { useEditorContext } from '@woocommerce/base-context';
/**
* Internal dependencies
@@ -23,13 +28,21 @@ export const ShippingAddress = ( {
setIsShippingCalculatorOpen,
shippingAddress,
}: ShippingAddressProps ): JSX.Element | null => {
+ const addressComplete = isAddressComplete( shippingAddress );
+ const { isEditor } = useEditorContext();
+
+ // If the address is incomplete, and we're not in the editor, don't show anything.
+ if ( ! addressComplete && ! isEditor ) {
+ return null;
+ }
+ const formattedLocation = formatShippingAddress( shippingAddress );
return (
<>
-
+
{ showCalculator && (
diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx
index 78fcf12a674..a6bbe6dcdad 100644
--- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx
+++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx
@@ -2,8 +2,6 @@
* External dependencies
*/
import { __ } from '@wordpress/i18n';
-import { Notice } from 'wordpress-components';
-import classnames from 'classnames';
import type { CartResponseShippingRate } from '@woocommerce/types';
/**
@@ -15,12 +13,14 @@ export interface ShippingRateSelectorProps {
hasRates: boolean;
shippingRates: CartResponseShippingRate[];
isLoadingRates: boolean;
+ isAddressComplete: boolean;
}
export const ShippingRateSelector = ( {
hasRates,
shippingRates,
isLoadingRates,
+ isAddressComplete,
}: ShippingRateSelectorProps ): JSX.Element => {
const legend = hasRates
? __( 'Shipping options', 'woo-gutenberg-products-block' )
@@ -31,18 +31,13 @@ export const ShippingRateSelector = ( {
- { __(
- 'No shipping options were found.',
- 'woo-gutenberg-products-block'
- ) }
-
+ <>
+ { isAddressComplete &&
+ __(
+ 'There are no shipping options available. Please check your shipping address.',
+ 'woo-gutenberg-products-block'
+ ) }
+ >
}
shippingRates={ shippingRates }
isLoadingRates={ isLoadingRates }
diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/style.scss b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/style.scss
index 9562503f8bf..5e9cf3b2b20 100644
--- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/style.scss
+++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/style.scss
@@ -20,12 +20,16 @@
flex-basis: 100%;
text-align: left;
}
+ margin-top: ($gap-small);
}
.wc-block-components-shipping-rates-control__no-results-notice {
margin: 0 0 em($gap-small);
}
+ .wc-block-components-totals-shipping__change-address__link {
+ font-weight: normal;
+ }
.wc-block-components-totals-shipping__change-address-button {
@include link-button();
diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/test/index.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/test/index.tsx
new file mode 100644
index 00000000000..daa43f4a967
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/test/index.tsx
@@ -0,0 +1,282 @@
+/**
+ * External dependencies
+ */
+import { screen, render } from '@testing-library/react';
+import { SlotFillProvider } from '@woocommerce/blocks-checkout';
+import { previewCart as mockPreviewCart } from '@woocommerce/resource-previews';
+import * as wpData from '@wordpress/data';
+import * as baseContextHooks from '@woocommerce/base-context/hooks';
+
+/**
+ * Internal dependencies
+ */
+import { TotalsShipping } from '../index';
+
+jest.mock( '@wordpress/data', () => ( {
+ __esModule: true,
+ ...jest.requireActual( '@wordpress/data' ),
+ useSelect: jest.fn(),
+} ) );
+
+wpData.useSelect.mockImplementation( () => {
+ return { prefersCollection: false };
+} );
+
+const shippingAddress = {
+ first_name: 'John',
+ last_name: 'Doe',
+ company: 'Company',
+ address_1: '409 Main Street',
+ address_2: 'Apt 1',
+ city: 'London',
+ postcode: 'W1T 4JG',
+ country: 'GB',
+ state: '',
+ email: 'john.doe@company',
+ phone: '+1234567890',
+};
+
+jest.mock( '@woocommerce/base-context/hooks', () => {
+ return {
+ __esModule: true,
+ ...jest.requireActual( '@woocommerce/base-context/hooks' ),
+ useShippingData: jest.fn(),
+ useStoreCart: jest.fn(),
+ };
+} );
+baseContextHooks.useShippingData.mockReturnValue( {
+ needsShipping: true,
+ shippingRates: [
+ {
+ package_id: 0,
+ name: 'Shipping method',
+ destination: {
+ address_1: '',
+ address_2: '',
+ city: '',
+ state: '',
+ postcode: '',
+ country: '',
+ },
+ items: [
+ {
+ key: 'fb0c0a746719a7596f296344b80cb2b6',
+ name: 'Hoodie - Blue, Yes',
+ quantity: 1,
+ },
+ {
+ key: '1f0e3dad99908345f7439f8ffabdffc4',
+ name: 'Beanie',
+ quantity: 1,
+ },
+ ],
+ shipping_rates: [
+ {
+ rate_id: 'flat_rate:1',
+ name: 'Flat rate',
+ description: '',
+ delivery_time: '',
+ price: '500',
+ taxes: '0',
+ instance_id: 1,
+ method_id: 'flat_rate',
+ meta_data: [
+ {
+ key: 'Items',
+ value: 'Hoodie - Blue, Yes × 1, Beanie × 1',
+ },
+ ],
+ selected: false,
+ currency_code: 'USD',
+ currency_symbol: '$',
+ currency_minor_unit: 2,
+ currency_decimal_separator: '.',
+ currency_thousand_separator: ',',
+ currency_prefix: '$',
+ currency_suffix: '',
+ },
+ {
+ rate_id: 'local_pickup:2',
+ name: 'Local pickup',
+ description: '',
+ delivery_time: '',
+ price: '0',
+ taxes: '0',
+ instance_id: 2,
+ method_id: 'local_pickup',
+ meta_data: [
+ {
+ key: 'Items',
+ value: 'Hoodie - Blue, Yes × 1, Beanie × 1',
+ },
+ ],
+ selected: false,
+ currency_code: 'USD',
+ currency_symbol: '$',
+ currency_minor_unit: 2,
+ currency_decimal_separator: '.',
+ currency_thousand_separator: ',',
+ currency_prefix: '$',
+ currency_suffix: '',
+ },
+ {
+ rate_id: 'free_shipping:5',
+ name: 'Free shipping',
+ description: '',
+ delivery_time: '',
+ price: '0',
+ taxes: '0',
+ instance_id: 5,
+ method_id: 'free_shipping',
+ meta_data: [
+ {
+ key: 'Items',
+ value: 'Hoodie - Blue, Yes × 1, Beanie × 1',
+ },
+ ],
+ selected: true,
+ currency_code: 'USD',
+ currency_symbol: '$',
+ currency_minor_unit: 2,
+ currency_decimal_separator: '.',
+ currency_thousand_separator: ',',
+ currency_prefix: '$',
+ currency_suffix: '',
+ },
+ ],
+ },
+ ],
+} );
+baseContextHooks.useStoreCart.mockReturnValue( {
+ cartItems: mockPreviewCart.items,
+ cartTotals: [ mockPreviewCart.totals ],
+ cartCoupons: mockPreviewCart.coupons,
+ cartFees: mockPreviewCart.fees,
+ cartNeedsShipping: mockPreviewCart.needs_shipping,
+ shippingRates: [],
+ shippingAddress,
+ billingAddress: mockPreviewCart.billing_address,
+ cartHasCalculatedShipping: mockPreviewCart.has_calculated_shipping,
+ isLoadingRates: false,
+} );
+
+describe( 'TotalsShipping', () => {
+ it( 'should show correct calculator button label if address is complete', () => {
+ render(
+
+
+
+ );
+ expect(
+ screen.getByText(
+ 'Shipping to W1T 4JG, London, United Kingdom (UK)'
+ )
+ ).toBeInTheDocument();
+ expect( screen.getByText( 'Change address' ) ).toBeInTheDocument();
+ } );
+ it( 'should show correct calculator button label if address is incomplete', () => {
+ baseContextHooks.useStoreCart.mockReturnValue( {
+ cartItems: mockPreviewCart.items,
+ cartTotals: [ mockPreviewCart.totals ],
+ cartCoupons: mockPreviewCart.coupons,
+ cartFees: mockPreviewCart.fees,
+ cartNeedsShipping: mockPreviewCart.needs_shipping,
+ shippingRates: [],
+ shippingAddress: {
+ ...shippingAddress,
+ city: '',
+ country: '',
+ postcode: '',
+ },
+ billingAddress: mockPreviewCart.billing_address,
+ cartHasCalculatedShipping: mockPreviewCart.has_calculated_shipping,
+ isLoadingRates: false,
+ } );
+ render(
+
+
+
+ );
+ expect(
+ screen.queryByText( 'Change address' )
+ ).not.toBeInTheDocument();
+ expect(
+ screen.getByText( 'Add an address for shipping options' )
+ ).toBeInTheDocument();
+ } );
+ it( 'does not show the calculator button when default rates are available and no address has been entered', () => {
+ baseContextHooks.useStoreCart.mockReturnValue( {
+ cartItems: mockPreviewCart.items,
+ cartTotals: [ mockPreviewCart.totals ],
+ cartCoupons: mockPreviewCart.coupons,
+ cartFees: mockPreviewCart.fees,
+ cartNeedsShipping: mockPreviewCart.needs_shipping,
+ shippingRates: mockPreviewCart.shipping_rates,
+ shippingAddress: {
+ ...shippingAddress,
+ city: '',
+ country: '',
+ postcode: '',
+ },
+ billingAddress: mockPreviewCart.billing_address,
+ cartHasCalculatedShipping: mockPreviewCart.has_calculated_shipping,
+ isLoadingRates: false,
+ } );
+ render(
+
+
+
+ );
+ expect(
+ screen.queryByText( 'Change address' )
+ ).not.toBeInTheDocument();
+ expect(
+ screen.queryByText( 'Add an address for shipping options' )
+ ).not.toBeInTheDocument();
+ } );
+} );
diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/test/shipping-placeholder.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/test/shipping-placeholder.tsx
new file mode 100644
index 00000000000..469bb35d61a
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/totals/shipping/test/shipping-placeholder.tsx
@@ -0,0 +1,36 @@
+/**
+ * External dependencies
+ */
+import { screen, render } from '@testing-library/react';
+
+/**
+ * Internal dependencies
+ */
+import ShippingPlaceholder from '../shipping-placeholder';
+
+describe( 'ShippingPlaceholder', () => {
+ it( 'should show correct text if showCalculator is false', () => {
+ const { rerender } = render(
+
+ );
+ expect(
+ screen.getByText( 'No shipping options available' )
+ ).toBeInTheDocument();
+ rerender(
+
+ );
+ expect(
+ screen.getByText( 'Calculated during checkout' )
+ ).toBeInTheDocument();
+ } );
+} );
diff --git a/plugins/woocommerce-blocks/assets/js/base/utils/address.ts b/plugins/woocommerce-blocks/assets/js/base/utils/address.ts
index e3738fb614b..f894db86997 100644
--- a/plugins/woocommerce-blocks/assets/js/base/utils/address.ts
+++ b/plugins/woocommerce-blocks/assets/js/base/utils/address.ts
@@ -11,7 +11,9 @@ import {
defaultAddressFields,
ShippingAddress,
BillingAddress,
+ getSetting,
} from '@woocommerce/settings';
+import { decodeEntities } from '@wordpress/html-entities';
/**
* Compare two addresses and see if they are the same.
@@ -100,3 +102,62 @@ export const emptyHiddenAddressFields = <
return newAddress;
};
+
+/*
+ * Formats a shipping address for display.
+ *
+ * @param {Object} address The address to format.
+ * @return {string | null} The formatted address or null if no address is provided.
+ */
+export const formatShippingAddress = (
+ address: ShippingAddress | BillingAddress
+): string | null => {
+ // We bail early if we don't have an address.
+ if ( Object.values( address ).length === 0 ) {
+ return null;
+ }
+ const shippingCountries = getSetting< Record< string, string > >(
+ 'shippingCountries',
+ {}
+ );
+ const shippingStates = getSetting< Record< string, string > >(
+ 'shippingStates',
+ {}
+ );
+ const formattedCountry =
+ typeof shippingCountries[ address.country ] === 'string'
+ ? decodeEntities( shippingCountries[ address.country ] )
+ : '';
+
+ const formattedState =
+ typeof shippingStates[ address.country ] === 'object' &&
+ typeof shippingStates[ address.country ][ address.state ] === 'string'
+ ? decodeEntities(
+ shippingStates[ address.country ][ address.state ]
+ )
+ : address.state;
+
+ const addressParts = [];
+
+ addressParts.push( address.postcode.toUpperCase() );
+ addressParts.push( address.city );
+ addressParts.push( formattedState );
+ addressParts.push( formattedCountry );
+
+ const formattedLocation = addressParts.filter( Boolean ).join( ', ' );
+
+ if ( ! formattedLocation ) {
+ return null;
+ }
+
+ return formattedLocation;
+};
+
+/**
+ * Returns true if the address has a city and country.
+ */
+export const isAddressComplete = (
+ address: ShippingAddress | BillingAddress
+): boolean => {
+ return !! address.city && !! address.country;
+};
diff --git a/plugins/woocommerce-blocks/assets/js/base/utils/test/address.ts b/plugins/woocommerce-blocks/assets/js/base/utils/test/address.ts
index 8f454ad2058..27d31eef5b0 100644
--- a/plugins/woocommerce-blocks/assets/js/base/utils/test/address.ts
+++ b/plugins/woocommerce-blocks/assets/js/base/utils/test/address.ts
@@ -1,7 +1,11 @@
/**
* External dependencies
*/
-import { emptyHiddenAddressFields } from '@woocommerce/base-utils';
+import {
+ emptyHiddenAddressFields,
+ isAddressComplete,
+ formatShippingAddress,
+} from '@woocommerce/base-utils';
describe( 'emptyHiddenAddressFields', () => {
it( "Removes state from an address where the country doesn't use states", () => {
@@ -22,3 +26,101 @@ describe( 'emptyHiddenAddressFields', () => {
expect( filteredAddress ).toHaveProperty( 'state', '' );
} );
} );
+
+describe( 'isAddressComplete', () => {
+ it( 'correctly checks empty addresses', () => {
+ const address = {
+ first_name: '',
+ last_name: '',
+ company: '',
+ address_1: '',
+ address_2: '',
+ city: '',
+ postcode: '',
+ country: '',
+ state: '',
+ email: '',
+ phone: '',
+ };
+ expect( isAddressComplete( address ) ).toBe( false );
+ } );
+
+ it( 'correctly checks incomplete addresses', () => {
+ const address = {
+ first_name: 'John',
+ last_name: 'Doe',
+ company: 'Company',
+ address_1: '409 Main Street',
+ address_2: 'Apt 1',
+ city: '',
+ postcode: '',
+ country: '',
+ state: '',
+ email: 'john.doe@company',
+ phone: '+1234567890',
+ };
+ expect( isAddressComplete( address ) ).toBe( false );
+
+ address.city = 'London';
+ expect( isAddressComplete( address ) ).toBe( false );
+
+ address.postcode = 'W1T 4JG';
+ address.country = 'GB';
+ expect( isAddressComplete( address ) ).toBe( true );
+ } );
+
+ it( 'correctly checks complete addresses', () => {
+ const address = {
+ first_name: 'John',
+ last_name: 'Doe',
+ company: 'Company',
+ address_1: '409 Main Street',
+ address_2: 'Apt 1',
+ city: 'London',
+ postcode: 'W1T 4JG',
+ country: 'GB',
+ state: '',
+ email: 'john.doe@company',
+ phone: '+1234567890',
+ };
+ expect( isAddressComplete( address ) ).toBe( true );
+ } );
+} );
+
+describe( 'formatShippingAddress', () => {
+ it( 'returns null if address is empty', () => {
+ const address = {
+ first_name: '',
+ last_name: '',
+ company: '',
+ address_1: '',
+ address_2: '',
+ city: '',
+ postcode: '',
+ country: '',
+ state: '',
+ email: '',
+ phone: '',
+ };
+ expect( formatShippingAddress( address ) ).toBe( null );
+ } );
+
+ it( 'correctly returns the formatted address', () => {
+ const address = {
+ first_name: 'John',
+ last_name: 'Doe',
+ company: 'Company',
+ address_1: '409 Main Street',
+ address_2: 'Apt 1',
+ city: 'London',
+ postcode: 'W1T 4JG',
+ country: 'GB',
+ state: '',
+ email: 'john.doe@company',
+ phone: '+1234567890',
+ };
+ expect( formatShippingAddress( address ) ).toBe(
+ 'W1T 4JG, London, United Kingdom (UK)'
+ );
+ } );
+} );
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx b/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx
index 84fd6e36b67..7ca7678c2b1 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx
+++ b/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx
@@ -26,6 +26,7 @@ const Block = ( {
showRateSelector={ false }
values={ cartTotals }
currency={ totalsCurrency }
+ isCheckout={ true }
/>
);
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx b/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx
index 89e67fb766e..86f26557eed 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx
+++ b/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx
@@ -7,22 +7,21 @@ import { ShippingRatesControl } from '@woocommerce/base-components/cart-checkout
import {
getShippingRatesPackageCount,
hasCollectableRate,
+ isAddressComplete,
} from '@woocommerce/base-utils';
import { getCurrencyFromPriceResponse } from '@woocommerce/price-format';
import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount';
import { useEditorContext, noticeContexts } from '@woocommerce/base-context';
import { StoreNoticesContainer } from '@woocommerce/blocks-checkout';
import { decodeEntities } from '@wordpress/html-entities';
-import { Notice } from 'wordpress-components';
-import classnames from 'classnames';
import { getSetting } from '@woocommerce/settings';
import type {
PackageRateOption,
CartShippingPackageShippingRate,
} from '@woocommerce/types';
-import type { ReactElement } from 'react';
-import { useSelect } from '@wordpress/data';
import { CART_STORE_KEY } from '@woocommerce/block-data';
+import { useSelect } from '@wordpress/data';
+import type { ReactElement } from 'react';
/**
* Internal dependencies
@@ -87,11 +86,16 @@ const Block = ( {
} )
: shippingRates;
+ const shippingAddress = useSelect( ( select ) => {
+ return select( CART_STORE_KEY ).getCustomerData()?.shippingAddress;
+ } );
+
if ( ! needsShipping ) {
return null;
}
- const shippingAddressIsComplete = ! shippingAddressHasValidationErrors();
+ const shippingAddressHasErrors = ! shippingAddressHasValidationErrors();
+ const addressComplete = isAddressComplete( shippingAddress );
const shippingRatesPackageCount =
getShippingRatesPackageCount( shippingRates );
@@ -99,7 +103,7 @@ const Block = ( {
if (
( ! hasCalculatedShipping && ! shippingRatesPackageCount ) ||
( shippingCostRequiresAddress &&
- ( ! shippingAddressPushed || ! shippingAddressIsComplete ) )
+ ( ! shippingAddressPushed || ! shippingAddressHasErrors ) )
) {
return (
@@ -121,18 +125,17 @@ const Block = ( {
) : (
- { __(
- 'There are no shipping options available. Please check your shipping address.',
- 'woo-gutenberg-products-block'
- ) }
-
+ <>
+ { addressComplete
+ ? __(
+ 'There are no shipping options available. Please check your shipping address.',
+ 'woo-gutenberg-products-block'
+ )
+ : __(
+ 'Add a shipping address to view shipping options.',
+ 'woo-gutenberg-products-block'
+ ) }
+ >
}
renderOption={ renderShippingRatesControlOption }
collapsible={ false }