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

170 lines
4.3 KiB
JavaScript
Raw Normal View History

/**
* 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';
Add validation context provider and implement validation for shipping country and coupons. (https://github.com/woocommerce/woocommerce-blocks/pull/1972) * add errormessage handling to countryinput (along with storybook) * add types for react * Add validation context and implement * implement validation context for country field validation * tweak ValidationInputError so that it can receive property name for getting error from * improve storybook webpack config to pull from tsconfig.json * update storybook story to cover changes with context * Wrap Checkout Provider with Validation Context Provider * add screen-reader-text style to storybook * add styles for input error validation to text input * improve styling for ValidationInputError component * add validation error handling to TotalsCouponCode component And story * make sure errors are cleared on successful receive/remove item * dispatch loading cancellation on catching errors This is needed because loading would be cancelled before the error is thrown so any error handling after the thrown error will not be able to rely on loading. * implement validation setting for coupon errors * add error color to labels on inputs too * fix borders back and force border color * remove extra structure and improve validation error with alignment for coupon code * add aria-describedby for text inputs * add back in validation context provider to fix rebase issue * rework validation so it works for both checkout and cart * Some styling tweaks * more style fixes * remove unnecessary method * make sure new function is included in context defaults * package.lock update? seems harmless so rolling with it.
2020-03-17 11:45:33 +00:00
import {
CheckoutProvider,
useCheckoutContext,
useEditorContext,
useValidationContext,
Add validation context provider and implement validation for shipping country and coupons. (https://github.com/woocommerce/woocommerce-blocks/pull/1972) * add errormessage handling to countryinput (along with storybook) * add types for react * Add validation context and implement * implement validation context for country field validation * tweak ValidationInputError so that it can receive property name for getting error from * improve storybook webpack config to pull from tsconfig.json * update storybook story to cover changes with context * Wrap Checkout Provider with Validation Context Provider * add screen-reader-text style to storybook * add styles for input error validation to text input * improve styling for ValidationInputError component * add validation error handling to TotalsCouponCode component And story * make sure errors are cleared on successful receive/remove item * dispatch loading cancellation on catching errors This is needed because loading would be cancelled before the error is thrown so any error handling after the thrown error will not be able to rely on loading. * implement validation setting for coupon errors * add error color to labels on inputs too * fix borders back and force border color * remove extra structure and improve validation error with alignment for coupon code * add aria-describedby for text inputs * add back in validation context provider to fix rebase issue * rework validation so it works for both checkout and cart * Some styling tweaks * more style fixes * remove unnecessary method * make sure new function is included in context defaults * package.lock update? seems harmless so rolling with it.
2020-03-17 11:45:33 +00:00
} 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' ) );
Use store-themed set password form for checkout signup (https://github.com/woocommerce/woocommerce-blocks/pull/3236) * use my-account/lost-password endpoint url for set password (tbd): - companion for working on https://github.com/woocommerce/woocommerce/issues/27754 * use more appropriate (new) set-password endpoint * add version check - use new woo core endpoint if woo version is new enough * use my-account/lost-password for setting password in checkout signup: - this has been available forever - no need for a version check - page will show `Lost password`; looking at options for overriding that * use more explicit `newaccount` action for set password url if available * tweak feature gating for checkout signup: - only available in dev builds (will change soon) - only available if Woo core 4.7 or newer - checkout signup relies on fixes in 4.7+ (tbc) to my-account/lost-password endpoint for setting initial password - standardise feature gate logic so is consistent, ensure feature is disabled in API/backend, hide editor option, and disable front end - add new setting `wcVersion` to allow feature gating on woo version * fix woo-version feature gate of checkout signup: - fixed version logic, explicit 4.7.0 reference version - refactor version compare routine so can be used for woo or WP version * revamp Woo 4.7+ logic so PHPunit tests aren't dependent on Woo version: - Woo-version feature gating is implemented at integration layer: - checkout REST API - register/override new account email handler
2020-10-15 01:13:49 +00:00
// 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', '>=' );
Use store-themed set password form for checkout signup (https://github.com/woocommerce/woocommerce-blocks/pull/3236) * use my-account/lost-password endpoint url for set password (tbd): - companion for working on https://github.com/woocommerce/woocommerce/issues/27754 * use more appropriate (new) set-password endpoint * add version check - use new woo core endpoint if woo version is new enough * use my-account/lost-password for setting password in checkout signup: - this has been available forever - no need for a version check - page will show `Lost password`; looking at options for overriding that * use more explicit `newaccount` action for set password url if available * tweak feature gating for checkout signup: - only available in dev builds (will change soon) - only available if Woo core 4.7 or newer - checkout signup relies on fixes in 4.7+ (tbc) to my-account/lost-password endpoint for setting initial password - standardise feature gate logic so is consistent, ensure feature is disabled in API/backend, hide editor option, and disable front end - add new setting `wcVersion` to allow feature gating on woo version * fix woo-version feature gate of checkout signup: - fixed version logic, explicit 4.7.0 reference version - refactor version compare routine so can be used for woo or WP version * revamp Woo 4.7+ logic so PHPunit tests aren't dependent on Woo version: - Woo-version feature gating is implemented at integration layer: - checkout REST API - register/override new account email handler
2020-10-15 01:13:49 +00:00
useEffect( () => {
if ( hasErrorsToDisplay ) {
showAllValidationErrors();
scrollToTop( { focusableSelector: 'input:invalid' } );
}
}, [ hasErrorsToDisplay, scrollToTop, showAllValidationErrors ] );
if ( ! isEditor && ! hasOrder ) {
return <CheckoutOrderError />;
}
Support "create account" option in checkout block (https://github.com/woocommerce/woocommerce-blocks/pull/2851) * prototype 'create account' checkbox in checkout block * expose store config for generating password/username to blocks: + use FILTER_VALIDATE_BOOLEAN instead of hard-coded `yes` * stub out signup form in checkout block * context / provider to store checkout signup form data * revert signup form - checkout block will always generate username etc * persist signup checkbox in checkout state & pass to checkout API * add `create_account` param to order API, fix name in client POST * handle creating user account as part of order (first cut) * ensure the order is associated with the new customer * only show 'create account' checkbox when appropriate (guest checkout) * remove unnecessary username/password variables * refactor account-creation logic into functions: - clarify inputs and outputs - use RouteException for error handling - use woo options directly, avoid dependency on WC_Checkout * update "email exists" error message to use existing error message text * handle all known errors from wc_create_new_customer + use core message * only show "create account" checkbox to shopper when necessary: - if guest checkout is disabled, user must create account - not optional * only show "create account" if account creation is optional: - fixes incorrect logic in previous commit - add some comments to clarify * fix create account logic in API when checkout requires account: - use correct woo setting option name - reverse logic to match option = allow guest false means registration required * strip html tags from create account error messages * temporarily force enable autogenerate user/pass in new account API * fix rebase errors * add new allowCreateAccount attribute in checkout block * show/hide `Create account` checkbox dependent on block attribute: - previously was dependent on store setting * new create user API, with set initial password email (first cut): - use core register_new_user for creating the user - this triggers core "set new password" email - generate username using logic lifted from WC core - rough cut, lots to tidy/polish here * remove alternative/unused create account function * set `Customer` role for signups during checkout * eslint fix - switch case break * remove comments that mirror code & might go stale * tidy func comment * remove unused function * use store setting `allow signup` for default value of new block option * refactor order signup logic to service class first cut: - new CreateAccount service - hook up via custom action (for now at least) - paste over existing create account logic (temporary - will be replaced) * adapt wc_create_new_customer logic in CreateAccount service (WIP) * set default_password_nag on new account + throw instead of WP_Error * rename `createAccount` => `shouldCreateAccount` to clarify meaning * fix checkout block - renamed `shouldCreateAccount` (missed in prev commit) * prototype sending alternative email template for checkout signup * add magic link to set password to blocks new account html email * tidy up new account email templates - set password link, subject/heading * use same id so merchant setting tweaks apply to our new improved email * remove logging * code tidies in CreateAccount service: - remove unnecessary constructor - type-hint in should_create_customer_account - streamline logic in should_create_customer_account - remove unnecessary `empty` check - add comments to illuminate different use-cases handled by should_create_customer_account * don't provide password to new account email templates (no longer used) * declare dependencies in root namespace * code tidies on new account email class: - correct namespace and camelcase name - declare class in file, don't instantiate; instantiate in client code (CreateAccount service) when used - no require/file import, use `use` * move CustomerNewEmail to folder matching namespace * use Package->get_path for email template paths: - CreateAccount service now depends on Package - CreateAccount passes Package to email class so it can use `get_path` - note: CustomerNewAccount is not registered with DI container as it needs to be instantiated after Woo init (for `WC_Email`) - shift email templates to {plugin}/templates, consistent with WP convention * call CreateAccount::from_order_request directly, no custom hook: - custom hook is not appropriate as we may not want to allow extensibility in this way - TBD * add appropriate margin above create account checkbox * remove unnecessary direct-access protection * generalise name of error-handling method * simplify CustomerNewAccount - instantiate directly, when needed * remove unused new_account_email member - now instantiated on demand * numerous fixes and updates due to rebase changes * fix typo in name of CustomerNewAccount php file (missing `n`) * experiment - link to lost-password form in my-account (prototype branded screen) * Revert "experiment - link to lost-password form in my-account (prototype branded screen)" This reverts commit e1dc6dd5e9f0218ede81da92188d813c2d0856d9. * feature gate CreateAccount service init to dev build only + + remove stale comment * feature gate front end "Create account" checkbox to feature plugin only * feature gate editor "allow signup" option to dev build only * feature gate checkout api create account - dev build only * tweak feature gating PHP logic so it's robust: - all PHP feature gating is in the service class - all publicly-available methods return early if feature gate off - Checkout rest API transparently calls service - no explicit feature gate at API level * ensure frontend/editor features are feature gated (isExperimentalBuild is a function) * feature gate value of checkoutAllowsSignup - can only be true in feature plugin * fix a / an typo in comment Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com> * remove commented code * hello world unit test (doesn't test anything yet) * add a command for running unit tests when container already up: - this should probably move to another PR/branch * basic tests of core logic in CreateAccount service * import isExperimentalBuild direct: - import from alias package was causing an issue, likely a dependency cycle * refactor from_order_request to return new user ID so it's easier to test * test creating a customer from an order + rest request: - i.e. a full end-to-end integration test * delete redundant test and tidy comments * generalise test to provider format * refactor create-dup-user err test to use same approach as success test * add test for when user should not be created * don't hard-code options in "create" test, remove redundant provider in no-account-requested test * de-generalise "user already signed up" test * add test for malformed email * flesh out & comment successful signup tests * flesh out "invalid email" tests * clarify no account requested test comment * remove phpunit:quick - I don't think it's needed * add comment explaining this is an integration test * experiment – disable feature flag, is this why the tests are failing? * revert test commit - restore feature gate (experimental flag) * skip all tests if CreateAccount is disabled due to feature flag * d'oh - expose CreateAccount:is_feature_enabled so can be used in tests * add jsdoc for checkout-state shouldCreateAccount field * remove unnecessary comment + fix whitespace/indentation * simulate logged-out user for createaccount signup tests * use a single, compound if statement for early return (review nitpick) * don't hide `checkoutAllowsSignup` store setting behind feature flag: - the feature flag should be used to enable/disable behaviour - it's dangerous to adjust store settings/options based on feature flag * rejig tests so they require woocommerce_blocks_phase==3: - make feature gate method private to avoid exposing - remove feature flag check & test skip for other builds - set blocks phase in travis config * remove redundant user-logout in test setup - cleaner to just require this * use WP function bracket style (same line) Co-authored-by: Darren Ethier <darren@roughsmootheng.in> Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
2020-10-01 02:07:16 +00:00
if (
! isEditor &&
! customerId &&
! CHECKOUT_ALLOWS_GUEST &&
! ( allowCreateAccount && CHECKOUT_ALLOWS_SIGNUP )
Support "create account" option in checkout block (https://github.com/woocommerce/woocommerce-blocks/pull/2851) * prototype 'create account' checkbox in checkout block * expose store config for generating password/username to blocks: + use FILTER_VALIDATE_BOOLEAN instead of hard-coded `yes` * stub out signup form in checkout block * context / provider to store checkout signup form data * revert signup form - checkout block will always generate username etc * persist signup checkbox in checkout state & pass to checkout API * add `create_account` param to order API, fix name in client POST * handle creating user account as part of order (first cut) * ensure the order is associated with the new customer * only show 'create account' checkbox when appropriate (guest checkout) * remove unnecessary username/password variables * refactor account-creation logic into functions: - clarify inputs and outputs - use RouteException for error handling - use woo options directly, avoid dependency on WC_Checkout * update "email exists" error message to use existing error message text * handle all known errors from wc_create_new_customer + use core message * only show "create account" checkbox to shopper when necessary: - if guest checkout is disabled, user must create account - not optional * only show "create account" if account creation is optional: - fixes incorrect logic in previous commit - add some comments to clarify * fix create account logic in API when checkout requires account: - use correct woo setting option name - reverse logic to match option = allow guest false means registration required * strip html tags from create account error messages * temporarily force enable autogenerate user/pass in new account API * fix rebase errors * add new allowCreateAccount attribute in checkout block * show/hide `Create account` checkbox dependent on block attribute: - previously was dependent on store setting * new create user API, with set initial password email (first cut): - use core register_new_user for creating the user - this triggers core "set new password" email - generate username using logic lifted from WC core - rough cut, lots to tidy/polish here * remove alternative/unused create account function * set `Customer` role for signups during checkout * eslint fix - switch case break * remove comments that mirror code & might go stale * tidy func comment * remove unused function * use store setting `allow signup` for default value of new block option * refactor order signup logic to service class first cut: - new CreateAccount service - hook up via custom action (for now at least) - paste over existing create account logic (temporary - will be replaced) * adapt wc_create_new_customer logic in CreateAccount service (WIP) * set default_password_nag on new account + throw instead of WP_Error * rename `createAccount` => `shouldCreateAccount` to clarify meaning * fix checkout block - renamed `shouldCreateAccount` (missed in prev commit) * prototype sending alternative email template for checkout signup * add magic link to set password to blocks new account html email * tidy up new account email templates - set password link, subject/heading * use same id so merchant setting tweaks apply to our new improved email * remove logging * code tidies in CreateAccount service: - remove unnecessary constructor - type-hint in should_create_customer_account - streamline logic in should_create_customer_account - remove unnecessary `empty` check - add comments to illuminate different use-cases handled by should_create_customer_account * don't provide password to new account email templates (no longer used) * declare dependencies in root namespace * code tidies on new account email class: - correct namespace and camelcase name - declare class in file, don't instantiate; instantiate in client code (CreateAccount service) when used - no require/file import, use `use` * move CustomerNewEmail to folder matching namespace * use Package->get_path for email template paths: - CreateAccount service now depends on Package - CreateAccount passes Package to email class so it can use `get_path` - note: CustomerNewAccount is not registered with DI container as it needs to be instantiated after Woo init (for `WC_Email`) - shift email templates to {plugin}/templates, consistent with WP convention * call CreateAccount::from_order_request directly, no custom hook: - custom hook is not appropriate as we may not want to allow extensibility in this way - TBD * add appropriate margin above create account checkbox * remove unnecessary direct-access protection * generalise name of error-handling method * simplify CustomerNewAccount - instantiate directly, when needed * remove unused new_account_email member - now instantiated on demand * numerous fixes and updates due to rebase changes * fix typo in name of CustomerNewAccount php file (missing `n`) * experiment - link to lost-password form in my-account (prototype branded screen) * Revert "experiment - link to lost-password form in my-account (prototype branded screen)" This reverts commit e1dc6dd5e9f0218ede81da92188d813c2d0856d9. * feature gate CreateAccount service init to dev build only + + remove stale comment * feature gate front end "Create account" checkbox to feature plugin only * feature gate editor "allow signup" option to dev build only * feature gate checkout api create account - dev build only * tweak feature gating PHP logic so it's robust: - all PHP feature gating is in the service class - all publicly-available methods return early if feature gate off - Checkout rest API transparently calls service - no explicit feature gate at API level * ensure frontend/editor features are feature gated (isExperimentalBuild is a function) * feature gate value of checkoutAllowsSignup - can only be true in feature plugin * fix a / an typo in comment Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com> * remove commented code * hello world unit test (doesn't test anything yet) * add a command for running unit tests when container already up: - this should probably move to another PR/branch * basic tests of core logic in CreateAccount service * import isExperimentalBuild direct: - import from alias package was causing an issue, likely a dependency cycle * refactor from_order_request to return new user ID so it's easier to test * test creating a customer from an order + rest request: - i.e. a full end-to-end integration test * delete redundant test and tidy comments * generalise test to provider format * refactor create-dup-user err test to use same approach as success test * add test for when user should not be created * don't hard-code options in "create" test, remove redundant provider in no-account-requested test * de-generalise "user already signed up" test * add test for malformed email * flesh out & comment successful signup tests * flesh out "invalid email" tests * clarify no account requested test comment * remove phpunit:quick - I don't think it's needed * add comment explaining this is an integration test * experiment – disable feature flag, is this why the tests are failing? * revert test commit - restore feature gate (experimental flag) * skip all tests if CreateAccount is disabled due to feature flag * d'oh - expose CreateAccount:is_feature_enabled so can be used in tests * add jsdoc for checkout-state shouldCreateAccount field * remove unnecessary comment + fix whitespace/indentation * simulate logged-out user for createaccount signup tests * use a single, compound if statement for early return (review nitpick) * don't hide `checkoutAllowsSignup` store setting behind feature flag: - the feature flag should be used to enable/disable behaviour - it's dangerous to adjust store settings/options based on feature flag * rejig tests so they require woocommerce_blocks_phase==3: - make feature gate method private to avoid exposing - remove feature flag check & test skip for other builds - set blocks phase in travis config * remove redundant user-logout in test setup - cleaner to just require this * use WP function bracket style (same line) Co-authored-by: Darren Ethier <darren@roughsmootheng.in> Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
2020-10-01 02:07:16 +00:00
) {
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 }
Use store-themed set password form for checkout signup (https://github.com/woocommerce/woocommerce-blocks/pull/3236) * use my-account/lost-password endpoint url for set password (tbd): - companion for working on https://github.com/woocommerce/woocommerce/issues/27754 * use more appropriate (new) set-password endpoint * add version check - use new woo core endpoint if woo version is new enough * use my-account/lost-password for setting password in checkout signup: - this has been available forever - no need for a version check - page will show `Lost password`; looking at options for overriding that * use more explicit `newaccount` action for set password url if available * tweak feature gating for checkout signup: - only available in dev builds (will change soon) - only available if Woo core 4.7 or newer - checkout signup relies on fixes in 4.7+ (tbc) to my-account/lost-password endpoint for setting initial password - standardise feature gate logic so is consistent, ensure feature is disabled in API/backend, hide editor option, and disable front end - add new setting `wcVersion` to allow feature gating on woo version * fix woo-version feature gate of checkout signup: - fixed version logic, explicit 4.7.0 reference version - refactor version compare routine so can be used for woo or WP version * revamp Woo 4.7+ logic so PHPunit tests aren't dependent on Woo version: - Woo-version feature gating is implemented at integration layer: - checkout REST API - register/override new account email handler
2020-10-15 01:13:49 +00:00
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 );