170 lines
3.9 KiB
TypeScript
170 lines
3.9 KiB
TypeScript
|
/**
|
||
|
* External dependencies
|
||
|
*/
|
||
|
import type { CartItem } from '@woocommerce/types';
|
||
|
import type { Reducer } from 'redux';
|
||
|
|
||
|
/**
|
||
|
* Internal dependencies
|
||
|
*/
|
||
|
import { ACTION_TYPES as types } from './action-types';
|
||
|
import { defaultCartState, CartState } from '../default-states';
|
||
|
import { EMPTY_CART_ERRORS } from '../constants';
|
||
|
import type { CartAction } from './actions';
|
||
|
|
||
|
/**
|
||
|
* Sub-reducer for cart items array.
|
||
|
*
|
||
|
* @param {Array<CartItem>} state cartData.items state slice.
|
||
|
* @param {CartAction} action Action object.
|
||
|
*/
|
||
|
const cartItemsReducer = (
|
||
|
state: Array< CartItem > = [],
|
||
|
action: Partial< CartAction >
|
||
|
) => {
|
||
|
switch ( action.type ) {
|
||
|
case types.RECEIVE_CART_ITEM:
|
||
|
// Replace specified cart element with the new data from server.
|
||
|
return state.map( ( cartItem ) => {
|
||
|
if ( cartItem.key === action.cartItem?.key ) {
|
||
|
return action.cartItem;
|
||
|
}
|
||
|
return cartItem;
|
||
|
} );
|
||
|
}
|
||
|
return state;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Reducer for receiving items related to the cart.
|
||
|
*
|
||
|
* @param {CartState} state The current state in the store.
|
||
|
* @param {CartAction} action Action object.
|
||
|
*
|
||
|
* @return {CartState} New or existing state.
|
||
|
*/
|
||
|
const reducer: Reducer< CartState > = (
|
||
|
state = defaultCartState,
|
||
|
action: Partial< CartAction >
|
||
|
) => {
|
||
|
switch ( action.type ) {
|
||
|
case types.RECEIVE_ERROR:
|
||
|
if ( action.error ) {
|
||
|
state = {
|
||
|
...state,
|
||
|
errors: state.errors.concat( action.error ),
|
||
|
};
|
||
|
}
|
||
|
break;
|
||
|
case types.REPLACE_ERRORS:
|
||
|
if ( action.error ) {
|
||
|
state = {
|
||
|
...state,
|
||
|
errors: [ action.error ],
|
||
|
};
|
||
|
}
|
||
|
break;
|
||
|
case types.RECEIVE_CART:
|
||
|
if ( action.response ) {
|
||
|
state = {
|
||
|
...state,
|
||
|
errors: EMPTY_CART_ERRORS,
|
||
|
cartData: action.response,
|
||
|
};
|
||
|
}
|
||
|
break;
|
||
|
case types.APPLYING_COUPON:
|
||
|
if ( action.couponCode || action.couponCode === '' ) {
|
||
|
state = {
|
||
|
...state,
|
||
|
metaData: {
|
||
|
...state.metaData,
|
||
|
applyingCoupon: action.couponCode,
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
break;
|
||
|
case types.REMOVING_COUPON:
|
||
|
if ( action.couponCode || action.couponCode === '' ) {
|
||
|
state = {
|
||
|
...state,
|
||
|
metaData: {
|
||
|
...state.metaData,
|
||
|
removingCoupon: action.couponCode,
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case types.ITEM_PENDING_QUANTITY:
|
||
|
// Remove key by default - handles isQuantityPending==false
|
||
|
// and prevents duplicates when isQuantityPending===true.
|
||
|
const keysPendingQuantity = state.cartItemsPendingQuantity.filter(
|
||
|
( key ) => key !== action.cartItemKey
|
||
|
);
|
||
|
if ( action.isPendingQuantity && action.cartItemKey ) {
|
||
|
keysPendingQuantity.push( action.cartItemKey );
|
||
|
}
|
||
|
state = {
|
||
|
...state,
|
||
|
cartItemsPendingQuantity: keysPendingQuantity,
|
||
|
};
|
||
|
break;
|
||
|
case types.RECEIVE_REMOVED_ITEM:
|
||
|
const keysPendingDelete = state.cartItemsPendingDelete.filter(
|
||
|
( key ) => key !== action.cartItemKey
|
||
|
);
|
||
|
if ( action.isPendingDelete && action.cartItemKey ) {
|
||
|
keysPendingDelete.push( action.cartItemKey );
|
||
|
}
|
||
|
state = {
|
||
|
...state,
|
||
|
cartItemsPendingDelete: keysPendingDelete,
|
||
|
};
|
||
|
break;
|
||
|
// Delegate to cartItemsReducer.
|
||
|
case types.RECEIVE_CART_ITEM:
|
||
|
state = {
|
||
|
...state,
|
||
|
errors: EMPTY_CART_ERRORS,
|
||
|
cartData: {
|
||
|
...state.cartData,
|
||
|
items: cartItemsReducer( state.cartData.items, action ),
|
||
|
},
|
||
|
};
|
||
|
break;
|
||
|
case types.UPDATING_CUSTOMER_DATA:
|
||
|
state = {
|
||
|
...state,
|
||
|
metaData: {
|
||
|
...state.metaData,
|
||
|
updatingCustomerData: !! action.isResolving,
|
||
|
},
|
||
|
};
|
||
|
break;
|
||
|
case types.UPDATING_SELECTED_SHIPPING_RATE:
|
||
|
state = {
|
||
|
...state,
|
||
|
metaData: {
|
||
|
...state.metaData,
|
||
|
updatingSelectedRate: !! action.isResolving,
|
||
|
},
|
||
|
};
|
||
|
break;
|
||
|
case types.SET_IS_CART_DATA_STALE:
|
||
|
state = {
|
||
|
...state,
|
||
|
metaData: {
|
||
|
...state.metaData,
|
||
|
isCartDataStale: action.isCartDataStale,
|
||
|
},
|
||
|
};
|
||
|
break;
|
||
|
}
|
||
|
return state;
|
||
|
};
|
||
|
|
||
|
export type State = ReturnType< typeof reducer >;
|
||
|
|
||
|
export default reducer;
|