woocommerce/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/block.js

170 lines
4.3 KiB
JavaScript

/**
* External dependencies
*/
import classnames from 'classnames';
import { useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import {
PlaceOrderButton,
Policies,
ReturnToCartButton,
} from '@woocommerce/base-components/cart-checkout';
import {
CheckoutProvider,
useCheckoutContext,
useEditorContext,
useValidationContext,
} from '@woocommerce/base-context';
import { useStoreCart, useStoreNotices } from '@woocommerce/base-context/hooks';
import {
Sidebar,
SidebarLayout,
Main,
} from '@woocommerce/base-components/sidebar-layout';
import withScrollToTop from '@woocommerce/base-hocs/with-scroll-to-top';
import {
CHECKOUT_ALLOWS_GUEST,
CHECKOUT_ALLOWS_SIGNUP,
} from '@woocommerce/block-settings';
import { isWcVersion, getSetting } from '@woocommerce/settings';
/**
* Internal dependencies
*/
import CheckoutForm from './form';
import CheckoutSidebar from './sidebar';
import CheckoutOrderError from './checkout-order-error';
import { CheckoutExpressPayment } from '../payment-methods';
import { LOGIN_TO_CHECKOUT_URL } from './utils';
import './style.scss';
/**
* Renders the Checkout block wrapped within the CheckoutProvider.
*
* @param {Object} props Component props.
* @return {*} The component.
*/
const Block = ( props ) => {
return (
<CheckoutProvider>
<Checkout { ...props } />
</CheckoutProvider>
);
};
/**
* Main Checkout Component.
*
* @param {Object} props Component props.
* @param {Object} props.attributes Incoming block attributes.
* @param {function(any):any} props.scrollToTop Function for scrolling to top.
*/
const Checkout = ( { attributes, scrollToTop } ) => {
const { isEditor } = useEditorContext();
const {
cartItems,
cartTotals,
cartCoupons,
cartFees,
cartNeedsPayment,
} = useStoreCart();
const {
hasOrder,
hasError: checkoutHasError,
isIdle: checkoutIsIdle,
customerId,
} = useCheckoutContext();
const {
hasValidationErrors,
showAllValidationErrors,
} = useValidationContext();
const { hasNoticesOfType } = useStoreNotices();
const hasErrorsToDisplay =
checkoutIsIdle &&
checkoutHasError &&
( hasValidationErrors || hasNoticesOfType( 'default' ) );
// Checkout signup is feature gated to WooCommerce 4.7 and newer;
// uses updated my-account/lost-password screen from 4.7+ for
// setting initial password.
const allowCreateAccount =
attributes.allowCreateAccount && isWcVersion( '4.7.0', '>=' );
useEffect( () => {
if ( hasErrorsToDisplay ) {
showAllValidationErrors();
scrollToTop( { focusableSelector: 'input:invalid' } );
}
}, [ hasErrorsToDisplay, scrollToTop, showAllValidationErrors ] );
if ( ! isEditor && ! hasOrder ) {
return <CheckoutOrderError />;
}
if (
! isEditor &&
! customerId &&
! CHECKOUT_ALLOWS_GUEST &&
! ( allowCreateAccount && CHECKOUT_ALLOWS_SIGNUP )
) {
return (
<>
{ __(
'You must be logged in to checkout. ',
'woo-gutenberg-products-block'
) }
<a href={ LOGIN_TO_CHECKOUT_URL }>
{ __(
'Click here to log in.',
'woo-gutenberg-products-block'
) }
</a>
</>
);
}
const checkoutClassName = classnames( 'wc-block-checkout', {
'has-dark-controls': attributes.hasDarkControls,
} );
return (
<>
<SidebarLayout className={ checkoutClassName }>
<Main className="wc-block-checkout__main">
{ cartNeedsPayment && <CheckoutExpressPayment /> }
<CheckoutForm
showApartmentField={ attributes.showApartmentField }
showCompanyField={ attributes.showCompanyField }
showOrderNotes={ attributes.showOrderNotes }
showPhoneField={ attributes.showPhoneField }
requireCompanyField={ attributes.requireCompanyField }
requirePhoneField={ attributes.requirePhoneField }
allowCreateAccount={ allowCreateAccount }
/>
<div className="wc-block-checkout__actions">
{ attributes.showReturnToCart && (
<ReturnToCartButton
link={ getSetting(
'page-' + attributes?.cartPageId,
false
) }
/>
) }
<PlaceOrderButton />
</div>
{ attributes.showPolicyLinks && <Policies /> }
</Main>
<Sidebar className="wc-block-checkout__sidebar">
<CheckoutSidebar
cartCoupons={ cartCoupons }
cartItems={ cartItems }
cartTotals={ cartTotals }
cartFees={ cartFees }
/>
</Sidebar>
</SidebarLayout>
</>
);
};
export default withScrollToTop( Block );