chore: update Captain documents filter UI (#14429)

This commit is contained in:
Sivin Varghese
2026-05-12 11:27:30 +05:30
committed by GitHub
parent de696a55cb
commit 3df827c931
3 changed files with 53 additions and 63 deletions
@@ -1,6 +1,5 @@
<script setup>
import { computed, ref } from 'vue';
import { debounce } from '@chatwoot/utils';
import DocumentFiltersBar from 'dashboard/components-next/captain/assistant/DocumentFiltersBar.vue';
@@ -9,13 +8,9 @@ const emit = defineEmits(['change']);
const source = ref('all');
const status = ref(null);
const sort = ref('recently_updated');
const query = ref('');
const hasActiveFilters = computed(
() =>
source.value !== 'all' ||
Boolean(status.value) ||
Boolean(query.value.trim())
() => source.value !== 'all' || Boolean(status.value)
);
const buildParams = (page = 1) => {
@@ -23,12 +18,10 @@ const buildParams = (page = 1) => {
if (source.value !== 'all') params.source = source.value;
if (status.value) params.filter = status.value;
if (sort.value) params.sort = sort.value;
if (query.value.trim()) params.searchKey = query.value.trim();
return params;
};
const emitChange = () => emit('change');
const debouncedEmitChange = debounce(emitChange, 300);
const handleSourceSelect = sourceKey => {
source.value = sourceKey;
@@ -47,16 +40,10 @@ const handleSortSelect = sortKey => {
emitChange();
};
const handleSearch = value => {
query.value = value;
debouncedEmitChange();
};
const reset = () => {
source.value = 'all';
status.value = null;
sort.value = 'recently_updated';
query.value = '';
};
defineExpose({ buildParams, reset, hasActiveFilters });
@@ -67,10 +54,8 @@ defineExpose({ buildParams, reset, hasActiveFilters });
:active-source-filter="source"
:active-status-filter="status"
:active-sort="sort"
:search-query="query"
@select-source="handleSourceSelect"
@select-status="handleStatusSelect"
@select-sort="handleSortSelect"
@search="handleSearch"
/>
</template>
@@ -1,9 +1,9 @@
<script setup>
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { vOnClickOutside } from '@vueuse/components';
import Icon from 'dashboard/components-next/icon/Icon.vue';
import Input from 'dashboard/components-next/input/Input.vue';
import Button from 'dashboard/components-next/button/Button.vue';
import DropdownMenu from 'dashboard/components-next/dropdown-menu/DropdownMenu.vue';
@@ -11,15 +11,9 @@ const props = defineProps({
activeSourceFilter: { type: String, default: 'all' },
activeStatusFilter: { type: String, default: null },
activeSort: { type: String, default: 'recently_updated' },
searchQuery: { type: String, default: '' },
});
const emit = defineEmits([
'selectSource',
'selectStatus',
'selectSort',
'search',
]);
const emit = defineEmits(['selectSource', 'selectStatus', 'selectSort']);
const { t } = useI18n();
@@ -121,45 +115,27 @@ const handleMenuAction = ({ action, value }) => {
<template>
<div
v-on-clickaway="closeMenu"
class="flex flex-col gap-3 w-full lg:flex-row lg:items-center lg:justify-between"
v-on-click-outside="closeMenu"
class="inline-flex flex-wrap items-center gap-2 pt-2 w-fit"
>
<div class="flex flex-wrap items-center gap-2">
<div v-for="menu in filterMenus" :key="menu.key" class="relative">
<Button
:icon="menu.selected.icon"
slate
outline
:class="{ 'bg-n-slate-9/10': openMenu === menu.key }"
@click="toggleMenu(menu.key)"
>
<span class="min-w-0 truncate">{{ menu.selected.label }}</span>
<Icon icon="i-lucide-chevron-down" class="shrink-0 size-4" />
</Button>
<DropdownMenu
v-if="openMenu === menu.key"
:menu-items="menu.items"
:class="menu.dropdownClass"
class="top-full mt-2 ltr:left-0 rtl:right-0"
@action="handleMenuAction"
/>
</div>
<div v-for="menu in filterMenus" :key="menu.key" class="relative">
<Button
:icon="menu.selected.icon"
slate
size="sm"
:class="{ 'bg-n-slate-9/10': openMenu === menu.key }"
@click="toggleMenu(menu.key)"
>
<span class="min-w-0 truncate">{{ menu.selected.label }}</span>
<Icon icon="i-lucide-chevron-down" class="shrink-0 size-4" />
</Button>
<DropdownMenu
v-if="openMenu === menu.key"
:menu-items="menu.items"
:class="menu.dropdownClass"
class="top-full mt-2 ltr:left-0 rtl:right-0"
@action="handleMenuAction"
/>
</div>
<Input
:model-value="searchQuery"
type="search"
:placeholder="t('CAPTAIN.DOCUMENTS.FILTERS.SEARCH_PLACEHOLDER')"
:custom-input-class="['ltr:!pl-9 rtl:!pr-9']"
class="w-full lg:max-w-72"
@input="emit('search', $event.target.value)"
>
<template #prefix>
<Icon
icon="i-lucide-search"
class="absolute size-4 text-n-slate-11 top-1/2 -translate-y-1/2 ltr:left-3 rtl:right-3"
/>
</template>
</Input>
</div>
</template>