diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue index c3611c4643..bf1fcfdb9c 100644 --- a/src/components/ui/VnFilterPanel.vue +++ b/src/components/ui/VnFilterPanel.vue @@ -75,6 +75,9 @@ const arrayData = useArrayData($props.dataKey, { const route = useRoute(); const store = arrayData.store; const userParams = ref({}); + +defineExpose({ search, sanitizer, params: userParams }); + onMounted(() => { userParams.value = $props.modelValue ?? {}; emit('init', { params: userParams.value }); @@ -198,7 +201,7 @@ const customTags = computed(() => async function remove(key) { userParams.value[key] = undefined; - search(); + await search(); emit('remove', key); emit('update:modelValue', userParams.value); } diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js index 2692317975..da62eee3eb 100644 --- a/src/composables/useArrayData.js +++ b/src/composables/useArrayData.js @@ -75,18 +75,10 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) { limit: store.limit, }; - let exprFilter; let userParams = { ...store.userParams }; - if (store?.exprBuilder) { - const where = buildFilter(userParams, (param, value) => { - const res = store.exprBuilder(param, value); - if (res) delete userParams[param]; - return res; - }); - exprFilter = where ? { where } : null; - } - Object.assign(filter, store.userFilter, exprFilter); + Object.assign(filter, store.userFilter); + let where; if (filter?.where || store.filter?.where) where = Object.assign(filter?.where ?? {}, store.filter?.where ?? {}); @@ -95,12 +87,29 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) { const params = { filter }; Object.assign(params, userParams); - params.filter.skip = store.skip; - if (store.order && store.order.length) params.filter.order = store.order; + if (params.filter) params.filter.skip = store.skip; + if (store?.order && typeof store?.order == 'string') store.order = [store.order]; + if (store.order?.length) params.filter.order = [...store.order]; else delete params.filter.order; + store.currentFilter = JSON.parse(JSON.stringify(params)); + delete store.currentFilter.filter.include; + store.currentFilter.filter = JSON.stringify(store.currentFilter.filter); + + let exprFilter; + if (store?.exprBuilder) { + exprFilter = buildFilter(params, (param, value) => { + if (param == 'filter') return; + const res = store.exprBuilder(param, value); + if (res) delete params[param]; + return res; + }); + } + + if (params.filter.where || exprFilter) + params.filter.where = { ...params.filter.where, ...exprFilter }; params.filter = JSON.stringify(params.filter); - store.currentFilter = params; + store.isLoading = true; const response = await axios.get(store.url, { signal: canceller.signal, diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue index 66a1a132d7..90bce38fd0 100644 --- a/src/pages/Order/Card/OrderCatalog.vue +++ b/src/pages/Order/Card/OrderCatalog.vue @@ -1,14 +1,13 @@ <script setup> import { useStateStore } from 'stores/useStateStore'; import { useRoute, useRouter } from 'vue-router'; -import { onBeforeMount, onMounted, onUnmounted, ref, computed, watch } from 'vue'; +import { onMounted, onUnmounted, ref, computed, watch } from 'vue'; import axios from 'axios'; import { useI18n } from 'vue-i18n'; import VnPaginate from 'src/components/ui/VnPaginate.vue'; import CatalogItem from 'src/components/ui/CatalogItem.vue'; import OrderCatalogFilter from 'src/pages/Order/Card/OrderCatalogFilter.vue'; import VnSearchbar from 'src/components/ui/VnSearchbar.vue'; -import getParamWhere from 'src/filters/getParamWhere'; import { useArrayData } from 'src/composables/useArrayData'; const route = useRoute(); @@ -18,7 +17,6 @@ const { t } = useI18n(); const dataKey = 'OrderCatalogList'; const arrayData = useArrayData(dataKey); const store = arrayData.store; -const showFilter = ref(null); const tags = ref([]); let catalogParams = { @@ -26,27 +24,6 @@ let catalogParams = { orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }), }; -onBeforeMount(() => { - const whereParams = getParamWhere(route); - if (whereParams) { - const formattedWhereParams = {}; - if (whereParams.and) { - whereParams.and.forEach((item) => { - Object.assign(formattedWhereParams, item); - }); - } else { - Object.assign(formattedWhereParams, whereParams); - } - - catalogParams = { - ...catalogParams, - ...formattedWhereParams, - }; - } else { - showFilter.value = true; - } -}); - onMounted(() => { stateStore.rightDrawer = true; checkOrderConfirmation(); @@ -90,7 +67,7 @@ function extractValueTags(items) { ); tagValue.value = resultValueTags; } -const autoLoad = computed(() => !!catalogParams.categoryFk); +const autoLoad = computed(() => !!JSON.parse(route?.query.table ?? '{}')?.categoryFk); watch( () => store.data, @@ -112,7 +89,7 @@ watch( :info="t('You can search items by name or id')" /> <QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above> - <QScrollArea v-if="showFilter" class="fit text-grey-8"> + <QScrollArea class="fit text-grey-8"> <OrderCatalogFilter :data-key="dataKey" :tag-value="tagValue" @@ -128,8 +105,6 @@ watch( url="Orders/CatalogFilter" :limit="50" :user-params="catalogParams" - @on-fetch="showFilter = true" - :update-router="false" :auto-load="autoLoad" > <template #body="{ rows }"> diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue index ec8bc24f2d..b839be55ed 100644 --- a/src/pages/Order/Card/OrderCatalogFilter.vue +++ b/src/pages/Order/Card/OrderCatalogFilter.vue @@ -1,5 +1,5 @@ <script setup> -import { computed, ref, onMounted } from 'vue'; +import { ref } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRoute } from 'vue-router'; import axios from 'axios'; @@ -8,7 +8,6 @@ import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue'; import VnSelect from 'components/common/VnSelect.vue'; import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue'; import VnInput from 'src/components/common/VnInput.vue'; -import getParamWhere from 'src/filters/getParamWhere'; import CatalogFilterValueDialog from 'src/pages/Order/Card/CatalogFilterValueDialog.vue'; import { useArrayData } from 'composables/useArrayData'; @@ -32,11 +31,8 @@ const route = useRoute(); const arrayData = useArrayData(props.dataKey); -const currentParams = ref({}); const categoryList = ref(null); -const selectedCategoryFk = ref(null); const typeList = ref([]); -const selectedTypeFk = ref(null); const searchByTag = ref(null); const vnFilterPanelRef = ref(); @@ -53,50 +49,32 @@ const orderWayList = ref([ const orderBySelected = ref('relevancy DESC, name'); const orderWaySelected = ref('ASC'); -onMounted(() => { - selectedCategoryFk.value = getParamWhere(route, 'categoryFk'); - selectedTypeFk.value = getParamWhere(route, 'typeFk'); -}); - const resetCategory = (params, search) => { - selectedCategoryFk.value = null; typeList.value = null; params.categoryFk = null; params.typeFk = null; arrayData.store.userFilter = null; - removeTagGroupParam(search); -}; - -const selectCategory = (params, category, search) => { - if (params.categoryFk === category?.id) { - resetCategory(params, search); - return; - } - selectedCategoryFk.value = category?.id; - params.categoryFk = category?.id; - params.typeFk = null; - selectedTypeFk.value = null; - loadTypes(category?.id); search(); }; -const loadTypes = async (categoryFk = selectedCategoryFk.value) => { +const selectCategory = async (params, category, search) => { + if (vnFilterPanelRef.value.params.categoryFk === category?.id) { + resetCategory(params, search); + return; + } + params.typeFk = null; + params.categoryFk = category.id; + await loadTypes(category?.id); + await search(); +}; + +const loadTypes = async (id) => { const { data } = await axios.get(`Orders/${route.params.id}/getItemTypeAvailable`, { - params: { itemCategoryId: categoryFk }, + params: { itemCategoryId: id }, }); typeList.value = data; }; -const selectedCategory = computed(() => { - return (categoryList.value || []).find( - (category) => category?.id === selectedCategoryFk.value - ); -}); - -const selectedType = computed(() => { - return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value); -}); - function exprBuilder(param, value) { switch (param) { case 'categoryFk': @@ -122,21 +100,21 @@ const applyTags = (tagInfo, params, search) => { async function onSearchByTag(value) { if (!value.target.value) return; - if (!currentParams.value?.tagGroups) { - currentParams.value.tagGroups = []; + if (!vnFilterPanelRef.value.params?.tagGroups) { + vnFilterPanelRef.value.params.tagGroups = []; } - currentParams.value.tagGroups.push({ + vnFilterPanelRef.value.params.tagGroups.push({ values: [{ value: value.target.value }], }); searchByTag.value = null; } -const removeTagGroupParam = (search, valIndex) => { +const removeTagGroupParam = (params, search, valIndex) => { if (!valIndex && valIndex !== 0) { - currentParams.value.tagGroups = null; + params.tagGroups = null; } else { - currentParams.value.tagGroups.splice(valIndex, 1); + params.tagGroups.splice(valIndex, 1); } }; @@ -148,7 +126,8 @@ const setCategoryList = (data) => { icon: `vn:${(category.icon || '').split('-')[1]}`, })); - selectedCategoryFk.value && loadTypes(); + vnFilterPanelRef.value.params.categoryFk && + loadTypes(vnFilterPanelRef.value.params.categoryFk); }; const getCategoryClass = (category, params) => { @@ -157,12 +136,6 @@ const getCategoryClass = (category, params) => { } }; -const clearFilter = (key) => { - if (key === 'categoryFk') { - resetCategory(); - } -}; - function addOrder(value, field, params) { let { orderBy } = params; orderBy = JSON.parse(orderBy); @@ -182,24 +155,22 @@ onMounted(() => { <VnFilterPanel ref="vnFilterPanelRef" :data-key="props.dataKey" - :hidden-tags="['orderFk', 'orderBy']" - :un-removable-params="['orderFk', 'orderBy']" + :hidden-tags="['filter', 'orderFk', 'orderBy']" + :unremovable-params="['orderFk', 'orderBy']" :expr-builder="exprBuilder" :custom-tags="['tagGroups', 'categoryFk']" :redirect="false" - @remove="clearFilter" - v-model="currentParams" > <template #tags="{ tag, formatFn }"> - <strong v-if="tag.label === 'typeFk'"> - {{ t(selectedType?.name || '') }} + <strong v-if="tag.label === 'typeFk' && typeList"> + {{ t(typeList.find((t) => t.id == tag.value)?.name || '') }} </strong> <div v-else class="q-gutter-x-xs"> <strong>{{ t(`params.${tag.label}`) }}: </strong> <span>{{ formatFn(tag.value) }}</span> </div> </template> - <template #customTags="{ tags: customTags, params, searchFn }"> + <template #customTags="{ params, tags: customTags, searchFn }"> <template v-for="customTag in customTags" :key="customTag.label"> <VnFilterPanelChip v-for="(tag, valIndex) in Array.isArray(customTag.value) @@ -210,11 +181,16 @@ onMounted(() => { @remove=" customTag.label === 'categoryFk' ? resetCategory(params, searchFn) - : removeTagGroupParam(searchFn, valIndex) + : removeTagGroupParam(params, searchFn, valIndex) " > - <strong v-if="customTag.label === 'categoryFk'"> - {{ t(selectedCategory?.name || '') }} + <strong v-if="customTag.label === 'categoryFk' && categoryList"> + {{ + t( + categoryList.find((c) => c.id == customTag.value)?.name || + '' + ) + }} </strong> <strong v-if="tag?.tagSelection?.name" class="q-mr-xs"> {{ tag.tagSelection.name }}: @@ -261,13 +237,8 @@ onMounted(() => { emit-value use-input sort-by="name ASC" - :disable="!selectedCategoryFk" - @update:model-value=" - (value) => { - selectedTypeFk = value; - searchFn(); - } - " + :disable="!params.categoryFk" + @update:model-value="searchFn()" > <template #option="{ itemProps, opt }"> <QItem v-bind="itemProps"> @@ -337,7 +308,7 @@ onMounted(() => { style="display: inline-block" :tags="tags" @apply-tags=" - ($event) => applyTags($event, currentParams, searchFn) + ($event) => applyTags($event, params, searchFn) " /> </QPopupProxy>