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 <muhsinkeramam@gmail.com>
This commit is contained in:
@@ -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 = () => {
|
||||
<span class="text-base text-n-slate-12 line-clamp-1">
|
||||
{{ question }}
|
||||
</span>
|
||||
<div v-if="!compact" class="flex items-center gap-2">
|
||||
<div v-if="!compact && showMenu" class="flex items-center gap-2">
|
||||
<Policy
|
||||
v-on-clickaway="() => toggleDropdown(false)"
|
||||
:permissions="['administrator']"
|
||||
|
||||
@@ -55,6 +55,12 @@ const statusOptions = computed(() =>
|
||||
}))
|
||||
);
|
||||
|
||||
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(() => {
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<ResponseCard
|
||||
v-for="response in responses"
|
||||
v-for="response in filteredResponses"
|
||||
:id="response.id"
|
||||
:key="response.id"
|
||||
:question="response.question"
|
||||
@@ -380,6 +395,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"
|
||||
|
||||
Reference in New Issue
Block a user