2022-10-11 15:46:59 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2023-01-20 14:34:25 +00:00
|
|
|
import { _n, __ } from '@wordpress/i18n';
|
2022-11-18 13:20:04 +00:00
|
|
|
import {
|
|
|
|
useState,
|
|
|
|
useEffect,
|
|
|
|
useCallback,
|
|
|
|
createInterpolateElement,
|
|
|
|
} from '@wordpress/element';
|
2022-12-15 23:52:03 +00:00
|
|
|
import { useShippingData } from '@woocommerce/base-context/hooks';
|
2022-10-11 15:46:59 +00:00
|
|
|
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';
|
2022-11-18 13:20:04 +00:00
|
|
|
import RadioControl from '@woocommerce/base-components/radio-control';
|
|
|
|
import type { RadioControlOption } from '@woocommerce/base-components/radio-control/types';
|
|
|
|
import { CartShippingPackageShippingRate } from '@woocommerce/types';
|
2022-10-11 15:46:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import './style.scss';
|
|
|
|
|
|
|
|
const getPickupLocation = (
|
|
|
|
option: CartShippingPackageShippingRate
|
|
|
|
): string => {
|
|
|
|
if ( option?.meta_data ) {
|
|
|
|
const match = option.meta_data.find(
|
2022-11-18 13:20:04 +00:00
|
|
|
( meta ) => meta.key === 'pickup_location'
|
2022-10-11 15:46:59 +00:00
|
|
|
);
|
|
|
|
return match ? match.value : '';
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
};
|
|
|
|
|
|
|
|
const getPickupAddress = (
|
|
|
|
option: CartShippingPackageShippingRate
|
|
|
|
): string => {
|
|
|
|
if ( option?.meta_data ) {
|
|
|
|
const match = option.meta_data.find(
|
2022-11-18 13:20:04 +00:00
|
|
|
( meta ) => meta.key === 'pickup_address'
|
2022-10-11 15:46:59 +00:00
|
|
|
);
|
|
|
|
return match ? match.value : '';
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
};
|
|
|
|
|
2022-12-08 15:24:49 +00:00
|
|
|
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 '';
|
|
|
|
};
|
|
|
|
|
2022-11-18 13:20:04 +00:00
|
|
|
const renderPickupLocation = (
|
|
|
|
option: CartShippingPackageShippingRate,
|
|
|
|
packageCount: number
|
|
|
|
): RadioControlOption => {
|
2022-10-11 15:46:59 +00:00
|
|
|
const priceWithTaxes = getSetting( 'displayCartPricesIncludingTax', false )
|
2022-11-18 13:20:04 +00:00
|
|
|
? option.price + option.taxes
|
|
|
|
: option.price;
|
2022-10-11 15:46:59 +00:00
|
|
|
const location = getPickupLocation( option );
|
|
|
|
const address = getPickupAddress( option );
|
2022-12-08 15:24:49 +00:00
|
|
|
const details = getPickupDetails( option );
|
|
|
|
|
2022-10-11 15:46:59 +00:00
|
|
|
return {
|
|
|
|
value: option.rate_id,
|
2022-10-18 16:31:06 +00:00
|
|
|
label: location
|
|
|
|
? decodeEntities( location )
|
|
|
|
: decodeEntities( option.name ),
|
2023-01-20 14:34:25 +00:00
|
|
|
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>
|
2022-11-18 13:20:04 +00:00
|
|
|
),
|
2022-12-08 15:24:49 +00:00
|
|
|
description: decodeEntities( details ),
|
2022-10-11 15:46:59 +00:00
|
|
|
secondaryDescription: address ? (
|
|
|
|
<>
|
|
|
|
<Icon
|
|
|
|
icon={ mapMarker }
|
|
|
|
className="wc-block-editor-components-block-icon"
|
|
|
|
/>
|
|
|
|
{ decodeEntities( address ) }
|
|
|
|
</>
|
|
|
|
) : undefined,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const Block = (): JSX.Element | null => {
|
2022-12-15 23:52:03 +00:00
|
|
|
const { shippingRates, selectShippingRate } = useShippingData();
|
2023-01-12 12:19:19 +00:00
|
|
|
|
|
|
|
// Get pickup locations from the first shipping package.
|
|
|
|
const pickupLocations = ( shippingRates[ 0 ]?.shipping_rates || [] ).filter(
|
|
|
|
( { method_id: methodId } ) => methodId === 'pickup_location'
|
|
|
|
);
|
|
|
|
|
|
|
|
const [ selectedOption, setSelectedOption ] = useState< string >(
|
|
|
|
() => pickupLocations.find( ( rate ) => rate.selected )?.rate_id || ''
|
|
|
|
);
|
|
|
|
|
2022-11-18 13:20:04 +00:00
|
|
|
const onSelectRate = useCallback(
|
|
|
|
( rateId: string ) => {
|
|
|
|
selectShippingRate( rateId );
|
|
|
|
},
|
|
|
|
[ selectShippingRate ]
|
|
|
|
);
|
2022-10-11 15:46:59 +00:00
|
|
|
|
2022-11-18 13:20:04 +00:00
|
|
|
// 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 );
|
2022-10-18 16:31:06 +00:00
|
|
|
}
|
2022-11-18 13:20:04 +00:00
|
|
|
}, [ onSelectRate, pickupLocations, selectedOption ] );
|
2022-10-18 16:31:06 +00:00
|
|
|
|
2022-10-11 15:46:59 +00:00
|
|
|
return (
|
2022-11-18 13:20:04 +00:00
|
|
|
<RadioControl
|
|
|
|
onChange={ ( value: string ) => {
|
|
|
|
setSelectedOption( value );
|
|
|
|
onSelectRate( value );
|
|
|
|
} }
|
|
|
|
selected={ selectedOption }
|
|
|
|
options={ pickupLocations.map( ( location ) =>
|
|
|
|
renderPickupLocation( location, shippingRates.length )
|
|
|
|
) }
|
2022-10-11 15:46:59 +00:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Block;
|