From 5680bdc9d84836621755dfb5127d0ade89ff2e91 Mon Sep 17 00:00:00 2001 From: Aashutosh Soni Date: Tue, 4 Mar 2025 16:44:09 +0530 Subject: [PATCH 1/5] Fixed: fixed double-click issue by adding loading states for accepting, recounting, and updating item statuses and disabled buttons untill action complete in Pending Review Tab (#639) --- src/views/PendingReviewDetail.vue | 41 ++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/views/PendingReviewDetail.vue b/src/views/PendingReviewDetail.vue index e1aaade8..60c4cfcd 100644 --- a/src/views/PendingReviewDetail.vue +++ b/src/views/PendingReviewDetail.vue @@ -134,13 +134,13 @@
- + - + - +
@@ -170,13 +170,13 @@ - + - + - + @@ -235,6 +235,9 @@ let isCountNameUpdating = ref(false) let countName = ref("") let segmentSelected = ref("all") let varianceThreshold = ref(40) +const isAccepting = ref(false); +const isRecounting = ref(false); +const isUpdatingStatus = ref(false); onIonViewWillEnter(async () => { emitter.emit("presentLoader", { message: "Loading cycle count details" }) @@ -413,6 +416,7 @@ async function addProduct() { } async function updateItemStatus(statusId: string, item?: any) { + isUpdatingStatus.value = true; let itemList: Array = [] if(item) { itemList = [{ @@ -431,6 +435,7 @@ async function updateItemStatus(statusId: string, item?: any) { } if(!itemList.length) { + isUpdatingStatus.value = false; return; } @@ -440,19 +445,23 @@ async function updateItemStatus(statusId: string, item?: any) { itemList }) - if(!hasError(resp)) { + const itemsCount = itemList.length + if (!hasError(resp)) { + showToast(translate(`${itemsCount} ${itemsCount > 1 ? 'count items were' : 'count item was'} ${statusId === 'INV_COUNT_REJECTED' ? 'rejected' : 'updated'}.`)) await fetchCountItems(); } else { throw resp.data } } catch(err) { - showToast(translate("Failed to update items")) + showToast(translate(`Failed to update ${itemList.length > 1 ? 'count items' : 'count item'}`)) logger.error("Failed to update items", err) } + isUpdatingStatus.value = false; } async function recountItem(item?: any) { + isRecounting.value = true; let importItemSeqIds: Array = [] if(item) { importItemSeqIds = [item.importItemSeqId] @@ -465,6 +474,7 @@ async function recountItem(item?: any) { } if(!importItemSeqIds.length) { + isRecounting.value = false; return; } @@ -474,16 +484,19 @@ async function recountItem(item?: any) { importItemSeqIds }) - if(!hasError(resp)) { + const itemsCount = importItemSeqIds.length + if (!hasError(resp)) { + showToast(translate(`${itemsCount} ${itemsCount > 1 ? 'count items were' : 'count item was'} recounted.`)) await fetchCountItems(); } else { throw resp.data } } catch(err) { - showToast(translate("Failed to recount items")) + showToast(translate(`Failed to recount ${importItemSeqIds.length > 1 ? 'count items' : 'count item'}`)) logger.error("Failed to recount items", err) } + isRecounting.value = false; } async function completeCount() { @@ -533,6 +546,7 @@ async function reassignCount() { } async function acceptItem(item?: any) { + isAccepting.value = true; const payloads = [] if(item) { payloads.push({ @@ -561,12 +575,15 @@ async function acceptItem(item?: any) { const resp = await Promise.allSettled(payloads.map((payload: any) => CountService.acceptItem(payload))) const isAnyRespHasError = resp.some((response: any) => response.status === "rejected") + + const itemsCount = payloads.length if(isAnyRespHasError) { - showToast(translate("Some of the item(s) are failed to accept")) + showToast(translate(`Failed to accept ${itemsCount > 1 ? 'count items' : 'count item'}`)) } else { - showToast(translate("All of the item(s) are accepted")) + showToast(translate(`${itemsCount} ${itemsCount > 1 ? 'count items were' : 'count item was'} accepted`)) } await fetchCountItems() + isAccepting.value = false; } function openDateTimeModal() { From 4dec5722979e28da7c2a7d0298c5deef261dbfe5 Mon Sep 17 00:00:00 2001 From: Aashutosh Soni Date: Tue, 4 Mar 2025 18:50:00 +0530 Subject: [PATCH 2/5] Fixed: replaced individual loading states with a global loading state for item actions in Pending Review Tab and removed stale changes. (#639) --- src/views/PendingReviewDetail.vue | 48 +++++++++++++------------------ 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/src/views/PendingReviewDetail.vue b/src/views/PendingReviewDetail.vue index 60c4cfcd..adc4a020 100644 --- a/src/views/PendingReviewDetail.vue +++ b/src/views/PendingReviewDetail.vue @@ -134,13 +134,13 @@
- + - + - +
@@ -170,13 +170,13 @@ - + - + - + @@ -235,9 +235,7 @@ let isCountNameUpdating = ref(false) let countName = ref("") let segmentSelected = ref("all") let varianceThreshold = ref(40) -const isAccepting = ref(false); -const isRecounting = ref(false); -const isUpdatingStatus = ref(false); +const isGlobalLoading = ref(false); onIonViewWillEnter(async () => { emitter.emit("presentLoader", { message: "Loading cycle count details" }) @@ -416,7 +414,7 @@ async function addProduct() { } async function updateItemStatus(statusId: string, item?: any) { - isUpdatingStatus.value = true; + isGlobalLoading.value = true; let itemList: Array = [] if(item) { itemList = [{ @@ -435,7 +433,7 @@ async function updateItemStatus(statusId: string, item?: any) { } if(!itemList.length) { - isUpdatingStatus.value = false; + isGlobalLoading.value = false; return; } @@ -445,23 +443,21 @@ async function updateItemStatus(statusId: string, item?: any) { itemList }) - const itemsCount = itemList.length if (!hasError(resp)) { - showToast(translate(`${itemsCount} ${itemsCount > 1 ? 'count items were' : 'count item was'} ${statusId === 'INV_COUNT_REJECTED' ? 'rejected' : 'updated'}.`)) await fetchCountItems(); } else { throw resp.data } } catch(err) { - showToast(translate(`Failed to update ${itemList.length > 1 ? 'count items' : 'count item'}`)) + showToast(translate("Failed to update items")) logger.error("Failed to update items", err) } - isUpdatingStatus.value = false; + isGlobalLoading.value = false; } async function recountItem(item?: any) { - isRecounting.value = true; + isGlobalLoading.value = true; let importItemSeqIds: Array = [] if(item) { importItemSeqIds = [item.importItemSeqId] @@ -474,7 +470,7 @@ async function recountItem(item?: any) { } if(!importItemSeqIds.length) { - isRecounting.value = false; + isGlobalLoading.value = false; return; } @@ -484,19 +480,17 @@ async function recountItem(item?: any) { importItemSeqIds }) - const itemsCount = importItemSeqIds.length if (!hasError(resp)) { - showToast(translate(`${itemsCount} ${itemsCount > 1 ? 'count items were' : 'count item was'} recounted.`)) await fetchCountItems(); } else { throw resp.data } } catch(err) { - showToast(translate(`Failed to recount ${importItemSeqIds.length > 1 ? 'count items' : 'count item'}`)) + showToast(translate("Failed to recount items")) logger.error("Failed to recount items", err) } - isRecounting.value = false; + isGlobalLoading.value = false; } async function completeCount() { @@ -546,7 +540,7 @@ async function reassignCount() { } async function acceptItem(item?: any) { - isAccepting.value = true; + isGlobalLoading.value = true; const payloads = [] if(item) { payloads.push({ @@ -575,15 +569,13 @@ async function acceptItem(item?: any) { const resp = await Promise.allSettled(payloads.map((payload: any) => CountService.acceptItem(payload))) const isAnyRespHasError = resp.some((response: any) => response.status === "rejected") - - const itemsCount = payloads.length if(isAnyRespHasError) { - showToast(translate(`Failed to accept ${itemsCount > 1 ? 'count items' : 'count item'}`)) + showToast(translate("Some of the item(s) are failed to accept")) } else { - showToast(translate(`${itemsCount} ${itemsCount > 1 ? 'count items were' : 'count item was'} accepted`)) + showToast(translate("All of the item(s) are accepted")) } await fetchCountItems() - isAccepting.value = false; + isGlobalLoading.value = false; } function openDateTimeModal() { @@ -661,4 +653,4 @@ ion-footer ion-buttons { padding: 0; } } - + \ No newline at end of file From 322fbbeeb675095420aa83a430ad996a530b535b Mon Sep 17 00:00:00 2001 From: Aashutosh Soni Date: Wed, 5 Mar 2025 11:48:26 +0530 Subject: [PATCH 3/5] Fixed: replaced global loading state with individual loading states for item actions in Pending Review Tab and updated footer loading state. (#639) --- src/views/PendingReviewDetail.vue | 66 ++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/views/PendingReviewDetail.vue b/src/views/PendingReviewDetail.vue index adc4a020..75ccb2bc 100644 --- a/src/views/PendingReviewDetail.vue +++ b/src/views/PendingReviewDetail.vue @@ -134,13 +134,13 @@
- + - + - +
@@ -170,13 +170,13 @@ - + - + - + @@ -235,7 +235,8 @@ let isCountNameUpdating = ref(false) let countName = ref("") let segmentSelected = ref("all") let varianceThreshold = ref(40) -const isGlobalLoading = ref(false); +const itemLoadingStates = ref<{ [key: string]: boolean }>({}); +const footerLoadingState = ref(false); onIonViewWillEnter(async () => { emitter.emit("presentLoader", { message: "Loading cycle count details" }) @@ -414,7 +415,11 @@ async function addProduct() { } async function updateItemStatus(statusId: string, item?: any) { - isGlobalLoading.value = true; + if (item) { + itemLoadingStates.value[item.importItemSeqId] = true; + } else { + footerLoadingState.value = true; + } let itemList: Array = [] if(item) { itemList = [{ @@ -433,7 +438,11 @@ async function updateItemStatus(statusId: string, item?: any) { } if(!itemList.length) { - isGlobalLoading.value = false; + if (item) { + itemLoadingStates.value[item.importItemSeqId] = false; + } else { + footerLoadingState.value = false; + } return; } @@ -453,11 +462,20 @@ async function updateItemStatus(statusId: string, item?: any) { showToast(translate("Failed to update items")) logger.error("Failed to update items", err) } - isGlobalLoading.value = false; + if (item) { + itemLoadingStates.value[item.importItemSeqId] = false; + } else { + footerLoadingState.value = false; + } } async function recountItem(item?: any) { - isGlobalLoading.value = true; + if (item) { + itemLoadingStates.value[item.importItemSeqId] = true; + } else { + footerLoadingState.value = true; + } + let importItemSeqIds: Array = [] if(item) { importItemSeqIds = [item.importItemSeqId] @@ -470,7 +488,11 @@ async function recountItem(item?: any) { } if(!importItemSeqIds.length) { - isGlobalLoading.value = false; + if (item) { + itemLoadingStates.value[item.importItemSeqId] = false; + } else { + footerLoadingState.value = false; + } return; } @@ -490,7 +512,11 @@ async function recountItem(item?: any) { showToast(translate("Failed to recount items")) logger.error("Failed to recount items", err) } - isGlobalLoading.value = false; + if (item) { + itemLoadingStates.value[item.importItemSeqId] = false; + } else { + footerLoadingState.value = false; + } } async function completeCount() { @@ -540,7 +566,12 @@ async function reassignCount() { } async function acceptItem(item?: any) { - isGlobalLoading.value = true; + if (item) { + itemLoadingStates.value[item.importItemSeqId] = true; + } else { + footerLoadingState.value = true; + } + const payloads = [] if(item) { payloads.push({ @@ -575,7 +606,12 @@ async function acceptItem(item?: any) { showToast(translate("All of the item(s) are accepted")) } await fetchCountItems() - isGlobalLoading.value = false; + + if (item) { + itemLoadingStates.value[item.importItemSeqId] = false; + } else { + footerLoadingState.value = false; + } } function openDateTimeModal() { From f4e1fb24504621f6777d337ac4b9aebb48f60dbe Mon Sep 17 00:00:00 2001 From: Aashutosh Soni Date: Mon, 10 Mar 2025 18:26:14 +0530 Subject: [PATCH 4/5] Fixed: indentation issues, refactored variable names and logic refactoration in PendingReviewDetail.vue (#639) --- src/views/PendingReviewDetail.vue | 63 +++++++++++++++---------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/src/views/PendingReviewDetail.vue b/src/views/PendingReviewDetail.vue index 75ccb2bc..bee54f85 100644 --- a/src/views/PendingReviewDetail.vue +++ b/src/views/PendingReviewDetail.vue @@ -134,13 +134,13 @@
- + - + - +
@@ -170,13 +170,13 @@ - + - + - + @@ -235,8 +235,8 @@ let isCountNameUpdating = ref(false) let countName = ref("") let segmentSelected = ref("all") let varianceThreshold = ref(40) -const itemLoadingStates = ref<{ [key: string]: boolean }>({}); -const footerLoadingState = ref(false); +const isUpdatingItem = ref<{ [key: string]: boolean }>({}); +const isUpdatingItemsInBulk = ref(false); onIonViewWillEnter(async () => { emitter.emit("presentLoader", { message: "Loading cycle count details" }) @@ -415,18 +415,15 @@ async function addProduct() { } async function updateItemStatus(statusId: string, item?: any) { - if (item) { - itemLoadingStates.value[item.importItemSeqId] = true; - } else { - footerLoadingState.value = true; - } let itemList: Array = [] if(item) { + isUpdatingItem.value[item.importItemSeqId] = true; itemList = [{ importItemSeqId: item.importItemSeqId, statusId }] } else { + isUpdatingItemsInBulk.value = true; currentCycleCount.value.items.map((item: any) => { if(item.isChecked) { itemList.push({ @@ -438,11 +435,7 @@ async function updateItemStatus(statusId: string, item?: any) { } if(!itemList.length) { - if (item) { - itemLoadingStates.value[item.importItemSeqId] = false; - } else { - footerLoadingState.value = false; - } + resetUpdatingState(item); return; } @@ -457,23 +450,27 @@ async function updateItemStatus(statusId: string, item?: any) { } else { throw resp.data } - } catch(err) { showToast(translate("Failed to update items")) logger.error("Failed to update items", err) + } finally { + resetUpdatingState(item); } +} + +function resetUpdatingState(item?: any) { if (item) { - itemLoadingStates.value[item.importItemSeqId] = false; - } else { - footerLoadingState.value = false; + isUpdatingItem.value[item.importItemSeqId] = false; + } else { + isUpdatingItemsInBulk.value = false; } -} +} async function recountItem(item?: any) { if (item) { - itemLoadingStates.value[item.importItemSeqId] = true; + isUpdatingItem.value[item.importItemSeqId] = true; } else { - footerLoadingState.value = true; + isUpdatingItemsInBulk.value = true; } let importItemSeqIds: Array = [] @@ -489,9 +486,9 @@ async function recountItem(item?: any) { if(!importItemSeqIds.length) { if (item) { - itemLoadingStates.value[item.importItemSeqId] = false; + isUpdatingItem.value[item.importItemSeqId] = false; } else { - footerLoadingState.value = false; + isUpdatingItemsInBulk.value = false; } return; } @@ -513,9 +510,9 @@ async function recountItem(item?: any) { logger.error("Failed to recount items", err) } if (item) { - itemLoadingStates.value[item.importItemSeqId] = false; + isUpdatingItem.value[item.importItemSeqId] = false; } else { - footerLoadingState.value = false; + isUpdatingItemsInBulk.value = false; } } @@ -567,9 +564,9 @@ async function reassignCount() { async function acceptItem(item?: any) { if (item) { - itemLoadingStates.value[item.importItemSeqId] = true; + isUpdatingItem.value[item.importItemSeqId] = true; } else { - footerLoadingState.value = true; + isUpdatingItemsInBulk.value = true; } const payloads = [] @@ -608,9 +605,9 @@ async function acceptItem(item?: any) { await fetchCountItems() if (item) { - itemLoadingStates.value[item.importItemSeqId] = false; + isUpdatingItem.value[item.importItemSeqId] = false; } else { - footerLoadingState.value = false; + isUpdatingItemsInBulk.value = false; } } From 93e019e6045649d59877f6c88b278c0ce6aca83c Mon Sep 17 00:00:00 2001 From: Aashutosh Soni Date: Thu, 27 Mar 2025 15:25:48 +0530 Subject: [PATCH 5/5] Improved: Added isAnyItemUpdating state to manage button disable logic during item updates. (#639) --- src/views/PendingReviewDetail.vue | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/views/PendingReviewDetail.vue b/src/views/PendingReviewDetail.vue index 9b911ef6..197083d2 100644 --- a/src/views/PendingReviewDetail.vue +++ b/src/views/PendingReviewDetail.vue @@ -170,16 +170,16 @@ - + - + - + - + @@ -237,6 +237,9 @@ let segmentSelected = ref("all") let varianceThreshold = ref(40) const isUpdatingItem = ref<{ [key: string]: boolean }>({}); const isUpdatingItemsInBulk = ref(false); +const isAnyItemUpdating = computed(() => { + return Object.values(isUpdatingItem.value).some((isUpdating) => isUpdating); +}); onIonViewWillEnter(async () => { emitter.emit("presentLoader", { message: "Loading cycle count details" }) @@ -426,6 +429,7 @@ async function updateItemStatus(statusId: string, item?: any) { isUpdatingItemsInBulk.value = true; currentCycleCount.value.items.map((item: any) => { if(item.isChecked) { + isUpdatingItem.value[item.importItemSeqId] = true; itemList.push({ importItemSeqId: item.importItemSeqId, statusId @@ -465,6 +469,9 @@ function resetUpdatingState(item?: any) { isUpdatingItem.value[item.importItemSeqId] = false; } else { isUpdatingItemsInBulk.value = false; + currentCycleCount.value.items.forEach((item: any) => { + isUpdatingItem.value[item.importItemSeqId] = false; + }); } } @@ -473,6 +480,11 @@ async function recountItem(item?: any) { isUpdatingItem.value[item.importItemSeqId] = true; } else { isUpdatingItemsInBulk.value = true; + currentCycleCount.value.items.map((item: any) => { + if(item.isChecked) { + isUpdatingItem.value[item.importItemSeqId] = true; + } + }) } let importItemSeqIds: Array = [] @@ -517,6 +529,9 @@ async function recountItem(item?: any) { isUpdatingItem.value[item.importItemSeqId] = false; } else { isUpdatingItemsInBulk.value = false; + currentCycleCount.value.items.forEach((item: any) => { + isUpdatingItem.value[item.importItemSeqId] = false; + }); } } @@ -571,6 +586,11 @@ async function acceptItem(item?: any) { isUpdatingItem.value[item.importItemSeqId] = true; } else { isUpdatingItemsInBulk.value = true; + currentCycleCount.value.items.map((item: any) => { + if(item.isChecked) { + isUpdatingItem.value[item.importItemSeqId] = true; + } + }) } const payloads = [] @@ -614,6 +634,9 @@ async function acceptItem(item?: any) { isUpdatingItem.value[item.importItemSeqId] = false; } else { isUpdatingItemsInBulk.value = false; + currentCycleCount.value.items.forEach((item: any) => { + isUpdatingItem.value[item.importItemSeqId] = false; + }); } }