Add notice on quantity change and update `wc/store/cart` to use thunks (https://github.com/woocommerce/woocommerce-blocks/pull/7938)
* Add receiveCart thunk
* Add mapCartResponseToCart helper
* Add getItemsPendingQuantityUpdate selector
* Update cart resolvers to be thunks
* Remove RECEIVE_CART action and replace with SET_CART_DATA
receiveCart will turn into a thunk.
* Add notifyQuantityChanges functions
* Remove receiveCart from action type definition, replace with setCartData
* Move apiFetchWithHeaders out of controls
This will just be a normal function since we'll be updating actions to thunks which will use this instead of a control.
* Include thunks in actions file
* Update receiveCart action to setCartData
* Update applyCoupon action to a thunk
* Update useStoreCartCoupons to get action from correct place
* Update StoreCartCoupon types
* Add types for Thunk and ThunkReturnType in mapped-types
* Change applyCoupon to a thunk
* Get applyCoupon, removeCoupon, receiveApplyingCoupon from useDispatch
This is to separate the concerns of actions vs. selectors. Previously the actions were fetched during useSelect which is not a pattern we use anywhere else in the codebase. Since we updated the MapToDispatch type, we can now get correctly typed thunks from the data store.
* Improve apiFetchWithHeaders typings
* Convert removeCoupon from generator to thunk
* Add applyCoupon and removeCoupon to CartAction type
* Remove unused old-style type-def
* Add receiveApplyingCoupon & receiveRemovingCoupon to StoreCartCoupon
* Correct issues with StoreCartCoupon type
These were not intended to reflect the actions in data store, rather the functions offered by the useStoreCartCoupons hook.
* Update applyExtensionCartUpdate to a thunk
* Update addItemToCart to thunk
* Add ResolveSelectFromMap type that works with thunks
* Add CartDispatchFromMap and CartResolveSelectFromMap types
We can add this to all data stores to get them working with thunks properly.
* Add docs and update generic name in ResolveSelectFromMap
* Add correct types for thunk resolvers in cart data store
* Update removeItemFromCart to thunk
* Update apiFetchWithHeaders to use generic
* Update selectShippingRate to thunk
* Update resolver tests to test correct thunk functionality
* Update updateCustomerData to thunk
* Update reducer test to reflect new action name
* Update comments on CartDispatchFromMap and CartResolveSelectFromMap
* Add quantity_limits to preview cart
* Make notices speak when shown
* Remove copilot comment
* Add isWithinQuantityLimits function
This is because we shouldn't show a notice if the quantity limits change, but the item's quantity is still OK.
* Add tests for notifyQuantityChanges
* Show notice when multiple_of is updated
* Update test to test for multiple_of changes
* Remove empty export
* Remove controls from cart data store
Not needed anymore since the exported value from the shared-controls file was empty.
* Export a control and async function for apiFetchWithHeaders
This is required because async functions cannot be called from sync generators.
* Use control version of apiFetchWithHeaders in the collections store
* Improve comments and remove incorrect TypeScript
* Update assets/js/data/cart/actions.ts
Co-authored-by: Mike Jolley <mike.jolley@me.com>
* Update ResolveSelectFromMap to include selectors too
* Update TS in actions
* Use finally to remove duplicate code
* remove item pending delete/qty update after action runs in all cases
This will also reset the state when the request to remove it/change quantity errors
* Remove unnecessary type from param.
Not needed because we have TS now. The description can stay though, it is useful.
* Update snackbar wording to use active voice
* Remove old WP version check
* Set max quantity to high number instead of null
This would only happen in a niche case, and would require several TS changes to fix, so it's better to set it as a number here. 9999 should be high enough, and is the default quantity limit set below in get_product_quantity_limit
* Set code on woocommerce_rest_cart_invalid_key to 409
This is so the cart is returned in the response, so the client can update.
* Fix typo in comment and add CartSelectFromMap
* Remove unnecessary docblock
* Add getItemsPendingDelete selector
This is needed so we can show a notice for items that are unexpectedly removed from the cart. We need to know which ones are pending delete so we can skip showing the notice for them.
* Add type for notifyQuantityChanges args and change args to object
* Add notifyIfRemoved function
This will check items that have been removed and show a notice for them.
* Fix TS in receiveCart & pass itemsPendingDelete to notifyQuantiyChanges
* Update wording on removal notice
* Update types for notifyQuantityChanges args
* Update tests to reflect new wording and args being an object
* Check item is truth before running comparison of keys
* Update tests for unexpectedly and expectedly removed items
* Ignore print_r to satisfy phpcs
* Update PHP tests to reflect correct response code when deleting items
* Remove unnecessary controls and dispatch events directly from thunk
Co-authored-by: Mike Jolley <mike.jolley@me.com>
2022-12-16 16:06:37 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import { Cart, CartItem } from '@woocommerce/types';
|
2023-01-25 16:28:41 +00:00
|
|
|
import { dispatch, select } from '@wordpress/data';
|
Add notice on quantity change and update `wc/store/cart` to use thunks (https://github.com/woocommerce/woocommerce-blocks/pull/7938)
* Add receiveCart thunk
* Add mapCartResponseToCart helper
* Add getItemsPendingQuantityUpdate selector
* Update cart resolvers to be thunks
* Remove RECEIVE_CART action and replace with SET_CART_DATA
receiveCart will turn into a thunk.
* Add notifyQuantityChanges functions
* Remove receiveCart from action type definition, replace with setCartData
* Move apiFetchWithHeaders out of controls
This will just be a normal function since we'll be updating actions to thunks which will use this instead of a control.
* Include thunks in actions file
* Update receiveCart action to setCartData
* Update applyCoupon action to a thunk
* Update useStoreCartCoupons to get action from correct place
* Update StoreCartCoupon types
* Add types for Thunk and ThunkReturnType in mapped-types
* Change applyCoupon to a thunk
* Get applyCoupon, removeCoupon, receiveApplyingCoupon from useDispatch
This is to separate the concerns of actions vs. selectors. Previously the actions were fetched during useSelect which is not a pattern we use anywhere else in the codebase. Since we updated the MapToDispatch type, we can now get correctly typed thunks from the data store.
* Improve apiFetchWithHeaders typings
* Convert removeCoupon from generator to thunk
* Add applyCoupon and removeCoupon to CartAction type
* Remove unused old-style type-def
* Add receiveApplyingCoupon & receiveRemovingCoupon to StoreCartCoupon
* Correct issues with StoreCartCoupon type
These were not intended to reflect the actions in data store, rather the functions offered by the useStoreCartCoupons hook.
* Update applyExtensionCartUpdate to a thunk
* Update addItemToCart to thunk
* Add ResolveSelectFromMap type that works with thunks
* Add CartDispatchFromMap and CartResolveSelectFromMap types
We can add this to all data stores to get them working with thunks properly.
* Add docs and update generic name in ResolveSelectFromMap
* Add correct types for thunk resolvers in cart data store
* Update removeItemFromCart to thunk
* Update apiFetchWithHeaders to use generic
* Update selectShippingRate to thunk
* Update resolver tests to test correct thunk functionality
* Update updateCustomerData to thunk
* Update reducer test to reflect new action name
* Update comments on CartDispatchFromMap and CartResolveSelectFromMap
* Add quantity_limits to preview cart
* Make notices speak when shown
* Remove copilot comment
* Add isWithinQuantityLimits function
This is because we shouldn't show a notice if the quantity limits change, but the item's quantity is still OK.
* Add tests for notifyQuantityChanges
* Show notice when multiple_of is updated
* Update test to test for multiple_of changes
* Remove empty export
* Remove controls from cart data store
Not needed anymore since the exported value from the shared-controls file was empty.
* Export a control and async function for apiFetchWithHeaders
This is required because async functions cannot be called from sync generators.
* Use control version of apiFetchWithHeaders in the collections store
* Improve comments and remove incorrect TypeScript
* Update assets/js/data/cart/actions.ts
Co-authored-by: Mike Jolley <mike.jolley@me.com>
* Update ResolveSelectFromMap to include selectors too
* Update TS in actions
* Use finally to remove duplicate code
* remove item pending delete/qty update after action runs in all cases
This will also reset the state when the request to remove it/change quantity errors
* Remove unnecessary type from param.
Not needed because we have TS now. The description can stay though, it is useful.
* Update snackbar wording to use active voice
* Remove old WP version check
* Set max quantity to high number instead of null
This would only happen in a niche case, and would require several TS changes to fix, so it's better to set it as a number here. 9999 should be high enough, and is the default quantity limit set below in get_product_quantity_limit
* Set code on woocommerce_rest_cart_invalid_key to 409
This is so the cart is returned in the response, so the client can update.
* Fix typo in comment and add CartSelectFromMap
* Remove unnecessary docblock
* Add getItemsPendingDelete selector
This is needed so we can show a notice for items that are unexpectedly removed from the cart. We need to know which ones are pending delete so we can skip showing the notice for them.
* Add type for notifyQuantityChanges args and change args to object
* Add notifyIfRemoved function
This will check items that have been removed and show a notice for them.
* Fix TS in receiveCart & pass itemsPendingDelete to notifyQuantiyChanges
* Update wording on removal notice
* Update types for notifyQuantityChanges args
* Update tests to reflect new wording and args being an object
* Check item is truth before running comparison of keys
* Update tests for unexpectedly and expectedly removed items
* Ignore print_r to satisfy phpcs
* Update PHP tests to reflect correct response code when deleting items
* Remove unnecessary controls and dispatch events directly from thunk
Co-authored-by: Mike Jolley <mike.jolley@me.com>
2022-12-16 16:06:37 +00:00
|
|
|
import { __, sprintf } from '@wordpress/i18n';
|
|
|
|
|
2023-01-25 16:28:41 +00:00
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import { STORE_KEY as CART_STORE_KEY } from './constants';
|
|
|
|
|
Add notice on quantity change and update `wc/store/cart` to use thunks (https://github.com/woocommerce/woocommerce-blocks/pull/7938)
* Add receiveCart thunk
* Add mapCartResponseToCart helper
* Add getItemsPendingQuantityUpdate selector
* Update cart resolvers to be thunks
* Remove RECEIVE_CART action and replace with SET_CART_DATA
receiveCart will turn into a thunk.
* Add notifyQuantityChanges functions
* Remove receiveCart from action type definition, replace with setCartData
* Move apiFetchWithHeaders out of controls
This will just be a normal function since we'll be updating actions to thunks which will use this instead of a control.
* Include thunks in actions file
* Update receiveCart action to setCartData
* Update applyCoupon action to a thunk
* Update useStoreCartCoupons to get action from correct place
* Update StoreCartCoupon types
* Add types for Thunk and ThunkReturnType in mapped-types
* Change applyCoupon to a thunk
* Get applyCoupon, removeCoupon, receiveApplyingCoupon from useDispatch
This is to separate the concerns of actions vs. selectors. Previously the actions were fetched during useSelect which is not a pattern we use anywhere else in the codebase. Since we updated the MapToDispatch type, we can now get correctly typed thunks from the data store.
* Improve apiFetchWithHeaders typings
* Convert removeCoupon from generator to thunk
* Add applyCoupon and removeCoupon to CartAction type
* Remove unused old-style type-def
* Add receiveApplyingCoupon & receiveRemovingCoupon to StoreCartCoupon
* Correct issues with StoreCartCoupon type
These were not intended to reflect the actions in data store, rather the functions offered by the useStoreCartCoupons hook.
* Update applyExtensionCartUpdate to a thunk
* Update addItemToCart to thunk
* Add ResolveSelectFromMap type that works with thunks
* Add CartDispatchFromMap and CartResolveSelectFromMap types
We can add this to all data stores to get them working with thunks properly.
* Add docs and update generic name in ResolveSelectFromMap
* Add correct types for thunk resolvers in cart data store
* Update removeItemFromCart to thunk
* Update apiFetchWithHeaders to use generic
* Update selectShippingRate to thunk
* Update resolver tests to test correct thunk functionality
* Update updateCustomerData to thunk
* Update reducer test to reflect new action name
* Update comments on CartDispatchFromMap and CartResolveSelectFromMap
* Add quantity_limits to preview cart
* Make notices speak when shown
* Remove copilot comment
* Add isWithinQuantityLimits function
This is because we shouldn't show a notice if the quantity limits change, but the item's quantity is still OK.
* Add tests for notifyQuantityChanges
* Show notice when multiple_of is updated
* Update test to test for multiple_of changes
* Remove empty export
* Remove controls from cart data store
Not needed anymore since the exported value from the shared-controls file was empty.
* Export a control and async function for apiFetchWithHeaders
This is required because async functions cannot be called from sync generators.
* Use control version of apiFetchWithHeaders in the collections store
* Improve comments and remove incorrect TypeScript
* Update assets/js/data/cart/actions.ts
Co-authored-by: Mike Jolley <mike.jolley@me.com>
* Update ResolveSelectFromMap to include selectors too
* Update TS in actions
* Use finally to remove duplicate code
* remove item pending delete/qty update after action runs in all cases
This will also reset the state when the request to remove it/change quantity errors
* Remove unnecessary type from param.
Not needed because we have TS now. The description can stay though, it is useful.
* Update snackbar wording to use active voice
* Remove old WP version check
* Set max quantity to high number instead of null
This would only happen in a niche case, and would require several TS changes to fix, so it's better to set it as a number here. 9999 should be high enough, and is the default quantity limit set below in get_product_quantity_limit
* Set code on woocommerce_rest_cart_invalid_key to 409
This is so the cart is returned in the response, so the client can update.
* Fix typo in comment and add CartSelectFromMap
* Remove unnecessary docblock
* Add getItemsPendingDelete selector
This is needed so we can show a notice for items that are unexpectedly removed from the cart. We need to know which ones are pending delete so we can skip showing the notice for them.
* Add type for notifyQuantityChanges args and change args to object
* Add notifyIfRemoved function
This will check items that have been removed and show a notice for them.
* Fix TS in receiveCart & pass itemsPendingDelete to notifyQuantiyChanges
* Update wording on removal notice
* Update types for notifyQuantityChanges args
* Update tests to reflect new wording and args being an object
* Check item is truth before running comparison of keys
* Update tests for unexpectedly and expectedly removed items
* Ignore print_r to satisfy phpcs
* Update PHP tests to reflect correct response code when deleting items
* Remove unnecessary controls and dispatch events directly from thunk
Co-authored-by: Mike Jolley <mike.jolley@me.com>
2022-12-16 16:06:37 +00:00
|
|
|
interface NotifyQuantityChangesArgs {
|
|
|
|
oldCart: Cart;
|
|
|
|
newCart: Cart;
|
|
|
|
cartItemsPendingQuantity?: string[] | undefined;
|
|
|
|
cartItemsPendingDelete?: string[] | undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
const isWithinQuantityLimits = ( cartItem: CartItem ) => {
|
|
|
|
return (
|
|
|
|
cartItem.quantity >= cartItem.quantity_limits.minimum &&
|
|
|
|
cartItem.quantity <= cartItem.quantity_limits.maximum &&
|
|
|
|
cartItem.quantity % cartItem.quantity_limits.multiple_of === 0
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const notifyIfQuantityLimitsChanged = ( oldCart: Cart, newCart: Cart ) => {
|
|
|
|
newCart.items.forEach( ( cartItem ) => {
|
|
|
|
const oldCartItem = oldCart.items.find( ( item ) => {
|
|
|
|
return item && item.key === cartItem.key;
|
|
|
|
} );
|
|
|
|
|
|
|
|
// If getCartData has not finished resolving, then this is the first load.
|
|
|
|
const isFirstLoad = oldCart.items.length === 0;
|
|
|
|
|
|
|
|
// Item has been removed, we don't need to do any more checks.
|
|
|
|
if ( ! oldCartItem && ! isFirstLoad ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( isWithinQuantityLimits( cartItem ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const quantityAboveMax =
|
|
|
|
cartItem.quantity > cartItem.quantity_limits.maximum;
|
|
|
|
const quantityBelowMin =
|
|
|
|
cartItem.quantity < cartItem.quantity_limits.minimum;
|
|
|
|
const quantityOutOfStep =
|
|
|
|
cartItem.quantity % cartItem.quantity_limits.multiple_of !== 0;
|
|
|
|
|
|
|
|
// If the quantity is still within the constraints, then we don't need to show any notice, this is because
|
|
|
|
// QuantitySelector will not automatically update the value.
|
|
|
|
if ( ! quantityAboveMax && ! quantityBelowMin && ! quantityOutOfStep ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( quantityOutOfStep ) {
|
|
|
|
dispatch( 'core/notices' ).createInfoNotice(
|
|
|
|
sprintf(
|
|
|
|
/* translators: %1$s is the name of the item, %2$d is the quantity of the item. %3$d is a number that the quantity must be a multiple of. */
|
|
|
|
__(
|
|
|
|
'The quantity of "%1$s" was changed to %2$d. You must purchase this product in groups of %3$d.',
|
|
|
|
'woo-gutenberg-products-block'
|
|
|
|
),
|
|
|
|
cartItem.name,
|
|
|
|
// We round down to the nearest step value here. We need to do it this way because at this point we
|
|
|
|
// don't know the next quantity. That only gets set once the HTML Input field applies its min/max
|
|
|
|
// constraints.
|
|
|
|
Math.floor(
|
|
|
|
cartItem.quantity / cartItem.quantity_limits.multiple_of
|
|
|
|
) * cartItem.quantity_limits.multiple_of,
|
|
|
|
cartItem.quantity_limits.multiple_of
|
|
|
|
),
|
|
|
|
{
|
|
|
|
context: 'wc/cart',
|
|
|
|
speak: true,
|
|
|
|
type: 'snackbar',
|
|
|
|
id: `${ cartItem.key }-quantity-update`,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( quantityBelowMin ) {
|
|
|
|
dispatch( 'core/notices' ).createInfoNotice(
|
|
|
|
sprintf(
|
|
|
|
/* translators: %1$s is the name of the item, %2$d is the quantity of the item. */
|
|
|
|
__(
|
|
|
|
'The quantity of "%1$s" was increased to %2$d. This is the minimum required quantity.',
|
|
|
|
'woo-gutenberg-products-block'
|
|
|
|
),
|
|
|
|
cartItem.name,
|
|
|
|
cartItem.quantity_limits.minimum
|
|
|
|
),
|
|
|
|
{
|
|
|
|
context: 'wc/cart',
|
|
|
|
speak: true,
|
|
|
|
type: 'snackbar',
|
|
|
|
id: `${ cartItem.key }-quantity-update`,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Quantity is above max, so has been reduced.
|
|
|
|
dispatch( 'core/notices' ).createInfoNotice(
|
|
|
|
sprintf(
|
|
|
|
/* translators: %1$s is the name of the item, %2$d is the quantity of the item. */
|
|
|
|
__(
|
|
|
|
'The quantity of "%1$s" was decreased to %2$d. This is the maximum allowed quantity.',
|
|
|
|
'woo-gutenberg-products-block'
|
|
|
|
),
|
|
|
|
cartItem.name,
|
|
|
|
cartItem.quantity_limits.maximum
|
|
|
|
),
|
|
|
|
{
|
|
|
|
context: 'wc/cart',
|
|
|
|
speak: true,
|
|
|
|
type: 'snackbar',
|
|
|
|
id: `${ cartItem.key }-quantity-update`,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
|
|
|
const notifyIfQuantityChanged = (
|
|
|
|
oldCart: Cart,
|
|
|
|
newCart: Cart,
|
|
|
|
cartItemsPendingQuantity: string[]
|
|
|
|
) => {
|
|
|
|
newCart.items.forEach( ( cartItem ) => {
|
|
|
|
if ( cartItemsPendingQuantity.includes( cartItem.key ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const oldCartItem = oldCart.items.find( ( item ) => {
|
|
|
|
return item && item.key === cartItem.key;
|
|
|
|
} );
|
|
|
|
if ( ! oldCartItem ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( cartItem.key === oldCartItem.key ) {
|
|
|
|
if (
|
|
|
|
cartItem.quantity !== oldCartItem.quantity &&
|
|
|
|
isWithinQuantityLimits( cartItem )
|
|
|
|
) {
|
|
|
|
dispatch( 'core/notices' ).createInfoNotice(
|
|
|
|
sprintf(
|
|
|
|
/* translators: %1$s is the name of the item, %2$d is the quantity of the item. */
|
|
|
|
__(
|
|
|
|
'The quantity of "%1$s" was changed to %2$d.',
|
|
|
|
'woo-gutenberg-products-block'
|
|
|
|
),
|
|
|
|
cartItem.name,
|
|
|
|
cartItem.quantity
|
|
|
|
),
|
|
|
|
{
|
|
|
|
context: 'wc/cart',
|
|
|
|
speak: true,
|
|
|
|
type: 'snackbar',
|
|
|
|
id: `${ cartItem.key }-quantity-update`,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return cartItem;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether the old cart contains an item that the new cart doesn't, and that the item was not slated for removal.
|
|
|
|
*
|
|
|
|
* @param oldCart The old cart.
|
|
|
|
* @param newCart The new cart.
|
|
|
|
* @param cartItemsPendingDelete The cart items that are pending deletion.
|
|
|
|
*/
|
|
|
|
const notifyIfRemoved = (
|
|
|
|
oldCart: Cart,
|
|
|
|
newCart: Cart,
|
|
|
|
cartItemsPendingDelete: string[]
|
|
|
|
) => {
|
|
|
|
oldCart.items.forEach( ( oldCartItem ) => {
|
|
|
|
if ( cartItemsPendingDelete.includes( oldCartItem.key ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const newCartItem = newCart.items.find( ( item: CartItem ) => {
|
|
|
|
return item && item.key === oldCartItem.key;
|
|
|
|
} );
|
|
|
|
|
|
|
|
if ( ! newCartItem ) {
|
|
|
|
dispatch( 'core/notices' ).createInfoNotice(
|
|
|
|
sprintf(
|
|
|
|
/* translators: %s is the name of the item. */
|
|
|
|
__(
|
|
|
|
'"%s" was removed from your cart.',
|
|
|
|
'woo-gutenberg-products-block'
|
|
|
|
),
|
|
|
|
oldCartItem.name
|
|
|
|
),
|
|
|
|
{
|
|
|
|
context: 'wc/cart',
|
|
|
|
speak: true,
|
|
|
|
type: 'snackbar',
|
|
|
|
id: `${ oldCartItem.key }-removed`,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function is used to notify the user when the quantity of an item in the cart has changed. It checks both the
|
|
|
|
* item's quantity and quantity limits.
|
|
|
|
*/
|
|
|
|
export const notifyQuantityChanges = ( {
|
|
|
|
oldCart,
|
|
|
|
newCart,
|
|
|
|
cartItemsPendingQuantity = [],
|
|
|
|
cartItemsPendingDelete = [],
|
|
|
|
}: NotifyQuantityChangesArgs ) => {
|
2023-01-25 16:28:41 +00:00
|
|
|
const isResolutionFinished =
|
|
|
|
select( CART_STORE_KEY ).hasFinishedResolution( 'getCartData' );
|
|
|
|
if ( ! isResolutionFinished ) {
|
|
|
|
return;
|
|
|
|
}
|
Add notice on quantity change and update `wc/store/cart` to use thunks (https://github.com/woocommerce/woocommerce-blocks/pull/7938)
* Add receiveCart thunk
* Add mapCartResponseToCart helper
* Add getItemsPendingQuantityUpdate selector
* Update cart resolvers to be thunks
* Remove RECEIVE_CART action and replace with SET_CART_DATA
receiveCart will turn into a thunk.
* Add notifyQuantityChanges functions
* Remove receiveCart from action type definition, replace with setCartData
* Move apiFetchWithHeaders out of controls
This will just be a normal function since we'll be updating actions to thunks which will use this instead of a control.
* Include thunks in actions file
* Update receiveCart action to setCartData
* Update applyCoupon action to a thunk
* Update useStoreCartCoupons to get action from correct place
* Update StoreCartCoupon types
* Add types for Thunk and ThunkReturnType in mapped-types
* Change applyCoupon to a thunk
* Get applyCoupon, removeCoupon, receiveApplyingCoupon from useDispatch
This is to separate the concerns of actions vs. selectors. Previously the actions were fetched during useSelect which is not a pattern we use anywhere else in the codebase. Since we updated the MapToDispatch type, we can now get correctly typed thunks from the data store.
* Improve apiFetchWithHeaders typings
* Convert removeCoupon from generator to thunk
* Add applyCoupon and removeCoupon to CartAction type
* Remove unused old-style type-def
* Add receiveApplyingCoupon & receiveRemovingCoupon to StoreCartCoupon
* Correct issues with StoreCartCoupon type
These were not intended to reflect the actions in data store, rather the functions offered by the useStoreCartCoupons hook.
* Update applyExtensionCartUpdate to a thunk
* Update addItemToCart to thunk
* Add ResolveSelectFromMap type that works with thunks
* Add CartDispatchFromMap and CartResolveSelectFromMap types
We can add this to all data stores to get them working with thunks properly.
* Add docs and update generic name in ResolveSelectFromMap
* Add correct types for thunk resolvers in cart data store
* Update removeItemFromCart to thunk
* Update apiFetchWithHeaders to use generic
* Update selectShippingRate to thunk
* Update resolver tests to test correct thunk functionality
* Update updateCustomerData to thunk
* Update reducer test to reflect new action name
* Update comments on CartDispatchFromMap and CartResolveSelectFromMap
* Add quantity_limits to preview cart
* Make notices speak when shown
* Remove copilot comment
* Add isWithinQuantityLimits function
This is because we shouldn't show a notice if the quantity limits change, but the item's quantity is still OK.
* Add tests for notifyQuantityChanges
* Show notice when multiple_of is updated
* Update test to test for multiple_of changes
* Remove empty export
* Remove controls from cart data store
Not needed anymore since the exported value from the shared-controls file was empty.
* Export a control and async function for apiFetchWithHeaders
This is required because async functions cannot be called from sync generators.
* Use control version of apiFetchWithHeaders in the collections store
* Improve comments and remove incorrect TypeScript
* Update assets/js/data/cart/actions.ts
Co-authored-by: Mike Jolley <mike.jolley@me.com>
* Update ResolveSelectFromMap to include selectors too
* Update TS in actions
* Use finally to remove duplicate code
* remove item pending delete/qty update after action runs in all cases
This will also reset the state when the request to remove it/change quantity errors
* Remove unnecessary type from param.
Not needed because we have TS now. The description can stay though, it is useful.
* Update snackbar wording to use active voice
* Remove old WP version check
* Set max quantity to high number instead of null
This would only happen in a niche case, and would require several TS changes to fix, so it's better to set it as a number here. 9999 should be high enough, and is the default quantity limit set below in get_product_quantity_limit
* Set code on woocommerce_rest_cart_invalid_key to 409
This is so the cart is returned in the response, so the client can update.
* Fix typo in comment and add CartSelectFromMap
* Remove unnecessary docblock
* Add getItemsPendingDelete selector
This is needed so we can show a notice for items that are unexpectedly removed from the cart. We need to know which ones are pending delete so we can skip showing the notice for them.
* Add type for notifyQuantityChanges args and change args to object
* Add notifyIfRemoved function
This will check items that have been removed and show a notice for them.
* Fix TS in receiveCart & pass itemsPendingDelete to notifyQuantiyChanges
* Update wording on removal notice
* Update types for notifyQuantityChanges args
* Update tests to reflect new wording and args being an object
* Check item is truth before running comparison of keys
* Update tests for unexpectedly and expectedly removed items
* Ignore print_r to satisfy phpcs
* Update PHP tests to reflect correct response code when deleting items
* Remove unnecessary controls and dispatch events directly from thunk
Co-authored-by: Mike Jolley <mike.jolley@me.com>
2022-12-16 16:06:37 +00:00
|
|
|
notifyIfRemoved( oldCart, newCart, cartItemsPendingDelete );
|
|
|
|
notifyIfQuantityLimitsChanged( oldCart, newCart );
|
|
|
|
notifyIfQuantityChanged( oldCart, newCart, cartItemsPendingQuantity );
|
|
|
|
};
|