2022-10-05 10:54:48 +00:00
|
|
|
/* eslint-disable @wordpress/no-unsafe-wp-apis */
|
2022-10-04 12:02:28 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2024-05-31 03:49:36 +00:00
|
|
|
import clsx from 'clsx';
|
2022-10-04 12:02:28 +00:00
|
|
|
import { __ } from '@wordpress/i18n';
|
2024-05-06 08:57:52 +00:00
|
|
|
import { PanelBody, ToggleControl } from '@wordpress/components';
|
2022-10-05 10:54:48 +00:00
|
|
|
import { Icon, store, shipping } from '@wordpress/icons';
|
2024-04-02 11:34:32 +00:00
|
|
|
import { ADMIN_URL, getSetting } from '@woocommerce/settings';
|
2022-12-09 09:50:08 +00:00
|
|
|
import { LOCAL_PICKUP_ENABLED } from '@woocommerce/block-settings';
|
2022-10-05 10:54:48 +00:00
|
|
|
import {
|
|
|
|
InspectorControls,
|
|
|
|
useBlockProps,
|
|
|
|
RichText,
|
|
|
|
} from '@wordpress/block-editor';
|
2024-09-16 13:03:20 +00:00
|
|
|
import { Button } from '@ariakit/react';
|
2022-10-05 10:54:48 +00:00
|
|
|
import { useShippingData } from '@woocommerce/base-context/hooks';
|
2022-10-04 12:02:28 +00:00
|
|
|
import { innerBlockAreas } from '@woocommerce/blocks-checkout';
|
2022-10-06 12:00:30 +00:00
|
|
|
import { useDispatch, useSelect } from '@wordpress/data';
|
|
|
|
import { CHECKOUT_STORE_KEY } from '@woocommerce/block-data';
|
2022-10-25 13:59:40 +00:00
|
|
|
import ExternalLinkCard from '@woocommerce/editor-components/external-link-card';
|
2024-04-02 11:34:32 +00:00
|
|
|
import { useEffect } from '@wordpress/element';
|
2022-10-04 12:02:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import {
|
|
|
|
FormStepBlock,
|
|
|
|
AdditionalFields,
|
|
|
|
AdditionalFieldsContent,
|
|
|
|
} from '../../form-step';
|
2022-10-11 15:46:59 +00:00
|
|
|
import { RatePrice, getLocalPickupPrices, getShippingPrices } from './shared';
|
|
|
|
import type { minMaxPrices } from './shared';
|
2022-10-05 10:54:48 +00:00
|
|
|
import './style.scss';
|
2022-12-22 13:36:25 +00:00
|
|
|
import { defaultShippingText, defaultLocalPickupText } from './constants';
|
2022-10-05 10:54:48 +00:00
|
|
|
|
|
|
|
const LocalPickupSelector = ( {
|
|
|
|
checked,
|
|
|
|
rate,
|
|
|
|
showPrice,
|
|
|
|
showIcon,
|
|
|
|
toggleText,
|
|
|
|
setAttributes,
|
2024-05-06 08:57:52 +00:00
|
|
|
onClick,
|
2022-10-05 10:54:48 +00:00
|
|
|
}: {
|
|
|
|
checked: string;
|
2022-10-11 15:46:59 +00:00
|
|
|
rate: minMaxPrices;
|
2022-10-05 10:54:48 +00:00
|
|
|
showPrice: boolean;
|
|
|
|
showIcon: boolean;
|
|
|
|
toggleText: string;
|
2024-05-06 08:57:52 +00:00
|
|
|
onClick: () => void;
|
2022-10-05 10:54:48 +00:00
|
|
|
setAttributes: ( attributes: Record< string, unknown > ) => void;
|
|
|
|
} ) => {
|
|
|
|
return (
|
2024-05-06 08:57:52 +00:00
|
|
|
<Button
|
2024-09-16 13:03:20 +00:00
|
|
|
render={ <div /> }
|
2024-05-31 03:49:36 +00:00
|
|
|
className={ clsx( 'wc-block-checkout__shipping-method-option', {
|
|
|
|
'wc-block-checkout__shipping-method-option--selected':
|
|
|
|
checked === 'pickup',
|
|
|
|
} ) }
|
2024-05-06 08:57:52 +00:00
|
|
|
onClick={ onClick }
|
2022-10-05 10:54:48 +00:00
|
|
|
>
|
|
|
|
{ showIcon === true && (
|
|
|
|
<Icon
|
|
|
|
icon={ store }
|
|
|
|
size={ 28 }
|
2022-10-20 10:48:46 +00:00
|
|
|
className="wc-block-checkout__shipping-method-option-icon"
|
2022-10-05 10:54:48 +00:00
|
|
|
/>
|
|
|
|
) }
|
|
|
|
<RichText
|
|
|
|
value={ toggleText }
|
2022-12-22 13:36:25 +00:00
|
|
|
placeholder={ defaultLocalPickupText }
|
2022-10-05 10:54:48 +00:00
|
|
|
tagName="span"
|
2022-10-20 10:48:46 +00:00
|
|
|
className="wc-block-checkout__shipping-method-option-title"
|
2022-10-05 10:54:48 +00:00
|
|
|
onChange={ ( value ) =>
|
|
|
|
setAttributes( { localPickupText: value } )
|
|
|
|
}
|
|
|
|
__unstableDisableFormats
|
|
|
|
preserveWhiteSpace
|
|
|
|
/>
|
2022-10-11 15:46:59 +00:00
|
|
|
{ showPrice === true && (
|
|
|
|
<RatePrice minRate={ rate.min } maxRate={ rate.max } />
|
|
|
|
) }
|
2024-05-06 08:57:52 +00:00
|
|
|
</Button>
|
2022-10-05 10:54:48 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const ShippingSelector = ( {
|
|
|
|
checked,
|
|
|
|
rate,
|
|
|
|
showPrice,
|
|
|
|
showIcon,
|
|
|
|
toggleText,
|
|
|
|
setAttributes,
|
2024-05-06 08:57:52 +00:00
|
|
|
onClick,
|
2022-10-05 10:54:48 +00:00
|
|
|
}: {
|
|
|
|
checked: string;
|
2022-10-11 15:46:59 +00:00
|
|
|
rate: minMaxPrices;
|
2022-10-05 10:54:48 +00:00
|
|
|
showPrice: boolean;
|
|
|
|
showIcon: boolean;
|
|
|
|
toggleText: string;
|
|
|
|
setAttributes: ( attributes: Record< string, unknown > ) => void;
|
2024-05-06 08:57:52 +00:00
|
|
|
onClick: () => void;
|
2022-10-05 10:54:48 +00:00
|
|
|
} ) => {
|
|
|
|
const Price =
|
2022-10-11 15:46:59 +00:00
|
|
|
rate.min === undefined ? (
|
2022-10-20 10:48:46 +00:00
|
|
|
<span className="wc-block-checkout__shipping-method-option-price">
|
2023-12-12 23:05:20 +00:00
|
|
|
{ __( 'calculated with an address', 'woocommerce' ) }
|
2022-10-05 10:54:48 +00:00
|
|
|
</span>
|
|
|
|
) : (
|
2022-10-11 15:46:59 +00:00
|
|
|
<RatePrice minRate={ rate.min } maxRate={ rate.max } />
|
2022-10-05 10:54:48 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
2024-05-06 08:57:52 +00:00
|
|
|
<Button
|
2024-09-16 13:03:20 +00:00
|
|
|
render={ <div /> }
|
2024-05-31 03:49:36 +00:00
|
|
|
className={ clsx( 'wc-block-checkout__shipping-method-option', {
|
|
|
|
'wc-block-checkout__shipping-method-option--selected':
|
|
|
|
checked === 'shipping',
|
|
|
|
} ) }
|
2024-05-06 08:57:52 +00:00
|
|
|
onClick={ onClick }
|
2022-10-05 10:54:48 +00:00
|
|
|
>
|
|
|
|
{ showIcon === true && (
|
|
|
|
<Icon
|
|
|
|
icon={ shipping }
|
|
|
|
size={ 28 }
|
2022-10-20 10:48:46 +00:00
|
|
|
className="wc-block-checkout__shipping-method-option-icon"
|
2022-10-05 10:54:48 +00:00
|
|
|
/>
|
|
|
|
) }
|
|
|
|
<RichText
|
|
|
|
value={ toggleText }
|
2022-12-22 13:36:25 +00:00
|
|
|
placeholder={ defaultShippingText }
|
2022-10-05 10:54:48 +00:00
|
|
|
tagName="span"
|
2022-10-20 10:48:46 +00:00
|
|
|
className="wc-block-checkout__shipping-method-option-title"
|
2022-10-05 10:54:48 +00:00
|
|
|
onChange={ ( value ) =>
|
|
|
|
setAttributes( { shippingText: value } )
|
|
|
|
}
|
|
|
|
__unstableDisableFormats
|
|
|
|
preserveWhiteSpace
|
|
|
|
/>
|
|
|
|
{ showPrice === true && Price }
|
2024-05-06 08:57:52 +00:00
|
|
|
</Button>
|
2022-10-05 10:54:48 +00:00
|
|
|
);
|
|
|
|
};
|
2022-10-04 12:02:28 +00:00
|
|
|
|
|
|
|
export const Edit = ( {
|
|
|
|
attributes,
|
|
|
|
setAttributes,
|
|
|
|
}: {
|
|
|
|
attributes: {
|
|
|
|
title: string;
|
|
|
|
description: string;
|
|
|
|
showStepNumber: boolean;
|
|
|
|
allowCreateAccount: boolean;
|
2022-10-05 10:54:48 +00:00
|
|
|
localPickupText: string;
|
|
|
|
shippingText: string;
|
2022-10-04 12:02:28 +00:00
|
|
|
showPrice: boolean;
|
|
|
|
showIcon: boolean;
|
|
|
|
className: string;
|
|
|
|
};
|
|
|
|
setAttributes: ( attributes: Record< string, unknown > ) => void;
|
2022-10-18 16:31:06 +00:00
|
|
|
} ): JSX.Element | null => {
|
2024-04-02 11:34:32 +00:00
|
|
|
useEffect( () => {
|
|
|
|
const localPickupTitle = getSetting< string >(
|
|
|
|
'localPickupText',
|
|
|
|
attributes.localPickupText
|
|
|
|
);
|
|
|
|
setAttributes( { localPickupText: localPickupTitle } );
|
|
|
|
// Disable the exhaustive deps rule because we only want to run this on first mount to set the attribute, not
|
|
|
|
// each time the attribute changes.
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [ setAttributes ] );
|
2022-10-06 12:00:30 +00:00
|
|
|
const { setPrefersCollection } = useDispatch( CHECKOUT_STORE_KEY );
|
|
|
|
const { prefersCollection } = useSelect( ( select ) => {
|
|
|
|
const checkoutStore = select( CHECKOUT_STORE_KEY );
|
|
|
|
return {
|
|
|
|
prefersCollection: checkoutStore.prefersCollection(),
|
|
|
|
};
|
|
|
|
} );
|
2022-10-05 10:54:48 +00:00
|
|
|
const { showPrice, showIcon, className, localPickupText, shippingText } =
|
|
|
|
attributes;
|
2022-10-18 16:31:06 +00:00
|
|
|
const {
|
|
|
|
shippingRates,
|
|
|
|
needsShipping,
|
|
|
|
hasCalculatedShipping,
|
|
|
|
isCollectable,
|
|
|
|
} = useShippingData();
|
|
|
|
|
|
|
|
if (
|
|
|
|
! needsShipping ||
|
|
|
|
! hasCalculatedShipping ||
|
|
|
|
! shippingRates ||
|
2022-12-09 09:50:08 +00:00
|
|
|
! isCollectable ||
|
|
|
|
! LOCAL_PICKUP_ENABLED
|
2022-10-18 16:31:06 +00:00
|
|
|
) {
|
|
|
|
return null;
|
|
|
|
}
|
2022-10-06 12:00:30 +00:00
|
|
|
|
|
|
|
const changeView = ( method: string ) => {
|
|
|
|
if ( method === 'pickup' ) {
|
|
|
|
setPrefersCollection( true );
|
|
|
|
} else {
|
|
|
|
setPrefersCollection( false );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-10-04 12:02:28 +00:00
|
|
|
return (
|
|
|
|
<FormStepBlock
|
|
|
|
attributes={ attributes }
|
|
|
|
setAttributes={ setAttributes }
|
2024-05-31 03:49:36 +00:00
|
|
|
className={ clsx(
|
2022-10-20 10:48:46 +00:00
|
|
|
'wc-block-checkout__shipping-method',
|
2022-10-05 10:54:48 +00:00
|
|
|
className
|
2022-10-04 12:02:28 +00:00
|
|
|
) }
|
|
|
|
>
|
|
|
|
<InspectorControls>
|
2023-12-12 23:05:20 +00:00
|
|
|
<PanelBody title={ __( 'Appearance', 'woocommerce' ) }>
|
2022-10-04 12:02:28 +00:00
|
|
|
<p className="wc-block-checkout__controls-text">
|
|
|
|
{ __(
|
|
|
|
'Choose how this block is displayed to your customers.',
|
2023-12-12 22:12:36 +00:00
|
|
|
'woocommerce'
|
2022-10-04 12:02:28 +00:00
|
|
|
) }
|
|
|
|
</p>
|
|
|
|
<ToggleControl
|
2023-12-12 23:05:20 +00:00
|
|
|
label={ __( 'Show icon', 'woocommerce' ) }
|
2022-10-05 10:54:48 +00:00
|
|
|
checked={ showIcon }
|
2022-10-04 12:02:28 +00:00
|
|
|
onChange={ () =>
|
|
|
|
setAttributes( {
|
2022-10-05 10:54:48 +00:00
|
|
|
showIcon: ! showIcon,
|
2022-10-04 12:02:28 +00:00
|
|
|
} )
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
<ToggleControl
|
2023-12-12 23:05:20 +00:00
|
|
|
label={ __( 'Show costs', 'woocommerce' ) }
|
2022-10-05 10:54:48 +00:00
|
|
|
checked={ showPrice }
|
2022-10-04 12:02:28 +00:00
|
|
|
onChange={ () =>
|
|
|
|
setAttributes( {
|
2022-10-05 10:54:48 +00:00
|
|
|
showPrice: ! showPrice,
|
2022-10-04 12:02:28 +00:00
|
|
|
} )
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</PanelBody>
|
2023-12-12 23:05:20 +00:00
|
|
|
<PanelBody title={ __( 'Shipping Methods', 'woocommerce' ) }>
|
2022-10-25 13:59:40 +00:00
|
|
|
<p className="wc-block-checkout__controls-text">
|
|
|
|
{ __(
|
|
|
|
'Methods can be made managed in your store settings.',
|
2023-12-12 22:12:36 +00:00
|
|
|
'woocommerce'
|
2022-10-25 13:59:40 +00:00
|
|
|
) }
|
|
|
|
</p>
|
|
|
|
<ExternalLinkCard
|
|
|
|
key={ 'shipping_methods' }
|
|
|
|
href={ `${ ADMIN_URL }admin.php?page=wc-settings&tab=shipping` }
|
2023-12-12 23:05:20 +00:00
|
|
|
title={ __( 'Shipping', 'woocommerce' ) }
|
2022-10-25 13:59:40 +00:00
|
|
|
description={ __(
|
|
|
|
'Manage your shipping zones, methods, and rates.',
|
2023-12-12 22:12:36 +00:00
|
|
|
'woocommerce'
|
2022-10-25 13:59:40 +00:00
|
|
|
) }
|
|
|
|
/>
|
|
|
|
<ExternalLinkCard
|
|
|
|
key={ 'pickup_location' }
|
|
|
|
href={ `${ ADMIN_URL }admin.php?page=wc-settings&tab=shipping§ion=pickup_location` }
|
2024-04-30 12:59:03 +00:00
|
|
|
title={ __( 'Pickup', 'woocommerce' ) }
|
2022-10-25 13:59:40 +00:00
|
|
|
description={ __(
|
|
|
|
'Allow customers to choose a local pickup location during checkout.',
|
2023-12-12 22:12:36 +00:00
|
|
|
'woocommerce'
|
2022-10-25 13:59:40 +00:00
|
|
|
) }
|
|
|
|
/>
|
|
|
|
</PanelBody>
|
2022-10-04 12:02:28 +00:00
|
|
|
</InspectorControls>
|
2024-05-06 08:57:52 +00:00
|
|
|
<div
|
2022-10-20 10:48:46 +00:00
|
|
|
id="shipping-method"
|
|
|
|
className="wc-block-checkout__shipping-method-container"
|
2024-05-06 08:57:52 +00:00
|
|
|
role="radiogroup"
|
2022-10-05 10:54:48 +00:00
|
|
|
>
|
|
|
|
<ShippingSelector
|
2022-10-06 12:00:30 +00:00
|
|
|
checked={ prefersCollection ? 'pickup' : 'shipping' }
|
2022-10-11 15:46:59 +00:00
|
|
|
rate={ getShippingPrices(
|
|
|
|
shippingRates[ 0 ]?.shipping_rates
|
|
|
|
) }
|
2024-05-06 08:57:52 +00:00
|
|
|
onClick={ () => {
|
|
|
|
changeView( 'shipping' );
|
|
|
|
} }
|
2022-10-05 10:54:48 +00:00
|
|
|
showPrice={ showPrice }
|
|
|
|
showIcon={ showIcon }
|
|
|
|
setAttributes={ setAttributes }
|
|
|
|
toggleText={ shippingText }
|
|
|
|
/>
|
|
|
|
<LocalPickupSelector
|
2022-10-06 12:00:30 +00:00
|
|
|
checked={ prefersCollection ? 'pickup' : 'shipping' }
|
2022-10-11 15:46:59 +00:00
|
|
|
rate={ getLocalPickupPrices(
|
|
|
|
shippingRates[ 0 ]?.shipping_rates
|
|
|
|
) }
|
2022-10-05 10:54:48 +00:00
|
|
|
showPrice={ showPrice }
|
2024-05-06 08:57:52 +00:00
|
|
|
onClick={ () => {
|
|
|
|
changeView( 'pickup' );
|
|
|
|
} }
|
2022-10-05 10:54:48 +00:00
|
|
|
showIcon={ showIcon }
|
|
|
|
setAttributes={ setAttributes }
|
|
|
|
toggleText={ localPickupText }
|
|
|
|
/>
|
2024-05-06 08:57:52 +00:00
|
|
|
</div>
|
2022-10-20 10:48:46 +00:00
|
|
|
<AdditionalFields block={ innerBlockAreas.SHIPPING_METHOD } />
|
2022-10-04 12:02:28 +00:00
|
|
|
</FormStepBlock>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const Save = (): JSX.Element => {
|
|
|
|
return (
|
|
|
|
<div { ...useBlockProps.save() }>
|
|
|
|
<AdditionalFieldsContent />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|