woocommerce/plugins/woocommerce-blocks/assets/js/blocks/checkout/inner-blocks/checkout-pickup-options-block/block.tsx

159 lines
4.2 KiB
TypeScript
Raw Normal View History

/**
* External dependencies
*/
import { _n, __ } from '@wordpress/i18n';
import {
useState,
useEffect,
useCallback,
createInterpolateElement,
} from '@wordpress/element';
import { useShippingData } from '@woocommerce/base-context/hooks';
import { getCurrencyFromPriceResponse } from '@woocommerce/price-format';
import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount';
import { decodeEntities } from '@wordpress/html-entities';
import { getSetting } from '@woocommerce/settings';
import { Icon, mapMarker } from '@wordpress/icons';
import RadioControl from '@woocommerce/base-components/radio-control';
import type { RadioControlOption } from '@woocommerce/base-components/radio-control/types';
import { CartShippingPackageShippingRate } from '@woocommerce/types';
Allow third party methods to appear in local pickup area (https://github.com/woocommerce/woocommerce-blocks/pull/8256) * Add get_collectible_method_ids function * Add collectibleMethodIds to asset data registry * Check whether method id is pickup_location/in collectibleMethodIds * Allow selectShippingRate to be called without a package id * Prevent collectible methods showing in the main shipping area * Remove unnecessary pluck and add pickup_location to returned array * No longer insert pickup_location in collectibleMethodIds * Allow third party methods to influence low/high collection price * Update useShippingData to consider any collectible method * Add hasSelectedLocalPickup to shipping types * Add dependency to selectShippingRate in useShippingData * Register collectibleMethodIds as a callback This is so the shipping methods get change to register before this is called. Passing a callback to `add` means it won't be called until just before it is output. * Update supports key to 'local_pickup' * Rename utils/shipping-rates to TS * Convert to TS, add isPackageRateCollectible & hasCollectableRate * Add tests for hasCollectableRate and isPackageRateCollectible * Update shipping controller to output only method names * Make PickupLocation shipping method support local_pickup * Set prefersCollection based on rate ID being collectible * Remove need to retrieve settings and use helper function instead * rename hasCollectableRate to hasCollectibleRate * Use array_reduce and update comments in get_local_pickup_method_ids * Switch order of array_unique and array_values * Remove unneeded dependency * Hyphenate local-pickup so it follows the same format as other features * Update use of collectible to collectable * Change supports feature to be hyphenated
2023-02-03 16:00:24 +00:00
import { isPackageRateCollectable } from '@woocommerce/base-utils';
/**
* Internal dependencies
*/
import './style.scss';
const getPickupLocation = (
option: CartShippingPackageShippingRate
): string => {
if ( option?.meta_data ) {
const match = option.meta_data.find(
( meta ) => meta.key === 'pickup_location'
);
return match ? match.value : '';
}
return '';
};
const getPickupAddress = (
option: CartShippingPackageShippingRate
): string => {
if ( option?.meta_data ) {
const match = option.meta_data.find(
( meta ) => meta.key === 'pickup_address'
);
return match ? match.value : '';
}
return '';
};
const getPickupDetails = (
option: CartShippingPackageShippingRate
): string => {
if ( option?.meta_data ) {
const match = option.meta_data.find(
( meta ) => meta.key === 'pickup_details'
);
return match ? match.value : '';
}
return '';
};
const renderPickupLocation = (
option: CartShippingPackageShippingRate,
packageCount: number
): RadioControlOption => {
const priceWithTaxes = getSetting( 'displayCartPricesIncludingTax', false )
? option.price + option.taxes
: option.price;
const location = getPickupLocation( option );
const address = getPickupAddress( option );
const details = getPickupDetails( option );
return {
value: option.rate_id,
label: location
? decodeEntities( location )
: decodeEntities( option.name ),
secondaryLabel:
parseInt( priceWithTaxes, 10 ) > 0 ? (
createInterpolateElement(
/* translators: %1$s name of the product (ie: Sunglasses), %2$d number of units in the current cart package */
_n(
'<price/>',
'<price/> x <packageCount/> packages',
packageCount,
'woo-gutenberg-products-block'
),
{
price: (
<FormattedMonetaryAmount
currency={ getCurrencyFromPriceResponse(
option
) }
value={ priceWithTaxes }
/>
),
packageCount: <>{ packageCount }</>,
}
)
) : (
<em>{ __( 'free', 'woo-gutenberg-products-block' ) }</em>
),
description: decodeEntities( details ),
secondaryDescription: address ? (
<>
<Icon
icon={ mapMarker }
className="wc-block-editor-components-block-icon"
/>
{ decodeEntities( address ) }
</>
) : undefined,
};
};
const Block = (): JSX.Element | null => {
const { shippingRates, selectShippingRate } = useShippingData();
// Get pickup locations from the first shipping package.
const pickupLocations = ( shippingRates[ 0 ]?.shipping_rates || [] ).filter(
Allow third party methods to appear in local pickup area (https://github.com/woocommerce/woocommerce-blocks/pull/8256) * Add get_collectible_method_ids function * Add collectibleMethodIds to asset data registry * Check whether method id is pickup_location/in collectibleMethodIds * Allow selectShippingRate to be called without a package id * Prevent collectible methods showing in the main shipping area * Remove unnecessary pluck and add pickup_location to returned array * No longer insert pickup_location in collectibleMethodIds * Allow third party methods to influence low/high collection price * Update useShippingData to consider any collectible method * Add hasSelectedLocalPickup to shipping types * Add dependency to selectShippingRate in useShippingData * Register collectibleMethodIds as a callback This is so the shipping methods get change to register before this is called. Passing a callback to `add` means it won't be called until just before it is output. * Update supports key to 'local_pickup' * Rename utils/shipping-rates to TS * Convert to TS, add isPackageRateCollectible & hasCollectableRate * Add tests for hasCollectableRate and isPackageRateCollectible * Update shipping controller to output only method names * Make PickupLocation shipping method support local_pickup * Set prefersCollection based on rate ID being collectible * Remove need to retrieve settings and use helper function instead * rename hasCollectableRate to hasCollectibleRate * Use array_reduce and update comments in get_local_pickup_method_ids * Switch order of array_unique and array_values * Remove unneeded dependency * Hyphenate local-pickup so it follows the same format as other features * Update use of collectible to collectable * Change supports feature to be hyphenated
2023-02-03 16:00:24 +00:00
isPackageRateCollectable
);
const [ selectedOption, setSelectedOption ] = useState< string >(
() => pickupLocations.find( ( rate ) => rate.selected )?.rate_id || ''
);
const onSelectRate = useCallback(
( rateId: string ) => {
selectShippingRate( rateId );
},
[ selectShippingRate ]
);
// Update the selected option if there is no rate selected on mount.
useEffect( () => {
if ( ! selectedOption && pickupLocations[ 0 ] ) {
setSelectedOption( pickupLocations[ 0 ].rate_id );
onSelectRate( pickupLocations[ 0 ].rate_id );
}
}, [ onSelectRate, pickupLocations, selectedOption ] );
return (
<RadioControl
onChange={ ( value: string ) => {
setSelectedOption( value );
onSelectRate( value );
} }
selected={ selectedOption }
options={ pickupLocations.map( ( location ) =>
renderPickupLocation( location, shippingRates.length )
) }
/>
);
};
export default Block;