From 1b02ebec68d650e86509e54d536c507411132e2b Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Sat, 12 Jul 2025 10:06:30 +0530 Subject: [PATCH] fix: Approved FAQ not disappearing from pending list after filtering (#11909) # Pull Request Template ## Description This PR fixes an issue where approved FAQs were not removed from the list when filtered by `pending` status. **Fix:** Implemented real-time client-side filtering using a `filteredResponses` computed property in `Index.vue`, updated all list and selection logic to use it, and also hide the card toggle dropdown button when the bulk action checkbox is selected. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? ### Loom video https://www.loom.com/share/216221a4910c44ebb1d49ab9e34c820c?sid=98c9c239-54eb-4bd9-b04d-aeccc55bfb3a ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Muhsin Keloth --- .../captain/assistant/ResponseCard.vue | 6 +- .../dashboard/captain/responses/Index.vue | 58 ++++++++++++------- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/app/javascript/dashboard/components-next/captain/assistant/ResponseCard.vue b/app/javascript/dashboard/components-next/captain/assistant/ResponseCard.vue index 7879411c8..a924ca228 100644 --- a/app/javascript/dashboard/components-next/captain/assistant/ResponseCard.vue +++ b/app/javascript/dashboard/components-next/captain/assistant/ResponseCard.vue @@ -55,6 +55,10 @@ const props = defineProps({ type: Boolean, default: false, }, + showMenu: { + type: Boolean, + default: true, + }, }); const emit = defineEmits(['action', 'navigate', 'select', 'hover']); @@ -130,7 +134,7 @@ const handleDocumentableClick = () => { {{ question }} -
+
})) ); +const filteredResponses = computed(() => { + return selectedStatus.value === 'pending' + ? responses.value.filter(r => r.status === 'pending') + : responses.value; +}); + const selectedStatusLabel = computed(() => { const status = statusOptions.value.find( option => option.value === selectedStatus.value @@ -94,7 +100,9 @@ const handleEdit = () => { }; const handleAction = ({ action, id }) => { - selectedResponse.value = responses.value.find(response => id === response.id); + selectedResponse.value = filteredResponses.value.find( + response => id === response.id + ); nextTick(() => { if (action === 'delete') { handleDelete(); @@ -139,7 +147,7 @@ const hoveredCard = ref(null); const bulkSelectionState = computed(() => { const selectedCount = bulkSelectedIds.value.size; - const totalCount = responses.value?.length || 0; + const totalCount = filteredResponses.value?.length || 0; return { hasSelected: selectedCount > 0, @@ -152,13 +160,13 @@ const bulkCheckbox = computed({ get: () => bulkSelectionState.value.allSelected, set: value => { bulkSelectedIds.value = value - ? new Set(responses.value.map(r => r.id)) + ? new Set(filteredResponses.value.map(r => r.id)) : new Set(); }, }); const buildSelectedCountLabel = computed(() => { - const count = responses.value?.length || 0; + const count = filteredResponses.value?.length || 0; return bulkSelectionState.value.allSelected ? t('CAPTAIN.RESPONSES.UNSELECT_ALL', { count }) : t('CAPTAIN.RESPONSES.SELECT_ALL', { count }); @@ -174,6 +182,24 @@ const handleCardSelect = id => { bulkSelectedIds.value = selected; }; +const fetchResponseAfterBulkAction = () => { + const hasNoResponsesLeft = filteredResponses.value?.length === 0; + const currentPage = responseMeta.value?.page; + + if (hasNoResponsesLeft) { + // Page is now empty after bulk action. + // Fetch the previous page if not already on the first page. + const pageToFetch = currentPage > 1 ? currentPage - 1 : currentPage; + fetchResponses(pageToFetch); + } else { + // Page still has responses left, re-fetch the same page. + fetchResponses(currentPage); + } + + // Clear selection + bulkSelectedIds.value = new Set(); +}; + const handleBulkApprove = async () => { try { await store.dispatch( @@ -181,8 +207,7 @@ const handleBulkApprove = async () => { Array.from(bulkSelectedIds.value) ); - // Clear selection - bulkSelectedIds.value = new Set(); + fetchResponseAfterBulkAction(); useAlert(t('CAPTAIN.RESPONSES.BULK_APPROVE.SUCCESS_MESSAGE')); } catch (error) { useAlert( @@ -205,23 +230,13 @@ const onPageChange = page => { }; const onDeleteSuccess = () => { - if (responses.value?.length === 0 && responseMeta.value?.page > 1) { + if (filteredResponses.value?.length === 0 && responseMeta.value?.page > 1) { onPageChange(responseMeta.value.page - 1); } }; const onBulkDeleteSuccess = () => { - // Only fetch if no records left - if (responses.value?.length === 0) { - const page = - responseMeta.value?.page > 1 - ? responseMeta.value.page - 1 - : responseMeta.value.page; - fetchResponses(page); - } - - // Clear selection - bulkSelectedIds.value = new Set(); + fetchResponseAfterBulkAction(); }; const handleStatusFilterChange = ({ value }) => { @@ -249,8 +264,8 @@ onMounted(() => { :header-title="$t('CAPTAIN.RESPONSES.HEADER')" :button-label="$t('CAPTAIN.RESPONSES.ADD_NEW')" :is-fetching="isFetching" - :is-empty="!responses.length" - :show-pagination-footer="!isFetching && !!responses.length" + :is-empty="!filteredResponses.length" + :show-pagination-footer="!isFetching && !!filteredResponses.length" :feature-flag="FEATURE_FLAGS.CAPTAIN" @update:current-page="onPageChange" @click="handleCreate" @@ -368,7 +383,7 @@ onMounted(() => {
{ :updated-at="response.updated_at" :is-selected="bulkSelectedIds.has(response.id)" :selectable="hoveredCard === response.id || bulkSelectedIds.size > 0" + :show-menu="!bulkSelectedIds.has(response.id)" @action="handleAction" @navigate="handleNavigationAction" @select="handleCardSelect"