0
0
Fork 0

feat: fix bugs and filters

This commit is contained in:
Javier Segarra 2024-07-18 15:20:44 +02:00
parent b24c7b0352
commit 7cbdf0d98b
13 changed files with 101 additions and 169 deletions

View File

@ -35,7 +35,9 @@ function stopEventPropagation(event) {
dense dense
square square
> >
<span v-if="!col.chip.icon">{{ row[col.name] }}</span> <span v-if="!col.chip.icon">
{{ col.format ? col.format(row) : row[col.name] }}
</span>
<QIcon v-else :name="col.chip.icon" color="primary-light" /> <QIcon v-else :name="col.chip.icon" color="primary-light" />
</QChip> </QChip>
</span> </span>

View File

@ -147,7 +147,7 @@ const col = computed(() => {
} }
if ( if (
(newColumn.name.startsWith('is') || newColumn.name.startsWith('has')) && (newColumn.name.startsWith('is') || newColumn.name.startsWith('has')) &&
!newColumn.component newColumn.component == null
) )
newColumn.component = 'checkbox'; newColumn.component = 'checkbox';
if ($props.default && !newColumn.component) newColumn.component = $props.default; if ($props.default && !newColumn.component) newColumn.component = $props.default;
@ -158,7 +158,7 @@ const col = computed(() => {
const components = computed(() => $props.components ?? defaultComponents); const components = computed(() => $props.components ?? defaultComponents);
</script> </script>
<template> <template>
<div class="row no-wrap" :style="$props.column.style"> <div class="row no-wrap">
<VnComponent <VnComponent
v-if="col.before" v-if="col.before"
:prop="col.before" :prop="col.before"

View File

@ -64,6 +64,7 @@ const components = {
attrs: { attrs: {
...defaultAttrs, ...defaultAttrs,
clearable: true, clearable: true,
type: 'number',
}, },
forceAttrs, forceAttrs,
}, },

View File

@ -1,7 +1,7 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
import { useArrayData } from 'composables/useArrayData'; import { useArrayData } from 'composables/useArrayData';
const model = defineModel({ type: Object, required: true }); const model = defineModel({ type: Object });
const $props = defineProps({ const $props = defineProps({
name: { name: {
type: String, type: String,
@ -56,7 +56,7 @@ defineExpose({ orderBy });
<span :title="label">{{ label }}</span> <span :title="label">{{ label }}</span>
<QChip <QChip
v-if="name" v-if="name"
:label="!vertical && model?.index" :label="!vertical ? model?.index : ''"
:icon=" :icon="
(model?.index || hover) && !vertical (model?.index || hover) && !vertical
? model?.direction == 'DESC' ? model?.direction == 'DESC'

View File

@ -96,9 +96,9 @@ const route = useRoute();
const router = useRouter(); const router = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
const DEFAULT_MODE = 'card'; const CARD_MODE = 'card';
const TABLE_MODE = 'table'; const TABLE_MODE = 'table';
const mode = ref(DEFAULT_MODE); const mode = ref(CARD_MODE);
const selected = ref([]); const selected = ref([]);
const routeQuery = JSON.parse(route?.query[$props.searchUrl] ?? '{}'); const routeQuery = JSON.parse(route?.query[$props.searchUrl] ?? '{}');
const params = ref({ ...routeQuery, ...routeQuery.filter?.where }); const params = ref({ ...routeQuery, ...routeQuery.filter?.where });
@ -117,13 +117,16 @@ const tableModes = [
{ {
icon: 'grid_view', icon: 'grid_view',
title: t('grid view'), title: t('grid view'),
value: DEFAULT_MODE, value: CARD_MODE,
disable: $props.disableOption?.card, disable: $props.disableOption?.card,
}, },
]; ];
onMounted(() => { onMounted(() => {
mode.value = quasar.platform.is.mobile ? DEFAULT_MODE : $props.defaultMode; mode.value =
quasar.platform.is.mobile && !$props.disableOption?.card
? CARD_MODE
: $props.defaultMode;
stateStore.rightDrawer = true; stateStore.rightDrawer = true;
setUserParams(route.query[$props.searchUrl]); setUserParams(route.query[$props.searchUrl]);
columnsVisibilitySkiped.value = [ columnsVisibilitySkiped.value = [
@ -212,6 +215,7 @@ function stopEventPropagation(event) {
} }
function reload(params) { function reload(params) {
selected.value = [];
CrudModelRef.value.reload(params); CrudModelRef.value.reload(params);
} }
@ -360,7 +364,7 @@ function handleOnDataSaved(_, res) {
/> />
</template> </template>
<template #header-cell="{ col }"> <template #header-cell="{ col }">
<QTh v-if="col.visible ?? true" auto-width> <QTh v-if="col.visible ?? true" :class="[col.columnClass]">
<div <div
class="column self-start q-ml-xs ellipsis" class="column self-start q-ml-xs ellipsis"
:class="`text-${col?.align ?? 'left'}`" :class="`text-${col?.align ?? 'left'}`"
@ -385,6 +389,7 @@ function handleOnDataSaved(_, res) {
:data-key="$attrs['data-key']" :data-key="$attrs['data-key']"
v-model="params[columnName(col)]" v-model="params[columnName(col)]"
:search-url="searchUrl" :search-url="searchUrl"
class="full-width"
/> />
</div> </div>
</QTh> </QTh>
@ -409,7 +414,7 @@ function handleOnDataSaved(_, res) {
<QTd <QTd
auto-width auto-width
class="no-margin q-px-xs" class="no-margin q-px-xs"
:class="[getColAlign(col), col.class, col.columnField?.class]" :class="[getColAlign(col), col.columnClass]"
v-if="col.visible ?? true" v-if="col.visible ?? true"
> >
<slot :name="`column-${col.name}`" :col="col" :row="row"> <slot :name="`column-${col.name}`" :col="col" :row="row">
@ -432,6 +437,7 @@ function handleOnDataSaved(_, res) {
> >
<QBtn <QBtn
v-for="(btn, index) of col.actions" v-for="(btn, index) of col.actions"
v-show="btn.show ? btn.show(row) : true"
:key="index" :key="index"
:title="btn.title" :title="btn.title"
:icon="btn.icon" :icon="btn.icon"

View File

@ -17,15 +17,17 @@ const $props = defineProps({
}, },
}); });
let mixed;
const componentArray = computed(() => { const componentArray = computed(() => {
if (typeof $props.prop === 'object') return [$props.prop]; if (typeof $props.prop === 'object') return [$props.prop];
return $props.prop; return $props.prop;
}); });
function mix(toComponent) { function mix(toComponent) {
if (mixed) return mixed;
const { component, attrs, event } = toComponent; const { component, attrs, event } = toComponent;
const customComponent = $props.components[component]; const customComponent = $props.components[component];
return { mixed = {
component: customComponent?.component ?? component, component: customComponent?.component ?? component,
attrs: { attrs: {
...toValueAttrs(attrs), ...toValueAttrs(attrs),
@ -35,6 +37,7 @@ function mix(toComponent) {
}, },
event: event ?? customComponent?.event, event: event ?? customComponent?.event,
}; };
return mixed;
} }
function toValueAttrs(attrs) { function toValueAttrs(attrs) {

View File

@ -98,6 +98,7 @@ watch(
:class="{ required: $attrs.required }" :class="{ required: $attrs.required }"
:rules="$attrs.required ? [requiredFieldRule] : null" :rules="$attrs.required ? [requiredFieldRule] : null"
:clearable="false" :clearable="false"
@click="isPopupOpen = true"
> >
<template #append> <template #append>
<QIcon <QIcon

View File

@ -1,18 +1,28 @@
<script setup>
defineProps({ wrap: { type: Boolean, default: false } });
</script>
<template> <template>
<div class="vn-row q-gutter-md q-mb-md"> <div class="vn-row q-gutter-md q-mb-md" :class="{ wrap }">
<slot></slot> <slot />
</div> </div>
</template> </template>
<style lang="scss" scopped> <style lang="scss" scoped>
.vn-row { .vn-row {
display: flex; display: flex;
> * { &.wrap {
flex: 1; flex-wrap: wrap;
}
&:not(.wrap) {
> :slotted(*) {
flex: 1;
}
} }
} }
@media screen and (max-width: 800px) { @media screen and (max-width: 800px) {
.vn-row { .vn-row {
flex-direction: column; &:not(.wrap) {
flex-direction: column;
}
} }
} }
</style> </style>

View File

@ -233,27 +233,23 @@ input::-webkit-inner-spin-button {
} }
.q-table { .q-table {
thead, th,
tbody { td {
th { padding: 1px 10px 1px 10px;
.q-select { max-width: 100px;
max-width: 120px; div span {
}
}
td {
padding: 1px 10px 1px 10px;
max-width: 100px;
div span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.expand { overflow: hidden;
max-width: 400px; white-space: nowrap;
} text-overflow: ellipsis;
}
.shrink {
min-width: 65px;
}
.expand {
max-width: 200px;
} }
} }

View File

@ -1271,6 +1271,7 @@ components:
active: Is active active: Is active
visible: Is visible visible: Is visible
floramondo: Is floramondo floramondo: Is floramondo
showBadDates: Show future items
userPanel: userPanel:
copyToken: Token copied to clipboard copyToken: Token copied to clipboard
settings: Settings settings: Settings

View File

@ -1252,6 +1252,7 @@ components:
active: Activo active: Activo
visible: Visible visible: Visible
floramondo: Floramondo floramondo: Floramondo
showBadDates: Ver items a futuro
userPanel: userPanel:
copyToken: Token copiado al portapapeles copyToken: Token copiado al portapapeles
settings: Configuración settings: Configuración

View File

@ -9,13 +9,14 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue'; import VnInputDate from 'src/components/common/VnInputDate.vue';
import EditTableCellValueForm from 'src/components/EditTableCellValueForm.vue'; import EditTableCellValueForm from 'src/components/EditTableCellValueForm.vue';
import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue'; import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
import { useQuasar } from 'quasar';
import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue'; import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
import { tMobile } from 'src/composables/tMobile';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import { dashIfEmpty, toDate } from 'src/filters'; import { toDate } from 'src/filters';
import { useVnConfirm } from 'composables/useVnConfirm'; import { useVnConfirm } from 'composables/useVnConfirm';
import { useState } from 'src/composables/useState'; import { useState } from 'src/composables/useState';
import { toCurrency } from 'filters/index';
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import axios from 'axios'; import axios from 'axios';
import { isLower, isBigger } from 'src/filters/date.js'; import { isLower, isBigger } from 'src/filters/date.js';
@ -23,7 +24,6 @@ import RightMenu from 'src/components/common/RightMenu.vue';
import VnTable from 'src/components/VnTable/VnTable.vue'; import VnTable from 'src/components/VnTable/VnTable.vue';
import { QCheckbox } from 'quasar'; import { QCheckbox } from 'quasar';
const checked = ref(false);
const stateStore = useStateStore(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
const { openConfirmationModal } = useVnConfirm(); const { openConfirmationModal } = useVnConfirm();
@ -54,61 +54,6 @@ const exprBuilder = (param, value) => {
}; };
const params = reactive({}); const params = reactive({});
// const arrayData = useArrayData('ItemFixedPrices', {
// url: 'FixedPrices/filter',
// userParams: params,
// order: ['name ASC', 'itemFk'],
// exprBuilder: exprBuilder,
// });
// const store = arrayData.store;
// const fetchFixedPrices = async () => {
// await arrayData.fetch({ append: false });
// };
// const onFixedPricesFetched = (data) => {
// data.forEach((item) => {
// console.log(item.hasMinPrice);
// item.hasMinPrice = `${item.hasMinPrice !== 0}`;
// });
// fixedPrices.value = data;
// // el objetivo de guardar una copia de las rows es evitar guardar cambios si la data no cambió al disparar los eventos
// fixedPricesOriginalData.value = JSON.parse(JSON.stringify(data));
// };
// watch(
// () => store.data,
// (data) => onFixedPricesFetched(data)
// );
// const applyColumnFilter = async (col) => {
// try {
// const paramKey = col.columnFilter?.filterParamKey || col.field;
// params[paramKey] = col.columnFilter.filterValue;
// await arrayData.addFilter({ params });
// } catch (err) {
// console.error('Error applying column filter', err);
// }
// };
// const getColumnInputEvents = (col) => {
// return col.columnFilter.type === 'select'
// ? { 'update:modelValue': () => applyColumnFilter(col) }
// : {
// 'keyup.enter': () => applyColumnFilter(col),
// };
// };
// const defaultColumnFilter = {
// component: VnInput,
// type: 'text',
// filterValue: null,
// event: getColumnInputEvents,
// attrs: {
// dense: true,
// },
// };
const defaultColumnAttrs = { const defaultColumnAttrs = {
align: 'left', align: 'left',
sortable: true, sortable: true,
@ -123,6 +68,7 @@ const columns = computed(() => [
...defaultColumnAttrs, ...defaultColumnAttrs,
isId: true, isId: true,
cardVisible: true, cardVisible: true,
columnClass: 'shrink',
columnField: { columnField: {
component: 'input', component: 'input',
type: 'number', type: 'number',
@ -131,6 +77,7 @@ const columns = computed(() => [
{ {
label: t('globals.name'), label: t('globals.name'),
field: 'name', field: 'name',
columnClass: 'shrink',
name: 'description', name: 'description',
...defaultColumnAttrs, ...defaultColumnAttrs,
create: true, create: true,
@ -142,9 +89,6 @@ const columns = computed(() => [
name: 'rate2', name: 'rate2',
...defaultColumnAttrs, ...defaultColumnAttrs,
cardVisible: true, cardVisible: true,
class: 'expand',
style: 'max-width: 80px',
}, },
{ {
label: t('item.fixedPrice.packingPrice'), label: t('item.fixedPrice.packingPrice'),
@ -152,12 +96,11 @@ const columns = computed(() => [
name: 'rate3', name: 'rate3',
...defaultColumnAttrs, ...defaultColumnAttrs,
cardVisible: true, cardVisible: true,
class: 'expand',
style: 'max-width: 80px',
}, },
{ {
label: t('item.fixedPrice.minPrice'), label: t('item.fixedPrice.minPrice'),
class: 'expand',
field: 'minPrice', field: 'minPrice',
name: 'minPrice', name: 'minPrice',
...defaultColumnAttrs, ...defaultColumnAttrs,
@ -172,16 +115,17 @@ const columns = computed(() => [
label: t('item.fixedPrice.started'), label: t('item.fixedPrice.started'),
field: 'started', field: 'started',
name: 'started', name: 'started',
...defaultColumnAttrs, format: ({ started }) => toDate(started),
cardVisible: true, cardVisible: true,
...defaultColumnAttrs,
component: 'date', component: 'date',
format: (row) => toDate(row.started),
}, },
{ {
label: t('item.fixedPrice.ended'), label: t('item.fixedPrice.ended'),
field: 'ended', field: 'ended',
name: 'ended', name: 'ended',
...defaultColumnAttrs, ...defaultColumnAttrs,
columnClass: 'expand',
cardVisible: true, cardVisible: true,
component: 'date', component: 'date',
format: (row) => toDate(row.ended), format: (row) => toDate(row.ended),
@ -270,29 +214,7 @@ async function saveOnRowChange(row) {
else if (rowsSelected.value.length === 1) else if (rowsSelected.value.length === 1)
await upsertFixedPrice(rowsSelected.value[0]); await upsertFixedPrice(rowsSelected.value[0]);
rowsSelected.value = [row]; rowsSelected.value = [row];
// if (rowsSelected.value.length > 0) {
// disableUnselectedRows();
// } else {
// resetRowStates();
// }
// if (lastRow.value && lastRow.value !== row.id) {
// console.log('update');
// // await upsertPrice(row);
// }
// lastRow.value = row.id;
} }
// function disableUnselectedRows() {
// fixedPrices.value.forEach((row) => {
// row.disabled = !rowsSelected.value.includes(row.id);
// });
// }
// function resetRowStates() {
// fixedPrices.value.forEach((row) => {
// row.disable = false;
// });
// // Aquí puedes guardar los cambios si es necesario
// console.log('Guardando cambios...');
// }
const tableRef = ref(); const tableRef = ref();
function checkLastVisibleRow() { function checkLastVisibleRow() {
const rows = document const rows = document
@ -367,25 +289,6 @@ const openEditTableCellDialog = () => {
const onEditCellDataSaved = async () => { const onEditCellDataSaved = async () => {
rowsSelected.value = []; rowsSelected.value = [];
}; };
/*const lastRow = ref(null);
async function saveOnRowChange(row) {
if (lastRow.value && lastRow.value !== row.id) {
console.log('update');
await upsertPrice(row);
return;
}
lastRow.value = row.id;
}*/
// const onWarehousesFetched = (data) => {
// warehousesOptions.value = data;
// // Actualiza las 'options' del elemento con field 'warehouseFk' en 'editTableFieldsOptions'.
// const warehouseField = editTableFieldsOptions.find(
// (field) => field.field === 'warehouseFk'
// );
// warehouseField.attrs.options = data;
// };
import { useQuasar } from 'quasar';
const removeFuturePrice = async () => { const removeFuturePrice = async () => {
try { try {
rowsSelected.value.forEach(({ id }) => { rowsSelected.value.forEach(({ id }) => {
@ -405,11 +308,21 @@ function confirmRemove(item) {
component: VnConfirm, component: VnConfirm,
componentProps: { componentProps: {
title: t('This row will be removed'), title: t('This row will be removed'),
message: t('Do you want to clone this item?'), message: t('Do you want to remove?'),
promise: async () => removePrice(item.id), promise: async () => removePrice(item.id),
}, },
}); });
} }
function confirmRemoveFuturePrice(item) {
quasar.dialog({
component: VnConfirm,
componentProps: {
title: t('This row will be removed'),
message: t('Do you want to remove?'),
promise: async () => removeFuturePrice(item.id),
},
});
}
const removePrice = async (id) => { const removePrice = async (id) => {
try { try {
@ -433,7 +346,6 @@ function handleOnDataSave(CrudModelRef) {
nextTick(() => { nextTick(() => {
highlightNewRow(checkLastVisibleRow()); highlightNewRow(checkLastVisibleRow());
}); });
// CrudModelRef.value.insert(lastItem);
} }
onUnmounted(() => (stateStore.rightDrawer = false)); onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
@ -465,12 +377,20 @@ onUnmounted(() => (stateStore.rightDrawer = false));
{{ t('Edit fixed price(s)') }} {{ t('Edit fixed price(s)') }}
</QTooltip> </QTooltip>
</QBtn> </QBtn>
<QBtn
:label="tMobile('globals.remove')"
color="primary"
icon="delete"
flat
@click="confirmRemoveFuturePrice"
:title="t('globals.remove')"
v-if="rowsSelected.length"
/>
</template> </template>
</VnSubToolbar> </VnSubToolbar>
<QPage> <QPage>
{{ lastRow }}
{{ rowsSelected }}
<VnTable <VnTable
:default-remove="false"
data-key="ItemFixedPrices" data-key="ItemFixedPrices"
url="FixedPrices/filter" url="FixedPrices/filter"
:filter="{ where: exprBuilder }" :filter="{ where: exprBuilder }"
@ -500,14 +420,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</template> </template>
<template #body-selection="scope"> <template #body-selection="scope">
{{ scope }} {{ scope }}
<QCheckbox <QCheckbox flat v-model="scope.selected" />
flat
style="width: 10px; margin-left: -20px"
v-model="scope.selected"
/>
<!--:disable="
rowsSelected.length > 0 && rowsSelected[0].id !== scope.row.id
"-->
</template> </template>
<template #column-itemId="props"> <template #column-itemId="props">
@ -538,13 +451,16 @@ onUnmounted(() => (stateStore.rightDrawer = false));
{{ row.name }} {{ row.name }}
</span> </span>
<ItemDescriptorProxy :id="row.itemFk" /> <ItemDescriptorProxy :id="row.itemFk" />
<FetchedTags style="max-width: 220px" :item="row" :max-length="6" /> <FetchedTags
style="width: max-content; max-width: 220px"
:item="row"
:max-length="6"
/>
</QTd> </QTd>
</template> </template>
<template #column-rate2="props"> <template #column-rate2="props">
<QTd class="col"> <QTd class="col">
<VnInput <VnInput
style="max-width: 80px"
mask="###.##" mask="###.##"
v-model.number="props.row.rate2" v-model.number="props.row.rate2"
v-on="getRowUpdateInputEvents(props)" v-on="getRowUpdateInputEvents(props)"
@ -556,7 +472,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<template #column-rate3="props"> <template #column-rate3="props">
<QTd class="col"> <QTd class="col">
<VnInput <VnInput
style="width: 80px"
mask="###.##" mask="###.##"
v-model.number="props.row.rate3" v-model.number="props.row.rate3"
v-on="getRowUpdateInputEvents(props)" v-on="getRowUpdateInputEvents(props)"
@ -577,12 +492,11 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<VnInput <VnInput
class="col" class="col"
mask="###.##" mask="###.##"
style="width: 80px"
:disable="props.row.hasMinPrice === 1" :disable="props.row.hasMinPrice === 1"
v-model.number="props.row.minPrice" v-model.number="props.row.minPrice"
v-on="getRowUpdateInputEvents(props)" v-on="getRowUpdateInputEvents(props)"
> >
<template #append>{{ props.row.hasMinPrice }}</template> <template #append></template>
</VnInput> </VnInput>
</div> </div>
</QTd> </QTd>
@ -590,6 +504,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<template #column-started="props"> <template #column-started="props">
<QTd class="col"> <QTd class="col">
<VnInputDate <VnInputDate
style="min-width: 147px"
:show-event="true" :show-event="true"
v-model="props.row.started" v-model="props.row.started"
v-on="getRowUpdateInputEvents(props, false, 'date')" v-on="getRowUpdateInputEvents(props, false, 'date')"
@ -607,6 +522,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<template #column-ended="props"> <template #column-ended="props">
<QTd class="col"> <QTd class="col">
<VnInputDate <VnInputDate
style="min-width: 147px"
:show-event="true" :show-event="true"
v-model="props.row.ended" v-model="props.row.ended"
v-on="getRowUpdateInputEvents(props, false, 'date')" v-on="getRowUpdateInputEvents(props, false, 'date')"
@ -691,7 +607,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
.q-field__append { .q-field__append {
padding: 0; padding: 0;
} }
/* height or max-height is important */
tbody tr.highlight .q-td { tbody tr.highlight .q-td {
animation: highlight-animation 4s ease-in-out; animation: highlight-animation 4s ease-in-out;

View File

@ -24,8 +24,7 @@ const route = useRoute();
const itemTypeWorkersOptions = ref([]); const itemTypeWorkersOptions = ref([]);
const sanitizeParam = (param) => { const sanitizeParam = (param) => {
if (!route?.query?.params) return 'false'; const params = JSON.parse(route?.query?.table);
const params = JSON.parse(route?.query?.params);
return params[param] ?? 'false'; return params[param] ?? 'false';
}; };
const $params = ref({}); const $params = ref({});
@ -110,19 +109,16 @@ const pushParam = (param) => ({
:false-value="'false'" :false-value="'false'"
@update:model-value="searchFn(pushParam('mine'))" @update:model-value="searchFn(pushParam('mine'))"
/> />
</QItemSection>
<QItemSection>
<QCheckbox <QCheckbox
size="sm" v-model="$params.showBadDates"
v-model="checked" :label="t(`components.itemsFilterPanel.showBadDates`)"
:label="t(`Show future items`)"
:true-value="'true'" :true-value="'true'"
:false-value="'false'" :false-value="'false'"
@update:model-value="searchFn(pushParam('showBadDates'))" @update:model-value="searchFn(pushParam('showBadDates'))"
> >
</QCheckbox> </QCheckbox>
</QItemSection>
<QItemSection>
<QCheckbox <QCheckbox
:label="t('components.itemsFilterPanel.hasMinPrice')" :label="t('components.itemsFilterPanel.hasMinPrice')"
v-model="$params.hasMinPrice" v-model="$params.hasMinPrice"