2021-07-22 11:03:00 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import { __ } from '@wordpress/i18n';
|
2024-05-31 03:49:36 +00:00
|
|
|
import clsx from 'clsx';
|
2021-07-22 11:03:00 +00:00
|
|
|
import {
|
|
|
|
InnerBlocks,
|
|
|
|
useBlockProps,
|
|
|
|
InspectorControls,
|
|
|
|
} from '@wordpress/block-editor';
|
|
|
|
import { SidebarLayout } from '@woocommerce/base-components/sidebar-layout';
|
2022-08-12 14:23:08 +00:00
|
|
|
import { CheckoutProvider, EditorProvider } from '@woocommerce/base-context';
|
2021-07-22 11:03:00 +00:00
|
|
|
import {
|
|
|
|
previewCart,
|
|
|
|
previewSavedPaymentMethods,
|
|
|
|
} from '@woocommerce/resource-previews';
|
2024-05-21 08:48:24 +00:00
|
|
|
import { PanelBody, ToggleControl, RadioControl } from '@wordpress/components';
|
2023-01-06 14:53:53 +00:00
|
|
|
import { SlotFillProvider } from '@woocommerce/blocks-checkout';
|
2021-10-15 09:48:57 +00:00
|
|
|
import type { TemplateArray } from '@wordpress/blocks';
|
2023-10-19 15:43:43 +00:00
|
|
|
import { useEffect, useRef } from '@wordpress/element';
|
|
|
|
import { getQueryArg } from '@wordpress/url';
|
|
|
|
import { dispatch, select } from '@wordpress/data';
|
2021-07-22 11:03:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
2022-04-01 13:45:18 +00:00
|
|
|
import './inner-blocks';
|
2021-07-22 11:03:00 +00:00
|
|
|
import './styles/editor.scss';
|
2022-04-05 10:14:32 +00:00
|
|
|
import {
|
|
|
|
addClassToBody,
|
2022-08-12 14:23:08 +00:00
|
|
|
BlockSettings,
|
2022-04-05 10:14:32 +00:00
|
|
|
useBlockPropsWithLocking,
|
2022-04-07 13:47:58 +00:00
|
|
|
} from '../cart-checkout-shared';
|
2022-08-16 10:51:26 +00:00
|
|
|
import '../cart-checkout-shared/sidebar-notices';
|
2021-07-22 11:03:00 +00:00
|
|
|
import { CheckoutBlockContext, CheckoutBlockControlsContext } from './context';
|
|
|
|
import type { Attributes } from './types';
|
|
|
|
|
|
|
|
// This is adds a class to body to signal if the selected block is locked
|
|
|
|
addClassToBody();
|
|
|
|
|
|
|
|
// Array of allowed block names.
|
|
|
|
const ALLOWED_BLOCKS: string[] = [
|
|
|
|
'woocommerce/checkout-fields-block',
|
|
|
|
'woocommerce/checkout-totals-block',
|
|
|
|
];
|
|
|
|
|
|
|
|
export const Edit = ( {
|
2023-10-19 15:43:43 +00:00
|
|
|
clientId,
|
2021-07-22 11:03:00 +00:00
|
|
|
attributes,
|
|
|
|
setAttributes,
|
|
|
|
}: {
|
2023-10-19 15:43:43 +00:00
|
|
|
clientId: string;
|
2021-07-22 11:03:00 +00:00
|
|
|
attributes: Attributes;
|
|
|
|
setAttributes: ( attributes: Record< string, unknown > ) => undefined;
|
|
|
|
} ): JSX.Element => {
|
|
|
|
const {
|
|
|
|
showCompanyField,
|
|
|
|
requireCompanyField,
|
|
|
|
showApartmentField,
|
2024-05-21 08:48:24 +00:00
|
|
|
requireApartmentField,
|
2021-07-22 11:03:00 +00:00
|
|
|
showPhoneField,
|
|
|
|
requirePhoneField,
|
|
|
|
showOrderNotes,
|
|
|
|
showPolicyLinks,
|
|
|
|
showReturnToCart,
|
|
|
|
showRateAfterTaxName,
|
|
|
|
cartPageId,
|
2023-03-30 14:15:00 +00:00
|
|
|
isPreview = false,
|
2024-05-22 14:03:48 +00:00
|
|
|
showFormStepNumbers = false,
|
2021-07-22 11:03:00 +00:00
|
|
|
} = attributes;
|
|
|
|
|
2023-10-19 15:43:43 +00:00
|
|
|
// This focuses on the block when a certain query param is found. This is used on the link from the task list.
|
|
|
|
const focus = useRef( getQueryArg( window.location.href, 'focus' ) );
|
|
|
|
|
|
|
|
useEffect( () => {
|
|
|
|
if (
|
|
|
|
focus.current === 'checkout' &&
|
|
|
|
! select( 'core/block-editor' ).hasSelectedBlock()
|
|
|
|
) {
|
|
|
|
dispatch( 'core/block-editor' ).selectBlock( clientId );
|
|
|
|
dispatch( 'core/interface' ).enableComplementaryArea(
|
|
|
|
'core/edit-site',
|
|
|
|
'edit-site/block-inspector'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}, [ clientId ] );
|
|
|
|
|
2021-10-15 09:48:57 +00:00
|
|
|
const defaultTemplate = [
|
|
|
|
[ 'woocommerce/checkout-totals-block', {}, [] ],
|
2024-08-20 13:42:38 +00:00
|
|
|
[ 'woocommerce/checkout-fields-block', {}, [] ],
|
2021-10-15 09:48:57 +00:00
|
|
|
] as TemplateArray;
|
2021-07-22 11:03:00 +00:00
|
|
|
|
|
|
|
const toggleAttribute = ( key: keyof Attributes ): void => {
|
|
|
|
const newAttributes = {} as Partial< Attributes >;
|
|
|
|
newAttributes[ key ] = ! ( attributes[ key ] as boolean );
|
|
|
|
setAttributes( newAttributes );
|
|
|
|
};
|
|
|
|
|
|
|
|
const addressFieldControls = (): JSX.Element => (
|
|
|
|
<InspectorControls>
|
2024-05-22 14:03:48 +00:00
|
|
|
<PanelBody title={ __( 'Form Step Options', 'woocommerce' ) }>
|
|
|
|
<ToggleControl
|
|
|
|
label={ __( 'Show form step numbers', 'woocommerce' ) }
|
|
|
|
checked={ showFormStepNumbers }
|
|
|
|
onChange={ () =>
|
|
|
|
setAttributes( {
|
|
|
|
showFormStepNumbers: ! showFormStepNumbers,
|
|
|
|
} )
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</PanelBody>
|
2023-12-12 23:05:20 +00:00
|
|
|
<PanelBody title={ __( 'Address Fields', 'woocommerce' ) }>
|
2021-07-22 11:03:00 +00:00
|
|
|
<p className="wc-block-checkout__controls-text">
|
|
|
|
{ __(
|
|
|
|
'Show or hide fields in the checkout address forms.',
|
2023-12-12 22:12:36 +00:00
|
|
|
'woocommerce'
|
2021-07-22 11:03:00 +00:00
|
|
|
) }
|
|
|
|
</p>
|
|
|
|
<ToggleControl
|
2023-12-12 22:12:36 +00:00
|
|
|
label={ __( 'Company', 'woocommerce' ) }
|
2021-07-22 11:03:00 +00:00
|
|
|
checked={ showCompanyField }
|
|
|
|
onChange={ () => toggleAttribute( 'showCompanyField' ) }
|
|
|
|
/>
|
|
|
|
{ showCompanyField && (
|
2024-05-21 08:48:24 +00:00
|
|
|
<RadioControl
|
|
|
|
selected={ requireCompanyField }
|
|
|
|
options={ [
|
|
|
|
{
|
|
|
|
label: __( 'Optional', 'woocommerce' ),
|
|
|
|
value: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: __( 'Required', 'woocommerce' ),
|
|
|
|
value: true,
|
|
|
|
},
|
|
|
|
] }
|
2021-07-22 11:03:00 +00:00
|
|
|
onChange={ () =>
|
|
|
|
toggleAttribute( 'requireCompanyField' )
|
|
|
|
}
|
2024-05-21 08:48:24 +00:00
|
|
|
className="components-base-control--nested wc-block-components-require-company-field"
|
2021-07-22 11:03:00 +00:00
|
|
|
/>
|
|
|
|
) }
|
|
|
|
<ToggleControl
|
2024-05-21 08:48:24 +00:00
|
|
|
label={ __( 'Address line 2', 'woocommerce' ) }
|
2021-07-22 11:03:00 +00:00
|
|
|
checked={ showApartmentField }
|
|
|
|
onChange={ () => toggleAttribute( 'showApartmentField' ) }
|
|
|
|
/>
|
2024-05-21 08:48:24 +00:00
|
|
|
{ showApartmentField && (
|
|
|
|
<RadioControl
|
|
|
|
selected={ requireApartmentField }
|
|
|
|
options={ [
|
|
|
|
{
|
|
|
|
label: __( 'Optional', 'woocommerce' ),
|
|
|
|
value: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: __( 'Required', 'woocommerce' ),
|
|
|
|
value: true,
|
|
|
|
},
|
|
|
|
] }
|
|
|
|
onChange={ () =>
|
|
|
|
toggleAttribute( 'requireApartmentField' )
|
|
|
|
}
|
|
|
|
className="components-base-control--nested wc-block-components-require-apartment-field"
|
|
|
|
/>
|
|
|
|
) }
|
2021-07-22 11:03:00 +00:00
|
|
|
<ToggleControl
|
2023-12-12 22:12:36 +00:00
|
|
|
label={ __( 'Phone', 'woocommerce' ) }
|
2021-07-22 11:03:00 +00:00
|
|
|
checked={ showPhoneField }
|
|
|
|
onChange={ () => toggleAttribute( 'showPhoneField' ) }
|
|
|
|
/>
|
|
|
|
{ showPhoneField && (
|
2024-05-21 08:48:24 +00:00
|
|
|
<RadioControl
|
|
|
|
selected={ requirePhoneField }
|
|
|
|
options={ [
|
|
|
|
{
|
|
|
|
label: __( 'Optional', 'woocommerce' ),
|
|
|
|
value: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: __( 'Required', 'woocommerce' ),
|
|
|
|
value: true,
|
|
|
|
},
|
|
|
|
] }
|
2021-07-22 11:03:00 +00:00
|
|
|
onChange={ () =>
|
|
|
|
toggleAttribute( 'requirePhoneField' )
|
|
|
|
}
|
2024-05-21 08:48:24 +00:00
|
|
|
className="components-base-control--nested wc-block-components-require-phone-field"
|
2021-07-22 11:03:00 +00:00
|
|
|
/>
|
|
|
|
) }
|
|
|
|
</PanelBody>
|
|
|
|
</InspectorControls>
|
|
|
|
);
|
2021-09-24 13:44:05 +00:00
|
|
|
const blockProps = useBlockPropsWithLocking();
|
2021-07-22 11:03:00 +00:00
|
|
|
return (
|
2021-09-24 13:44:05 +00:00
|
|
|
<div { ...blockProps }>
|
2022-08-12 14:23:08 +00:00
|
|
|
<InspectorControls>
|
2021-09-16 12:16:21 +00:00
|
|
|
<BlockSettings
|
|
|
|
attributes={ attributes }
|
|
|
|
setAttributes={ setAttributes }
|
|
|
|
/>
|
2022-08-12 14:23:08 +00:00
|
|
|
</InspectorControls>
|
|
|
|
<EditorProvider
|
2023-03-30 14:15:00 +00:00
|
|
|
isPreview={ isPreview }
|
2022-08-12 14:23:08 +00:00
|
|
|
previewData={ { previewCart, previewSavedPaymentMethods } }
|
|
|
|
>
|
2023-01-06 14:53:53 +00:00
|
|
|
<SlotFillProvider>
|
|
|
|
<CheckoutProvider>
|
|
|
|
<SidebarLayout
|
2024-05-31 03:49:36 +00:00
|
|
|
className={ clsx( 'wc-block-checkout', {
|
2023-01-06 14:53:53 +00:00
|
|
|
'has-dark-controls': attributes.hasDarkControls,
|
|
|
|
} ) }
|
2021-07-22 11:03:00 +00:00
|
|
|
>
|
2023-01-06 14:53:53 +00:00
|
|
|
<CheckoutBlockControlsContext.Provider
|
|
|
|
value={ { addressFieldControls } }
|
2021-07-22 11:03:00 +00:00
|
|
|
>
|
2023-01-06 14:53:53 +00:00
|
|
|
<CheckoutBlockContext.Provider
|
|
|
|
value={ {
|
|
|
|
showApartmentField,
|
2024-05-21 08:48:24 +00:00
|
|
|
showCompanyField,
|
2023-01-06 14:53:53 +00:00
|
|
|
showPhoneField,
|
2024-05-21 08:48:24 +00:00
|
|
|
requireApartmentField,
|
|
|
|
requireCompanyField,
|
2023-01-06 14:53:53 +00:00
|
|
|
requirePhoneField,
|
|
|
|
showOrderNotes,
|
|
|
|
showPolicyLinks,
|
|
|
|
showReturnToCart,
|
|
|
|
cartPageId,
|
|
|
|
showRateAfterTaxName,
|
2024-05-22 14:03:48 +00:00
|
|
|
showFormStepNumbers,
|
2023-01-06 14:53:53 +00:00
|
|
|
} }
|
|
|
|
>
|
|
|
|
<InnerBlocks
|
|
|
|
allowedBlocks={ ALLOWED_BLOCKS }
|
|
|
|
template={ defaultTemplate }
|
|
|
|
templateLock="insert"
|
|
|
|
/>
|
|
|
|
</CheckoutBlockContext.Provider>
|
|
|
|
</CheckoutBlockControlsContext.Provider>
|
|
|
|
</SidebarLayout>
|
|
|
|
</CheckoutProvider>
|
|
|
|
</SlotFillProvider>
|
2021-09-16 12:16:21 +00:00
|
|
|
</EditorProvider>
|
2021-09-24 13:44:05 +00:00
|
|
|
</div>
|
2021-07-22 11:03:00 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const Save = (): JSX.Element => {
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
{ ...useBlockProps.save( {
|
|
|
|
className: 'wc-block-checkout is-loading',
|
|
|
|
} ) }
|
|
|
|
>
|
|
|
|
<InnerBlocks.Content />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|