/** * External dependencies */ import { __ } from '@wordpress/i18n'; import { CART_URL } from '@woocommerce/block-settings'; import { Icon, removeCart } from '@woocommerce/icons'; import { getSetting } from '@woocommerce/settings'; import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies */ import { PRODUCT_OUT_OF_STOCK, PRODUCT_NOT_PURCHASABLE, PRODUCT_NOT_ENOUGH_STOCK, PRODUCT_SOLD_INDIVIDUALLY, GENERIC_CART_ITEM_ERROR, } from './constants'; const cartItemErrorCodes = [ PRODUCT_OUT_OF_STOCK, PRODUCT_NOT_PURCHASABLE, PRODUCT_NOT_ENOUGH_STOCK, PRODUCT_SOLD_INDIVIDUALLY, GENERIC_CART_ITEM_ERROR, ]; /** * When an order was not created for the checkout, for example, when an item * was out of stock, this component will be shown instead of the checkout form. * * The error message is derived by the hydrated API request passed to the * checkout block. */ const CheckoutOrderError = () => { const preloadedApiRequests = getSetting( 'preloadedApiRequests', {} ); const checkoutData = { code: '', message: '', ...( preloadedApiRequests[ '/wc/store/checkout' ]?.body || {} ), }; const errorData = { code: checkoutData.code || 'unknown', message: decodeEntities( checkoutData.message ) || __( 'There was a problem checking out. Please try again. If the problem persists, please get in touch with us so we can assist.', 'woocommerce' ), }; return ( <div className="wc-block-checkout-error"> <Icon className="wc-block-checkout-error__image" alt="" srcElement={ removeCart } size={ 100 } /> <ErrorTitle errorData={ errorData } /> <ErrorMessage errorData={ errorData } /> <ErrorButton errorData={ errorData } /> </div> ); }; /** * Get the error message to display. * * @param {Object} props Incoming props for the component. * @param {Object} props.errorData Object containing code and message. */ const ErrorTitle = ( { errorData } ) => { let heading = __( 'Checkout error', 'woocommerce' ); if ( cartItemErrorCodes.includes( errorData.code ) ) { heading = __( 'There is a problem with your cart', 'woocommerce' ); } return ( <strong className="wc-block-checkout-error_title">{ heading }</strong> ); }; /** * Get the error message to display. * * @param {Object} props Incoming props for the component. * @param {Object} props.errorData Object containing code and message. */ const ErrorMessage = ( { errorData } ) => { let message = errorData.message; if ( cartItemErrorCodes.includes( errorData.code ) ) { message = message + ' ' + __( 'Please edit your cart and try again.', 'woocommerce' ); } return <p className="wc-block-checkout-error__description">{ message }</p>; }; /** * Get the CTA button to display. * * @param {Object} props Incoming props for the component. * @param {Object} props.errorData Object containing code and message. */ const ErrorButton = ( { errorData } ) => { let buttonText = __( 'Retry', 'woocommerce' ); let buttonUrl = 'javascript:window.location.reload(true)'; if ( cartItemErrorCodes.includes( errorData.code ) ) { buttonText = __( 'Edit your cart', 'woocommerce' ); buttonUrl = CART_URL; } return ( <span className="wp-block-button"> <a href={ buttonUrl } className="wp-block-button__link"> { buttonText } </a> </span> ); }; export default CheckoutOrderError;