323 lines
8.0 KiB
TypeScript
323 lines
8.0 KiB
TypeScript
|
/**
|
||
|
* External dependencies
|
||
|
*/
|
||
|
import { __ } from '@wordpress/i18n';
|
||
|
import classnames from 'classnames';
|
||
|
import {
|
||
|
InnerBlocks,
|
||
|
useBlockProps,
|
||
|
InspectorControls,
|
||
|
} from '@wordpress/block-editor';
|
||
|
import { SidebarLayout } from '@woocommerce/base-components/sidebar-layout';
|
||
|
import {
|
||
|
CheckoutProvider,
|
||
|
EditorProvider,
|
||
|
useEditorContext,
|
||
|
} from '@woocommerce/base-context';
|
||
|
import {
|
||
|
previewCart,
|
||
|
previewSavedPaymentMethods,
|
||
|
} from '@woocommerce/resource-previews';
|
||
|
import {
|
||
|
PanelBody,
|
||
|
ToggleControl,
|
||
|
CheckboxControl,
|
||
|
Notice,
|
||
|
} from '@wordpress/components';
|
||
|
import { CartCheckoutFeedbackPrompt } from '@woocommerce/editor-components/feedback-prompt';
|
||
|
import { CHECKOUT_PAGE_ID } from '@woocommerce/block-settings';
|
||
|
import { createInterpolateElement } from '@wordpress/element';
|
||
|
import { getAdminLink } from '@woocommerce/settings';
|
||
|
import { CartCheckoutCompatibilityNotice } from '@woocommerce/editor-components/compatibility-notices';
|
||
|
|
||
|
/**
|
||
|
* Internal dependencies
|
||
|
*/
|
||
|
import './styles/editor.scss';
|
||
|
import { Columns } from './columns';
|
||
|
import { addClassToBody, useBlockPropsWithLocking } from './hacks';
|
||
|
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',
|
||
|
];
|
||
|
|
||
|
const BlockSettings = ( {
|
||
|
attributes,
|
||
|
setAttributes,
|
||
|
}: {
|
||
|
attributes: Attributes;
|
||
|
setAttributes: ( attributes: Record< string, unknown > ) => undefined;
|
||
|
} ): JSX.Element => {
|
||
|
const { hasDarkControls } = attributes;
|
||
|
const { currentPostId } = useEditorContext();
|
||
|
|
||
|
return (
|
||
|
<InspectorControls>
|
||
|
{ currentPostId !== CHECKOUT_PAGE_ID && (
|
||
|
<Notice
|
||
|
className="wc-block-checkout__page-notice"
|
||
|
isDismissible={ false }
|
||
|
status="warning"
|
||
|
>
|
||
|
{ createInterpolateElement(
|
||
|
__(
|
||
|
'If you would like to use this block as your default checkout you must update your <a>page settings in WooCommerce</a>.',
|
||
|
'woo-gutenberg-products-block'
|
||
|
),
|
||
|
{
|
||
|
a: (
|
||
|
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
||
|
<a
|
||
|
href={ getAdminLink(
|
||
|
'admin.php?page=wc-settings&tab=advanced'
|
||
|
) }
|
||
|
target="_blank"
|
||
|
rel="noopener noreferrer"
|
||
|
/>
|
||
|
),
|
||
|
}
|
||
|
) }
|
||
|
</Notice>
|
||
|
) }
|
||
|
<PanelBody title={ __( 'Style', 'woo-gutenberg-products-block' ) }>
|
||
|
<ToggleControl
|
||
|
label={ __(
|
||
|
'Dark mode inputs',
|
||
|
'woo-gutenberg-products-block'
|
||
|
) }
|
||
|
help={ __(
|
||
|
'Inputs styled specifically for use on dark background colors.',
|
||
|
'woo-gutenberg-products-block'
|
||
|
) }
|
||
|
checked={ hasDarkControls }
|
||
|
onChange={ () =>
|
||
|
setAttributes( {
|
||
|
hasDarkControls: ! hasDarkControls,
|
||
|
} )
|
||
|
}
|
||
|
/>
|
||
|
</PanelBody>
|
||
|
<CartCheckoutFeedbackPrompt />
|
||
|
</InspectorControls>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export const Edit = ( {
|
||
|
attributes,
|
||
|
setAttributes,
|
||
|
}: {
|
||
|
attributes: Attributes;
|
||
|
setAttributes: ( attributes: Record< string, unknown > ) => undefined;
|
||
|
} ): JSX.Element => {
|
||
|
const {
|
||
|
allowCreateAccount,
|
||
|
showCompanyField,
|
||
|
requireCompanyField,
|
||
|
showApartmentField,
|
||
|
showPhoneField,
|
||
|
requirePhoneField,
|
||
|
showOrderNotes,
|
||
|
showPolicyLinks,
|
||
|
showReturnToCart,
|
||
|
showRateAfterTaxName,
|
||
|
cartPageId,
|
||
|
} = attributes;
|
||
|
|
||
|
const defaultInnerBlocksTemplate = [
|
||
|
[
|
||
|
'woocommerce/checkout-fields-block',
|
||
|
{},
|
||
|
[
|
||
|
[ 'woocommerce/checkout-express-payment-block', {}, [] ],
|
||
|
[ 'woocommerce/checkout-contact-information-block', {}, [] ],
|
||
|
[ 'woocommerce/checkout-shipping-address-block', {}, [] ],
|
||
|
[ 'woocommerce/checkout-billing-address-block', {}, [] ],
|
||
|
[ 'woocommerce/checkout-shipping-methods-block', {}, [] ],
|
||
|
[ 'woocommerce/checkout-payment-block', {}, [] ],
|
||
|
showOrderNotes
|
||
|
? [ 'woocommerce/checkout-order-note-block', {}, [] ]
|
||
|
: false,
|
||
|
showPolicyLinks
|
||
|
? [ 'woocommerce/checkout-terms-block', {}, [] ]
|
||
|
: false,
|
||
|
[
|
||
|
'woocommerce/checkout-actions-block',
|
||
|
{
|
||
|
showReturnToCart,
|
||
|
cartPageId,
|
||
|
},
|
||
|
[],
|
||
|
],
|
||
|
].filter( Boolean ),
|
||
|
],
|
||
|
[
|
||
|
'woocommerce/checkout-totals-block',
|
||
|
{},
|
||
|
[
|
||
|
[
|
||
|
'woocommerce/checkout-order-summary-block',
|
||
|
{
|
||
|
showRateAfterTaxName,
|
||
|
},
|
||
|
[],
|
||
|
],
|
||
|
],
|
||
|
],
|
||
|
];
|
||
|
|
||
|
const toggleAttribute = ( key: keyof Attributes ): void => {
|
||
|
const newAttributes = {} as Partial< Attributes >;
|
||
|
newAttributes[ key ] = ! ( attributes[ key ] as boolean );
|
||
|
setAttributes( newAttributes );
|
||
|
};
|
||
|
|
||
|
const accountControls = (): JSX.Element => (
|
||
|
<InspectorControls>
|
||
|
<PanelBody
|
||
|
title={ __(
|
||
|
'Account options',
|
||
|
'woo-gutenberg-products-block'
|
||
|
) }
|
||
|
>
|
||
|
<ToggleControl
|
||
|
label={ __(
|
||
|
'Allow shoppers to sign up for a user account during checkout',
|
||
|
'woo-gutenberg-products-block'
|
||
|
) }
|
||
|
checked={ allowCreateAccount }
|
||
|
onChange={ () =>
|
||
|
setAttributes( {
|
||
|
allowCreateAccount: ! allowCreateAccount,
|
||
|
} )
|
||
|
}
|
||
|
/>
|
||
|
</PanelBody>
|
||
|
</InspectorControls>
|
||
|
);
|
||
|
|
||
|
const addressFieldControls = (): JSX.Element => (
|
||
|
<InspectorControls>
|
||
|
<PanelBody
|
||
|
title={ __( 'Address Fields', 'woo-gutenberg-products-block' ) }
|
||
|
>
|
||
|
<p className="wc-block-checkout__controls-text">
|
||
|
{ __(
|
||
|
'Show or hide fields in the checkout address forms.',
|
||
|
'woo-gutenberg-products-block'
|
||
|
) }
|
||
|
</p>
|
||
|
<ToggleControl
|
||
|
label={ __( 'Company', 'woo-gutenberg-products-block' ) }
|
||
|
checked={ showCompanyField }
|
||
|
onChange={ () => toggleAttribute( 'showCompanyField' ) }
|
||
|
/>
|
||
|
{ showCompanyField && (
|
||
|
<CheckboxControl
|
||
|
label={ __(
|
||
|
'Require company name?',
|
||
|
'woo-gutenberg-products-block'
|
||
|
) }
|
||
|
checked={ requireCompanyField }
|
||
|
onChange={ () =>
|
||
|
toggleAttribute( 'requireCompanyField' )
|
||
|
}
|
||
|
className="components-base-control--nested"
|
||
|
/>
|
||
|
) }
|
||
|
<ToggleControl
|
||
|
label={ __(
|
||
|
'Apartment, suite, etc.',
|
||
|
'woo-gutenberg-products-block'
|
||
|
) }
|
||
|
checked={ showApartmentField }
|
||
|
onChange={ () => toggleAttribute( 'showApartmentField' ) }
|
||
|
/>
|
||
|
<ToggleControl
|
||
|
label={ __( 'Phone', 'woo-gutenberg-products-block' ) }
|
||
|
checked={ showPhoneField }
|
||
|
onChange={ () => toggleAttribute( 'showPhoneField' ) }
|
||
|
/>
|
||
|
{ showPhoneField && (
|
||
|
<CheckboxControl
|
||
|
label={ __(
|
||
|
'Require phone number?',
|
||
|
'woo-gutenberg-products-block'
|
||
|
) }
|
||
|
checked={ requirePhoneField }
|
||
|
onChange={ () =>
|
||
|
toggleAttribute( 'requirePhoneField' )
|
||
|
}
|
||
|
className="components-base-control--nested"
|
||
|
/>
|
||
|
) }
|
||
|
</PanelBody>
|
||
|
</InspectorControls>
|
||
|
);
|
||
|
const blockProps = useBlockPropsWithLocking();
|
||
|
return (
|
||
|
<div { ...blockProps }>
|
||
|
<EditorProvider
|
||
|
previewData={ { previewCart, previewSavedPaymentMethods } }
|
||
|
>
|
||
|
<BlockSettings
|
||
|
attributes={ attributes }
|
||
|
setAttributes={ setAttributes }
|
||
|
/>
|
||
|
<CheckoutProvider>
|
||
|
<Columns>
|
||
|
<SidebarLayout
|
||
|
className={ classnames( 'wc-block-checkout', {
|
||
|
'has-dark-controls': attributes.hasDarkControls,
|
||
|
} ) }
|
||
|
>
|
||
|
<CheckoutBlockControlsContext.Provider
|
||
|
value={ {
|
||
|
addressFieldControls,
|
||
|
accountControls,
|
||
|
} }
|
||
|
>
|
||
|
<CheckoutBlockContext.Provider
|
||
|
value={ {
|
||
|
allowCreateAccount,
|
||
|
showCompanyField,
|
||
|
requireCompanyField,
|
||
|
showApartmentField,
|
||
|
showPhoneField,
|
||
|
requirePhoneField,
|
||
|
} }
|
||
|
>
|
||
|
<InnerBlocks
|
||
|
allowedBlocks={ ALLOWED_BLOCKS }
|
||
|
template={ defaultInnerBlocksTemplate }
|
||
|
templateLock="insert"
|
||
|
/>
|
||
|
</CheckoutBlockContext.Provider>
|
||
|
</CheckoutBlockControlsContext.Provider>
|
||
|
</SidebarLayout>
|
||
|
</Columns>
|
||
|
</CheckoutProvider>
|
||
|
</EditorProvider>
|
||
|
<CartCheckoutCompatibilityNotice blockName="checkout" />
|
||
|
</div>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export const Save = (): JSX.Element => {
|
||
|
return (
|
||
|
<div
|
||
|
{ ...useBlockProps.save( {
|
||
|
className: 'wc-block-checkout is-loading',
|
||
|
} ) }
|
||
|
>
|
||
|
<InnerBlocks.Content />
|
||
|
</div>
|
||
|
);
|
||
|
};
|