From c2a14ae6fad3609445707c13e7ba97732b6fcf5e Mon Sep 17 00:00:00 2001 From: Yash Maheshwari Date: Mon, 16 Dec 2024 12:34:17 +0530 Subject: [PATCH] Implemented: vuex store to maintain product information(#254) --- src/store/modules/product/ProductState.ts | 4 ++ src/store/modules/product/actions.ts | 78 +++++++++++++++++++++ src/store/modules/product/getters.ts | 18 +++++ src/store/modules/product/index.ts | 19 +++++ src/store/modules/product/mutation-types.ts | 5 ++ src/store/modules/product/mutations.ts | 22 ++++++ src/store/modules/user/actions.ts | 5 +- 7 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 src/store/modules/product/ProductState.ts create mode 100644 src/store/modules/product/actions.ts create mode 100644 src/store/modules/product/getters.ts create mode 100644 src/store/modules/product/index.ts create mode 100644 src/store/modules/product/mutation-types.ts create mode 100644 src/store/modules/product/mutations.ts diff --git a/src/store/modules/product/ProductState.ts b/src/store/modules/product/ProductState.ts new file mode 100644 index 0000000..77ba763 --- /dev/null +++ b/src/store/modules/product/ProductState.ts @@ -0,0 +1,4 @@ +export default interface ProductState { + products: any; + stock: any; +} \ No newline at end of file diff --git a/src/store/modules/product/actions.ts b/src/store/modules/product/actions.ts new file mode 100644 index 0000000..7bc842d --- /dev/null +++ b/src/store/modules/product/actions.ts @@ -0,0 +1,78 @@ +import { ActionTree } from "vuex" +import RootState from "@/store/RootState" +import ProductState from "./ProductState" +import logger from "@/logger" +import { hasError } from "@/utils" +import * as types from "./mutation-types" +import { ProductService } from "@/services/ProductService" + +const actions: ActionTree = { + async fetchProducts({ commit, state }, productIds) { + const cachedProductIds = Object.keys(state.products); + const productIdFilter= productIds.reduce((filter: string, productId: any) => { + // If product already exist in cached products skip + if (cachedProductIds.includes(productId)) { + return filter; + } else { + // checking condition that if the filter is not empty then adding 'OR' to the filter + if (filter !== '') filter += ' OR ' + return filter += productId; + } + }, ''); + + // If there are no products skip the API call + if (productIdFilter === '') return; + + try { + // adding viewSize as by default we are having the viewSize of 10 + const resp = await ProductService.fetchProducts({ + "filters": ['productId: (' + productIdFilter + ')'], + "viewSize": productIds.length + }) + if(resp.data.response && !hasError(resp)) { + const products = resp.data.response.docs.reduce((products: any, product: any) => { + products[product.productId] = product + return products; + }, {}); + // Handled empty response in case of failed query + if(resp.data) commit(types.PRODUCT_LIST_UPDATED, products); + } else { + throw resp.data; + } + } catch(err) { + logger.error("Failed to fetch product information", err) + } + }, + + async fetchStock({ commit, state }, shipGroup) { + const productIds = shipGroup.map((item: any) => item.productId) + const facilityId = shipGroup[0].facilityId + for(const productId of productIds) { + if(state.stock[productId]?.[facilityId]) { + continue; + } + + try { + const payload = { + productId, + facilityId + } + + const resp: any = await ProductService.getInventoryAvailableByFacility(payload); + if (!hasError(resp)) { + commit(types.PRODUCT_STOCK_UPDATED, { productId: payload.productId, facilityId: facilityId, stock: resp.data }) + } else { + throw resp.data; + } + } catch (err) { + logger.error(err) + } + } + }, + + async clearProductState({ commit }) { + commit(types.PRODUCT_CLEARED) + } +} + +export default actions; \ No newline at end of file diff --git a/src/store/modules/product/getters.ts b/src/store/modules/product/getters.ts new file mode 100644 index 0000000..e8c49b6 --- /dev/null +++ b/src/store/modules/product/getters.ts @@ -0,0 +1,18 @@ +import { GetterTree } from "vuex" +import ProductState from "./ProductState" +import RootState from "@/store/RootState" + +const getters: GetterTree = { + getProducts(state) { + return state.products + }, + getProductById: (state) => (id: string) => { + console.log('id', id) + return state.products[id] || {} + }, + getProductStock: (state) => (productId: string, facilityId: string) => { + return state.stock[productId] ? state.stock[productId][facilityId] ? state.stock[productId][facilityId] : {} : {} + }, +} + +export default getters; \ No newline at end of file diff --git a/src/store/modules/product/index.ts b/src/store/modules/product/index.ts new file mode 100644 index 0000000..e3a1ccb --- /dev/null +++ b/src/store/modules/product/index.ts @@ -0,0 +1,19 @@ +import actions from "./actions" +import getters from "./getters" +import mutations from "./mutations" +import { Module } from "vuex" +import ProductState from "./ProductState" +import RootState from "@/store/RootState" + +const productModule: Module = { + namespaced: true, + state: { + products: {}, + stock: {} + }, + getters, + actions, + mutations, +} + +export default productModule; \ No newline at end of file diff --git a/src/store/modules/product/mutation-types.ts b/src/store/modules/product/mutation-types.ts new file mode 100644 index 0000000..29e701d --- /dev/null +++ b/src/store/modules/product/mutation-types.ts @@ -0,0 +1,5 @@ +export const SN_PRODUCT = "product" +export const PRODUCT_LIST_UPDATED = SN_PRODUCT + "/LIST_UPDATED" +export const PRODUCT_STOCK_UPDATED = SN_PRODUCT + "/STOCK_UPDATED" +export const PRODUCT_CLEARED = SN_PRODUCT + "/CLEARED" + diff --git a/src/store/modules/product/mutations.ts b/src/store/modules/product/mutations.ts new file mode 100644 index 0000000..73a79e1 --- /dev/null +++ b/src/store/modules/product/mutations.ts @@ -0,0 +1,22 @@ +import { MutationTree } from "vuex" +import ProductState from "./ProductState" +import * as types from "./mutation-types" + +const mutations: MutationTree = { + [types.PRODUCT_LIST_UPDATED](state, payload) { + state.products = payload + }, + [types.PRODUCT_CLEARED](state) { + state.products = {} + }, + [types.PRODUCT_STOCK_UPDATED] (state, payload) { + if(state.stock[payload.productId]) { + state.stock[payload.productId][payload.facilityId] = payload.stock + } else { + state.stock[payload.productId] = { + [payload.facilityId]: payload.stock + } + } + }, +} +export default mutations; \ No newline at end of file diff --git a/src/store/modules/user/actions.ts b/src/store/modules/user/actions.ts index 8e14d9f..9cfd52c 100644 --- a/src/store/modules/user/actions.ts +++ b/src/store/modules/user/actions.ts @@ -61,13 +61,13 @@ const actions: ActionTree = { Settings.defaultZone = userProfile.timeZone; } - setPermissions(appPermissions); + // setPermissions(appPermissions); if(omsRedirectionUrl && token) { dispatch("setOmsRedirectionInfo", { url: omsRedirectionUrl, token }) } commit(types.USER_TOKEN_CHANGED, { newToken: api_key }) commit(types.USER_INFO_UPDATED, userProfile); - commit(types.USER_PERMISSIONS_UPDATED, appPermissions); + // commit(types.USER_PERMISSIONS_UPDATED, appPermissions); commit(types.USER_CURRENT_ECOM_STORE_UPDATED, userProfile.stores.length ? userProfile.stores[0] : {}); emitter.emit("dismissLoader") } catch (err: any) { @@ -90,6 +90,7 @@ const actions: ActionTree = { commit(types.USER_END_SESSION) this.dispatch("orderRouting/clearRouting") this.dispatch("util/clearUtilState") + this.dispatch("product/clearProductState") dispatch("setOmsRedirectionInfo", { url: "", token: "" }) resetConfig(); resetPermissions();