@shopgate/engage
Version:
Shopgate's ENGAGE library.
145 lines • 19.2 kB
JavaScript
var _excluded=["geolocation"];function _objectWithoutProperties(source,excluded){if(source==null)return{};var target=_objectWithoutPropertiesLoose(source,excluded);var key,i;if(Object.getOwnPropertySymbols){var sourceSymbolKeys=Object.getOwnPropertySymbols(source);for(i=0;i<sourceSymbolKeys.length;i++){key=sourceSymbolKeys[i];if(excluded.indexOf(key)>=0)continue;if(!Object.prototype.propertyIsEnumerable.call(source,key))continue;target[key]=source[key];}}return target;}function _objectWithoutPropertiesLoose(source,excluded){if(source==null)return{};var target={};var sourceKeys=Object.keys(source);var key,i;for(i=0;i<sourceKeys.length;i++){key=sourceKeys[i];if(excluded.indexOf(key)>=0)continue;target[key]=source[key];}return target;}function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import{createSelector}from'reselect';import pickBy from'lodash/pickBy';import{getExternalCustomerNumber,getUserData,getUserId}from'@shopgate/engage/user';import{generateSortedHash}from'@shopgate/pwa-common/helpers/redux/generateSortedHash';import{getProduct}from'@shopgate/engage/product/selectors/product';import{getCurrentRoute}from'@shopgate/pwa-common/selectors/router';import{getIsLocationBasedShopping,makeUseLocationFulfillmentMethods}from'@shopgate/engage/core/selectors';import{makeGetEnabledFulfillmentMethods}from"../../core/config";import{makeIsProductActive,makeIsBaseProductActive}from"../../product/selectors/product";import{isProductAvailable}from"../helpers/productInventory";import{DIRECT_SHIP,NEARBY_LOCATIONS_LIMIT,NEARBY_LOCATIONS_RADIUS}from"../constants";/**
* Selector to retrieve a product's fulfillment methods.
* @returns {Function}
*/export var getProductFulfillmentMethods=createSelector(getProduct,function(product){if(!product||!product.fulfillmentMethods||product.fulfillmentMethods.length===0){return null;}return product.fulfillmentMethods;});/**
* Gets the location state.
* @param {Object} state State.
* @return {Object}
*/var getLocationsState=function getLocationsState(state){return state.locations||{};};/**
* Gets the location storage state.
* @param {Object} state State.
* @return {Object}
*/export var getLocationsStorage=function getLocationsStorage(state){return state.locations.storage;};/**
* Gets the location user state.
* @param {Object} state State.
* @return {Object}
*/var getUserState=function getUserState(state){return state.locations.user||{};};/**
* Retrieves the store finder search.
* @param {Object} state State.
* @returns {Object}
*/export var getStoreFinderSearch=function getStoreFinderSearch(state){var locationState=getLocationsState(state);return locationState.storeFinderSearch;};/**
* Retrieves the store finder search radius.
* @param {Object} state State.
* @returns {Object}
*/export var getStoreFinderSearchRadius=createSelector(getStoreFinderSearch,function(search){return search.radius||null;});/**
* Creates a selector that retrieves a filtered list of locations
* @param {Function} getFilters Has to retrieve the filters.
* @returns {Object}
*/export var makeGetFilteredLocations=function makeGetFilteredLocations(getFilters){return createSelector(getLocationsStorage,getFilters,function(storage,filters){// Get base locations.
var key=generateSortedHash(filters);var codes=storage.locationsByFilter[key]||[];var locations=codes.map(function(code){return storage.locationsByCode[code];});// Enhance with inventory data.
var productCode=filters.productCode;if(!productCode){return locations;}return locations.map(function(location){var pair=generateSortedHash({productCode:productCode,locationCode:location.code});var inventory=storage.inventoriesByCodePair[pair]||null;if(inventory){return _extends({},location,{inventory:inventory});}return location;});});};/**
* Creates a selector that retrieves active filter.
* @param {Object} state State.
* @returns {Object}
*/export var getActiveFilter=createSelector(getLocationsState,function(locationsState){var _locationsState$userS=locationsState.userSearch,geolocation=_locationsState$userS.geolocation,rest=_objectWithoutProperties(_locationsState$userS,_excluded);var longitude;var latitude;if(geolocation){longitude=geolocation.longitude;latitude=geolocation.latitude;}return pickBy(_extends({},rest,{longitude:longitude,latitude:latitude}));});/**
* Creates a selector that retrieves all locations for a given product.
* @param {Function} getProductCode Has to retrieve the product code.
* @returns {Object}
*/export var makeGetLocationsForProduct=function makeGetLocationsForProduct(getProductCode){/* eslint-disable require-jsdoc */var getFilters=function getFilters(state,props){return _extends({productCode:getProductCode(state,props)},pickBy(getActiveFilter(state)));};/* eslint-enable require-jsdoc */return makeGetFilteredLocations(getFilters);};/**
* Creates a selector that retrieves all locations for the store fonder.
* @returns {Object}
*/export var makeGetLocationsForStoreFinder=function makeGetLocationsForStoreFinder(){/* eslint-disable require-jsdoc */var getFilters=function getFilters(state){return _extends({enableInLocationFinder:true},pickBy(getStoreFinderSearch(state)),{},pickBy(getActiveFilter(state)));};/* eslint-enable require-jsdoc */return makeGetFilteredLocations(getFilters);};/**
* Selector that retrieves is fetching.
* @param {Object} state State.
* @returns {Object}
*/export var getIsFetching=function getIsFetching(state){return getLocationsStorage(state).isFetching;};/**
* Creates a selector that retrieves all locations for a given product.
* @param {Object} state State.
* @returns {Object}
*/export var getFilteredLocations=makeGetFilteredLocations(getActiveFilter);/**
* Gets the address of the users preferred location.
* @param {Object} state State.
* @return {Object}
*/export var getPreferredLocationAddress=function getPreferredLocationAddress(state){var _storage$locationsByC;var storage=getLocationsStorage(state);var locationCode=storage.preferredLocation.code;return(_storage$locationsByC=storage.locationsByCode[locationCode])===null||_storage$locationsByC===void 0?void 0:_storage$locationsByC.address;};/**
Gets the users preferred location.
* @param {Object} state State.
* @param {Object} props Props.
* @return {Object}
*/export var getPreferredLocation=function getPreferredLocation(state,props){var storage=getLocationsStorage(state);var locationCode=storage.preferredLocation.code;// Figure out default location.
if(!locationCode&&((props===null||props===void 0?void 0:props.productId)||(props===null||props===void 0?void 0:props.variantId))){var getAvailable=makeGetLocationsForProduct(function(_,iprops){return iprops.variantId||iprops.productId;});var available=getAvailable(state,props);return(available===null||available===void 0?void 0:available[0])||null;}return storage.locationsByCode[locationCode]||null;};/**
Gets the users preferred fulfillment method.
* @param {Object} state State.
* @param {Object} props Props.
* @return {Object}
*/export var getPreferredFulfillmentMethod=function getPreferredFulfillmentMethod(state,props){var storage=getLocationsStorage(state);var method=storage.preferredFulfillmentMethod.type;// Figure out a default fo method.
if(!method){try{var available=getProductFulfillmentMethods(state,props);return(available===null||available===void 0?void 0:available[0])||null;}catch(err){return null;}}return method;};/**
* Creates a selector that checks if the preferred fulfillment method is selectable for a product
* @returns {Function}
*/export var isPreferredFulfillmentMethodSelectableForProduct=createSelector(getPreferredFulfillmentMethod,getProductFulfillmentMethods,function(preferredMethod,productMethods){if(!preferredMethod||!Array.isArray(productMethods)){return false;}return productMethods.includes(preferredMethod);});/**
* Retrieves the user's search.
* @param {Object} state State.
* @returns {Object}
*/export var getUserSearch=function getUserSearch(state){var locationState=getLocationsState(state);return locationState.userSearch;};/**
* Retrieves the country code from the user's search.
* @param {Object} state State.
* @returns {string}
*/export var getUserSearchCountryCode=function getUserSearchCountryCode(state){var userSearch=getUserSearch(state);return userSearch.countryCode||'';};/**
* @param {Object} state State.
* @returns {string}
*/export var getUserSearchGeolocation=function getUserSearchGeolocation(state){var userSearch=getUserSearch(state);return userSearch.geolocation;};/**
* Get user current geolocation
* @param {Object} state State.
* @returns {string}
*/export var getUserGeolocation=createSelector(getUserState,function(state){return state.geolocation||null;});/**
* Retrieves the postal code from the user's search.
* @param {Object} state State.
* @returns {string}
*/export var getUserSearchPostalCode=function getUserSearchPostalCode(state){var userSearch=getUserSearch(state);return userSearch.postalCode;};/**
* Creates a new selector that retrieves a location by its code.
* @param {Function} getLocationCode Has to retrieve the location code.
* @returns {Object}
*/export var makeGetLocation=function makeGetLocation(getLocationCode){return function(state,props){var locationCode=getLocationCode(state,props);return getLocationsStorage(state).locationsByCode[locationCode]||null;};};/**
* Creates a selector that retrieves the inventory for a product at a location.
* @param {Function} getLocationCode Has to retrieve the location code.
* @param {Function} getProductCode Has to retrieve the product code.
* @returns {Object}
*/export var makeGetLocationInventory=function makeGetLocationInventory(getLocationCode,getProductCode){return function(state,props){var locationCode=getLocationCode(state,props);var productCode=getProductCode(state,props);var storage=getLocationsStorage(state);var pair=generateSortedHash({productCode:productCode,locationCode:locationCode});return storage.inventoriesByCodePair[pair]||null;};};/**
* Creates a selector that retrieves the fulfillment methods for a product at a location.
* @param {Function} getLocationCode Has to retrieve the location code.
* @returns {Object}
*/export var makeGetLocationFulfillmentMethods=function makeGetLocationFulfillmentMethods(getLocationCode){var getLocation=makeGetLocation(getLocationCode);return createSelector(getLocation,function(location){return(location===null||location===void 0?void 0:location.supportedFulfillmentMethods)||[];});};/**
* Creates a selector that determines if a location supports a specified fulfillment method.
* @param {Function} getLocationCode Has to retrieve the location code.
* @param {string} fulfillmentMethod The fulfillment method to check.
* @returns {Function}
*/export var makeIsLocationFulfillmentMethodEnabled=function makeIsLocationFulfillmentMethodEnabled(getLocationCode,fulfillmentMethod){var getLocationFulfillmentMethods=makeGetLocationFulfillmentMethods(getLocationCode);return createSelector(getLocationFulfillmentMethods,function(state){return state;},function(state,props){return props;},function(fulfillmentMethods,state,props){if(!fulfillmentMethods){return false;}var method=typeof fulfillmentMethod==='function'?fulfillmentMethod(state,props):fulfillmentMethod;return fulfillmentMethods.includes(method);});};/**
* Selector that retrieves the user's reserve form input.
* @returns {Function}
*/export var getUserFormInput=createSelector(getLocationsState,getUserData,function(locations,userData){if((!locations||!locations.userFormInput)&&!userData){return null;}var _ref=userData||{},firstName=_ref.firstName,lastName=_ref.lastName,email=_ref.mail;var _ref2=locations||{},_ref2$userFormInput=_ref2.userFormInput,userFormInput=_ref2$userFormInput===void 0?{}:_ref2$userFormInput;return _extends({firstName:firstName,lastName:lastName,email:email},userFormInput);});/**
* Creates a selector that retrieves the flag that decides if a product is currently orderable.
* @param {Function} getLocationCode Has to retrieve the location code.
* @param {Function} getProductCode Has to retrieve the product code.
* @returns {Function}
*/export var makeIsRopeProductOrderable=function makeIsRopeProductOrderable(getLocationCode,getProductCode){var getInventory=makeGetLocationInventory(getLocationCode,getProductCode);var getLocation=makeGetLocation(getLocationCode);return createSelector(getPreferredFulfillmentMethod,getLocation,getInventory,isPreferredFulfillmentMethodSelectableForProduct,function(fulfillmentMethod,location,inventory,fulfillmentMethodSelectable){if(fulfillmentMethod===DIRECT_SHIP){return null;}if(!fulfillmentMethodSelectable){return false;}if(location===null){return false;}return isProductAvailable(location,inventory);});};/**
* Creates a selector that checks if the Fulfillment Selector should be disabled.
* @param {Function} getLocationCode Has to retrieve the location code.
* @param {Function} getProductCode Has to retrieve the product code.
* @param {string} fulfillmentMethod The fulfillment method to check.
* @param {bool} ignoreLocationMethods[false] Wether the location fulfillment methods are ignored
* @returns {Function}
*/export var makeIsFulfillmentSelectorMethodEnabled=function makeIsFulfillmentSelectorMethodEnabled(getLocationCode,getProductCode,fulfillmentMethod){var ignoreLocationMethods=arguments.length>3&&arguments[3]!==undefined?arguments[3]:false;var getLocation=makeGetLocation(getLocationCode);var getInventory=makeGetLocationInventory(getLocationCode,getProductCode);var getMerchantFulfillmentMethods=makeGetEnabledFulfillmentMethods();var isProductActive=makeIsProductActive();var isBaseProductActive=makeIsBaseProductActive();var useLocationFulfillmentMethods=makeUseLocationFulfillmentMethods();var getLocationFulfillmentMethods=makeGetLocationFulfillmentMethods(getLocationCode);return createSelector(isProductActive,isBaseProductActive,getLocation,getInventory,getMerchantFulfillmentMethods,getProductFulfillmentMethods,getLocationFulfillmentMethods,getIsLocationBasedShopping,useLocationFulfillmentMethods,function(productActive,baseProductActive,location,inventory,merchantMethods,productMethods,locationMethods,isLocationBasedShopping,locationFulfillmentMethodsUsed){if(!productActive||!baseProductActive){return false;}if(isLocationBasedShopping&&(!location||!inventory)){return false;}var methodSupported=Array.isArray(merchantMethods)&&merchantMethods.includes(fulfillmentMethod)&&Array.isArray(productMethods)&&productMethods.includes(fulfillmentMethod);if(fulfillmentMethod===DIRECT_SHIP&&methodSupported){return true;}if(locationFulfillmentMethodsUsed&&!ignoreLocationMethods&&location){methodSupported=methodSupported&&Array.isArray(locationMethods)&&locationMethods.includes(fulfillmentMethod);}if(!methodSupported){return false;}return true;});};/**
* Returns the externalCustomerNumber that is used to create a new order.
*/export var getExternalCustomerNumberForOrder=createSelector(getUserId,getExternalCustomerNumber,function(id,externalCustomerNumber){if(externalCustomerNumber){return externalCustomerNumber.toString();}if(id){return id.toString();}return undefined;});/**
* Returns the pending state.
* @param {Object} state State
* @returns {boolean}
*/export var getIsPending=function getIsPending(state){return getLocationsStorage(state).pending;};/**
* Checks if the cart state is currently configurable
* During checkout the state is read only to make sure
* the user can't switch locations and timeslots.
*/export var getIsCartStateConfigurable=createSelector(getCurrentRoute,function(route){var _route$pathname;return(route===null||route===void 0?void 0:(_route$pathname=route.pathname)===null||_route$pathname===void 0?void 0:_route$pathname.indexOf('checkout'))===-1;});/**
* Get fulfillment slots for a location.
* @param {string} getLocationCode Location code selector.
* @returns {Array}
*/export var makeGetFulfillmentSlotsForLocation=function makeGetFulfillmentSlotsForLocation(getLocationCode){return createSelector(getLocationsStorage,getLocationCode,function(storage,locationCode){var _storage$fulfillmentS;return(_storage$fulfillmentS=storage.fulfillmentSlotsByLocation)===null||_storage$fulfillmentS===void 0?void 0:_storage$fulfillmentS[locationCode];});};/**
* Get alternative location params by geo location, preferred location, etc.
* @type {Object}
*/export var getProductAlternativeLocationParams=createSelector(getUserGeolocation,getUserSearch,getPreferredLocation,function(userGeolocation,userSearch,preferredLocation){if(!userSearch){return null;}var params={countryCode:userSearch.countryCode};if(userGeolocation){params.geolocation=userGeolocation;}else if(userSearch.geolocation){params.geolocation=userSearch.geolocation;}else if(userSearch.postalCode){params.postalCode=userSearch.postalCode;}else if(preferredLocation){params.geolocation={latitude:preferredLocation.latitude,longitude:preferredLocation.longitude};}return params;});/**
* @param {Function} getParams get params for fetch locations.
* @returns {Array}
*/export var getProductAlternativeLocations=createSelector(function(_,props){return props.productId;},function(_,props){return props.params;},getLocationsStorage,getProductAlternativeLocationParams,function(productId,propsParams,storage,alternativeParams){if(!alternativeParams){return null;}var fetchParams=_extends({productCode:productId},alternativeParams,{},propsParams);if(fetchParams.geolocation){fetchParams.latitude=fetchParams.geolocation.latitude;fetchParams.longitude=fetchParams.geolocation.longitude;delete fetchParams.geolocation;}var sortedHash=generateSortedHash(fetchParams);var codes=storage.locationsByFilter[sortedHash];if(!codes){return null;}return codes.map(function(code){return storage.locationsByCode[code];}).map(function(location){var pair=generateSortedHash({productCode:productId,locationCode:location.code});var productInventory=storage.inventoriesByCodePair[pair]||{};if(!productInventory.isAvailable){return null;}return _extends({},location,{productInventory:productInventory});}).filter(Boolean);});/**
* Creates a selector that retrieves nearby locations for a location referenced by a location code.
* @param {string} locationCode Location code.
* @returns {Function}
*/export var makeGetNearbyLocationsByLocationCode=function makeGetNearbyLocationsByLocationCode(locationCode){var getFilteredLocationsForRoute=makeGetFilteredLocations(function(state){var routeLocation=makeGetLocation(function(){return locationCode;})(state);return{latitude:routeLocation===null||routeLocation===void 0?void 0:routeLocation.latitude,longitude:routeLocation===null||routeLocation===void 0?void 0:routeLocation.longitude,limit:NEARBY_LOCATIONS_LIMIT,radius:NEARBY_LOCATIONS_RADIUS};});return createSelector(getFilteredLocationsForRoute,function(locations){// remove current location from nearby locations
var filteredLocations=locations.filter(function(location){return location.code!==locationCode;});return filteredLocations;});};