fix: call filterpanel from searchbar

This commit is contained in:
Javier Segarra 2025-02-23 13:11:43 +01:00
parent fdf9cfab74
commit 93326db2d9
6 changed files with 138 additions and 55 deletions

View File

@ -2,7 +2,7 @@
import RightAdvancedMenu from './RightAdvancedMenu.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue';
import VnTableFilter from '../VnTable/VnTableFilter.vue';
import { onBeforeMount, onMounted, onUnmounted, computed, ref, provide } from 'vue';
import { onBeforeMount, onMounted, onUnmounted, computed, ref, inject, watch } from 'vue';
import { useArrayData } from 'src/composables/useArrayData';
import { useRoute, useRouter } from 'vue-router';
import { useHasContent } from 'src/composables/useHasContent';
@ -36,6 +36,10 @@ const $props = defineProps({
type: Object,
default: null,
},
filterPanelRef: {
type: Object,
default: null,
},
redirect: {
type: Boolean,
default: true,
@ -52,12 +56,13 @@ const router = useRouter();
let arrayData;
const sectionValue = computed(() => $props.section ?? $props.dataKey);
const isMainSection = ref(false);
const searchbarRef = ref(null);
const searchbarId = 'section-searchbar';
const advancedMenuSlot = 'advanced-menu';
const hasContent = useHasContent(`#${searchbarId}`);
provide('searchbar', () => searchbarRef.value?.search());
// const filterPanel = ref(inject('filterPanel', null));
// filterPanel.value = inject('filterPanel', null);
onBeforeMount(() => {
if ($props.dataKey)
@ -69,14 +74,26 @@ onBeforeMount(() => {
});
checkIsMain();
});
// const filterPanel = ref(inject('filterPanel', null));
onMounted(() => {
const unsubscribe = router.afterEach(() => {
checkIsMain();
});
// filterPanel.value = inject('filterPanel', null);
onUnmounted(unsubscribe);
});
watch(
() => inject('filterPanel'),
(newValue) => {
if (newValue) {
debugger;
// hacer algo cuando el valor esté disponible
}
},
{ immediate: true },
);
onUnmounted(() => {
if (arrayData) arrayData.destroy();
});
@ -90,9 +107,10 @@ function checkIsMain() {
}
</script>
<template>
<pre>{{ filterPanelRef }}</pre>
<slot name="searchbar">
<VnSearchbar
ref="searchbarRef"
:filterPanel="filterPanelRef"
v-if="searchBar && !hasContent"
v-bind="arrayDataProps"
:data-key="dataKey"

View File

@ -1,5 +1,5 @@
<script setup>
import { ref, computed, inject, onMounted } from 'vue';
import { ref, computed, inject, onMounted, provide } from 'vue';
import { useI18n } from 'vue-i18n';
import { useArrayData } from 'composables/useArrayData';
import toDate from 'filters/toDate';
@ -61,12 +61,13 @@ const $props = defineProps({
type: Object,
default: null,
},
searchbarOptions: {
validations: {
type: Array,
default: () => [],
},
excludeParams: {
type: Object,
default: () => ({
use: false,
validateFn: null,
}),
default: null,
},
});
@ -93,7 +94,7 @@ const userParams = ref(useFilterParams($props.dataKey).params);
const userOrders = ref(useFilterParams($props.dataKey).orders);
const searchbar = ref(null);
const isLoading = ref(false);
const excludeParams = ref($props.excludeParams);
onMounted(() => {
searchbar.value = inject('searchbar');
});
@ -102,25 +103,36 @@ defineExpose({ search, params: userParams, remove });
async function search(evt) {
try {
if ($props.searchbarOptions.use) {
if (!searchbar.value) {
return;
}
if (typeof $props.searchbarOptions.validateFn === 'function') {
$props.searchbarOptions.validateFn(userParams.value);
}
// if ($props.searchbarOptions.use) {
// // if (!searchbar.value) {
// // return;
// // }
const validations = $props.validations.every((validation) => {
return validation(userParams.value);
});
// $props.searchbarOptions.validateFn(userParams.value);
if (!Object.keys(userParams.value).length) {
searchbar.value();
return;
}
if (!validations) {
return;
}
if (Object.keys(userParams.value).length) {
excludeParams.value = null;
}
// }
if (evt && $props.disableSubmitEvent) return;
store.filter.where = {};
isLoading.value = true;
const filter = { ...userParams.value, ...$props.modelValue };
store.userParamsChanged = true;
if (excludeParams.value) {
filter.params = {
...filter.params,
exclude: excludeParams.value,
};
}
await arrayData.addFilter({
params: filter,
});
@ -131,6 +143,7 @@ async function search(evt) {
isLoading.value = false;
}
}
provide('filterPanel', search);
async function clearFilters() {
try {

View File

@ -1,5 +1,5 @@
<script setup>
import { onMounted, ref, computed, watch } from 'vue';
import { onMounted, ref, computed, watch, inject, onUpdated } from 'vue';
import { useQuasar } from 'quasar';
import { useArrayData } from 'composables/useArrayData';
import VnInput from 'src/components/common/VnInput.vue';
@ -69,9 +69,13 @@ const props = defineProps({
type: Boolean,
default: true,
},
excludeParams: {
filterPanelOptions: {
type: Boolean,
default: true,
},
filterPanel: {
type: Object,
default: null,
default: true,
},
});
@ -101,6 +105,29 @@ const to = computed(() => {
return url;
});
// watch(
// () => filterPanel.value,
// (newValue) => {
// if (newValue) {
// // hacer algo cuando el valor esté disponible
// filterPanel.value = newValue;
// }
// },
// { immediate: true },
// );
const filterPanelRef = ref(null);
const filterPanel = ref(null);
watch(
() => filterPanelRef.value,
(newValue) => {
if (newValue) {
// hacer algo cuando el valor esté disponible
filterPanelRef.value = newValue;
}
},
{ immediate: true },
);
watch(
() => props.dataKey,
(val) => {
@ -108,6 +135,12 @@ watch(
store = arrayData.store;
},
);
watch(
() => props.filterPanel,
(val) => {
filterPanel.value = val;
},
);
onMounted(() => {
const params = store.userParams;
@ -120,7 +153,10 @@ async function search() {
arrayData.resetPagination();
let filter = { params: { search: searchText.value } };
if (props.filterPanelOptions && filterPanel.value) {
filterPanel.value.filterPanelRef.search(filter);
return;
}
if (!props.searchRemoveParams || !searchText.value) {
filter = {
params: {
@ -139,16 +175,9 @@ async function search() {
};
delete filter.params.search;
}
if (props.excludeParams) {
filter.params = {
...filter.params,
exclude: props.excludeParams,
};
}
await arrayData.applyFilter(filter);
searchText.value = undefined;
}
defineExpose({ search });
</script>
<template>
<Teleport to="#searchbar" v-if="state.isHeaderMounted()">

View File

@ -165,14 +165,19 @@ export function useArrayData(key, userOptions) {
async function addFilter({ filter, params }) {
if (filter) store.filter = filter;
let exclude = {};
if (params?.params?.exclude) {
exclude = params.params.exclude;
// params = { ...params, ...params.exclude };
delete params.params.exclude;
}
let userParams = { ...store.userParams, ...params };
userParams = sanitizerParams(userParams, store?.exprBuilder);
store.userParams = userParams;
resetPagination();
await fetch({});
await fetch({ exclude });
return { filter, params };
}
@ -224,7 +229,11 @@ export function useArrayData(key, userOptions) {
function sanitizerParams(params, exprBuilder) {
for (const param in params) {
if (params[param] === '' || params[param] === null) {
if (
params[param] === '' ||
params[param] === null ||
!Object(params[param]).length
) {
delete store.userParams[param];
delete params[param];
if (store.filter?.where) {

View File

@ -1,6 +1,8 @@
<script setup>
import { ref } from 'vue';
import { ref, computed, provide } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import { toDateString } from 'src/filters';
import FetchData from 'components/FetchData.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
@ -17,14 +19,29 @@ const props = defineProps({
required: true,
},
});
const route = useRoute();
const userParams = {
from: null,
to: null,
};
const filterPanelRef = ref(null);
// Proveer específicamente el filterPanel
provide('filterPanel', filterPanelRef);
defineExpose({ filterPanelRef });
const provinces = ref([]);
const states = ref([]);
const agencies = ref([]);
const warehouses = ref([]);
const groupedStates = ref([]);
const { notify } = useNotify();
const initializeFromQuery = computed(() => {
const query = route.query.table ? JSON.parse(route.query.table) : {};
from.value = query.from || from.toISOString();
to.value = query.to || to.toISOString();
Object.assign(userParams, { from, to });
return userParams;
});
const getGroupedStates = (data) => {
for (const state of data) {
groupedStates.value.push({
@ -46,11 +63,9 @@ function validateDateRange(params) {
if (hasFrom !== hasTo) {
notify(t(`dateRangeMustHaveBothFrom`), 'negative');
throw new Error(t(`dateRangeMustHaveBothFrom`));
}
return hasFrom && hasTo;
return (hasFrom && hasTo) || (!hasFrom && !hasTo);
}
</script>
@ -74,9 +89,11 @@ function validateDateRange(params) {
/>
<FetchData url="Warehouses" @on-fetch="(data) => (warehouses = data)" auto-load />
<VnFilterPanel
ref="filterPanelRef"
:data-key="props.dataKey"
:search-button="true"
:searchbar-options="{ use: true, validateFn: validateDateRange }"
:validations="[validateDateRange]"
:exclude-params="initializeFromQuery"
>
<template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs">

View File

@ -44,22 +44,13 @@ from.setDate(from.getDate() - 7);
const to = Date.vnNew();
to.setHours(23, 59, 0, 0);
to.setDate(to.getDate() + 1);
const userParams = {
from: null,
to: null,
};
onBeforeMount(() => {
initializeFromQuery();
// initializeFromQuery();
stateStore.rightDrawer = true;
if (!route.query.createForm) return;
onClientSelected(JSON.parse(route.query.createForm));
});
const initializeFromQuery = () => {
const query = route.query.table ? JSON.parse(route.query.table) : {};
from.value = query.from || from.toISOString();
to.value = query.to || to.toISOString();
Object.assign(userParams, { from, to });
};
const selectedRows = ref([]);
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
@ -464,6 +455,7 @@ watch(
},
{ immediate: true },
);
const filterPanelRef = ref(null);
</script>
<template>
@ -484,13 +476,18 @@ watch(
:array-data-props="{
url: 'Tickets/filter',
order: ['shippedDate DESC', 'shippedHour ASC', 'zoneLanding ASC', 'id'],
excludeParams: { ...userParams },
filterPanelOptions: true,
filterPanel: filterPanelRef,
searchRemoveParams: true,
exprBuilder,
}"
>
<template #advanced-menu>
<TicketFilter data-key="TicketList" />
<TicketFilter
ref="filterPanelRef"
data-key="TicketList"
:excludeParams="{ ...userParams }"
/>
</template>
<template #body>
<VnTable