This commit is contained in:
William Buezas 2024-02-27 07:32:51 -03:00
parent 9f35d20f2f
commit 50218d6ddf
2 changed files with 488 additions and 1 deletions

View File

@ -1,5 +1,5 @@
<script setup>
import { onMounted, ref, computed, reactive } from 'vue';
import { onMounted, ref, computed, reactive, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
@ -10,6 +10,7 @@ import TableVisibleColumns from 'src/components/common/TableVisibleColumns.vue';
import EditTableCellValueForm from 'src/components/EditTableCellValueForm.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
import EntryLatestBuysFilter from './EntryLatestBuysFilter.vue';
import { useStateStore } from 'stores/useStateStore';
import { toDate, toCurrency } from 'src/filters';
@ -604,6 +605,8 @@ onMounted(async () => {
allColumnNames.value = filteredColumns.map((col) => col.name);
await arrayData.fetch({ append: false });
});
onUnmounted(() => (stateStore.rightDrawer = false));
</script>
<template>
@ -649,6 +652,11 @@ onMounted(async () => {
<QSpace />
<div id="st-actions"></div>
</QToolbar>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
<QScrollArea class="fit text-grey-8">
<EntryLatestBuysFilter data-key="OrderCatalogList" :tags="tags" />
</QScrollArea>
</QDrawer>
<QPage class="column items-center q-pa-md">
<QTable
:rows="rows"

View File

@ -0,0 +1,479 @@
<script setup>
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
// import VnInput from 'components/common/VnInput.vue';
import FetchData from 'components/FetchData.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelectFilter from 'components/common/VnSelectFilter.vue';
// import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
import axios from 'axios';
const { t } = useI18n();
const route = useRoute();
const props = defineProps({
dataKey: {
type: String,
required: true,
},
tags: {
type: Array,
required: true,
},
});
const itemCategories = ref(null);
const selectedCategoryFk = ref(null);
const selectedTypeFk = ref(null);
const itemTypesOptions = ref([]);
const itemTypeWorkersOptions = ref([]);
const suppliersOptions = ref([]);
const categoryList = computed(() => {
return (itemCategories.value || [])
.filter((category) => category.display)
.map((category) => ({
...category,
icon: `vn:${(category.icon || '').split('-')[1]}`,
}));
});
const selectCategory = async (params, categoryId, search) => {
if (params.categoryFk === categoryId) {
resetCategory();
params.categoryFk = null;
return;
}
selectedCategoryFk.value = categoryId;
params.categoryFk = categoryId;
console.log('params:: ', params);
await fetchItemTypes(categoryId);
search();
};
const resetCategory = () => {
selectedCategoryFk.value = null;
itemTypesOptions.value = null;
};
const fetchItemTypes = async (id) => {
try {
const filter = {
fields: ['id', 'name', 'categoryFk'],
where: { categoryFk: id },
include: 'category',
order: 'name ASC',
};
const { data } = await axios.get('ItemTypes', {
params: { filter: JSON.stringify(filter) },
});
itemTypesOptions.value = data;
} catch (err) {
console.error('Error fetching item types', err);
}
};
// const selectedOrder = ref(null);
// const orderList = [
// { way: 'ASC', name: 'Ascendant' },
// { way: 'DESC', name: 'Descendant' },
// ];
// const selectedOrderField = ref(null);
// const OrderFields = [
// { field: 'relevancy DESC, name', name: 'Relevancy', priority: 999 },
// { field: 'showOrder, price', name: 'Color and price', priority: 999 },
// { field: 'name', name: 'Name', priority: 999 },
// { field: 'price', name: 'Price', priority: 999 },
// ];
// const clearFilter = (key) => {
// if (key === 'categoryFk') {
// resetCategory();
// }
// };
// const onFilterInit = async ({ params }) => {
// if (params.typeFk) {
// selectedTypeFk.value = params.typeFk;
// }
// if (params.categoryFk) {
// await loadTypes(params.categoryFk);
// selectedCategoryFk.value = params.categoryFk;
// }
// if (params.orderBy) {
// orderByParam.value = JSON.parse(params.orderBy);
// selectedOrder.value = orderByParam.value?.way;
// selectedOrderField.value = orderByParam.value?.field;
// }
// };
// const selectedCategory = computed(() =>
// (itemCategories.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':
// case 'typeFk':
// return { [param]: value };
// case 'search':
// return { 'i.name': { like: `%${value}%` } };
// }
// }
// const selectedTag = ref(null);
// const tagValues = ref([{}]);
// const tagOptions = ref(null);
// const isButtonDisabled = computed(
// () => !selectedTag.value || tagValues.value.some((item) => !item.value)
// );
// const applyTagFilter = (params, search) => {
// if (!tagValues.value?.length) {
// params.tagGroups = null;
// search();
// return;
// }
// if (!params.tagGroups) {
// params.tagGroups = [];
// }
// params.tagGroups.push(
// JSON.stringify({
// values: tagValues.value,
// tagSelection: {
// ...selectedTag.value,
// orgShowField: selectedTag.value.name,
// },
// tagFk: selectedTag.value.tagFk,
// })
// );
// search();
// selectedTag.value = null;
// tagValues.value = [{}];
// };
// const removeTagChip = (selection, params, search) => {
// if (params.tagGroups) {
// params.tagGroups = (params.tagGroups || []).filter(
// (value) => value !== selection
// );
// }
// search();
// };
// const orderByParam = ref(null);
// const onOrderFieldChange = (value, params, search) => {
// const orderBy = Object.assign({}, orderByParam.value, { field: value.field });
// params.orderBy = JSON.stringify(orderBy);
// search();
// };
// const onOrderChange = (value, params, search) => {
// const orderBy = Object.assign({}, orderByParam.value, { way: value.way });
// params.orderBy = JSON.stringify(orderBy);
// search();
// };
const getCategoryClass = (category, params) => {
if (category.id === params?.categoryFk) {
return 'active';
}
};
</script>
<template>
<FetchData
url="ItemCategories"
limit="30"
auto-load
@on-fetch="(data) => (itemCategories = data)"
/>
<FetchData
url="TicketRequests/getItemTypeWorker"
limit="30"
auto-load
:filter="{ fields: ['id', 'nickname'], order: 'nickname ASC', limit: 30 }"
@on-fetch="(data) => (itemTypeWorkersOptions = data)"
/>
<FetchData
url="Suppliers"
limit="30"
auto-load
:filter="{ fields: ['id', 'name', 'nickname'], order: 'name ASC', limit: 30 }"
@on-fetch="(data) => (suppliersOptions = data)"
/>
<VnFilterPanel
:data-key="props.dataKey"
:expr-builder="exprBuilder"
@init="onFilterInit"
@remove="clearFilter"
>
<template #tags="{ tag, formatFn }">
<div 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 v-for="tag in customTags" :key="tag.label">
<template v-if="tag.label === 'tagGroups'">
<VnFilterPanelChip
v-for="chip in tag.value"
:key="chip"
removable
@remove="removeTagChip(chip, params, searchFn)"
>
<strong> {{ JSON.parse(chip).tagSelection?.name }}: </strong>
<span>{{
(JSON.parse(chip).values || [])
.map((item) => item.value)
.join(' | ')
}}</span>
</VnFilterPanelChip>
</template>
</template>
</template> -->
<template #body="{ params, searchFn }">
<QItem class="category-filter q-mt-md">
<div
v-for="category in categoryList"
:key="category.name"
:class="['category', getCategoryClass(category, params)]"
>
<QIcon
:name="category.icon"
class="category-icon"
@click="selectCategory(params, category.id, searchFn)"
>
<QTooltip>
{{ t(category.name) }}
</QTooltip>
</QIcon>
</div>
</QItem>
<QItem class="q-my-md">
<QItemSection>
<VnSelectFilter
:label="t('params.typeFk')"
v-model="params.typeFk"
:options="itemTypesOptions"
option-value="id"
option-label="name"
dense
outlined
rounded
use-input
:disable="!selectedCategoryFk"
@update:model-value="
(value) => {
selectedTypeFk = value;
searchFn();
}
"
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel caption>
{{ opt.categoryName }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</QItemSection>
</QItem>
<QSeparator />
<QItem class="q-my-md">
<QItemSection>
<VnSelectFilter
:label="t('params.buyer')"
v-model="params.salesPersonFk"
:options="itemTypeWorkersOptions"
option-value="id"
option-label="nickname"
dense
outlined
rounded
use-input
@update:model-value="searchFn()"
/>
</QItemSection>
</QItem>
<QItem class="q-my-md">
<QItemSection>
<VnSelectFilter
:label="t('params.supplier')"
v-model="params.supplierFk"
:options="suppliersOptions"
option-value="id"
option-label="name"
dense
outlined
rounded
use-input
@update:model-value="searchFn()"
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel caption>
{{ opt.nickname }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</QItemSection>
</QItem>
<QItem class="q-my-md">
<QItemSection>
<VnInputDate
:label="t('params.from')"
v-model="params.from"
is-outlined
/>
</QItemSection>
</QItem>
<QItem class="q-my-md">
<QItemSection>
<VnInputDate
:label="t('params.to')"
v-model="params.to"
is-outlined
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QCheckbox
:label="t('params.active')"
v-model="params.active"
toggle-indeterminate
/>
</QItemSection>
<QItemSection>
<QCheckbox
:label="t('params.visible')"
v-model="params.visible"
toggle-indeterminate
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QCheckbox
:label="t('params.floramondo')"
v-model="params.floramondo"
toggle-indeterminate
/>
</QItemSection>
</QItem>
</template>
</VnFilterPanel>
</template>
<style lang="scss" scoped>
.category-filter {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 12px;
.category {
flex: 1;
flex-shrink: 0;
display: flex;
justify-content: center;
&.active {
.category-icon {
background-color: $primary;
}
}
}
.category-icon {
border-radius: 50%;
background-color: var(--vn-light-gray);
font-size: 2.6rem;
padding: 8px;
cursor: pointer;
}
}
.filter-icon {
font-size: 24px;
color: $primary;
padding: 0 4px;
cursor: pointer;
}
.filter-input {
flex-shrink: 1;
min-width: 0;
}
.filter-value {
display: flex;
align-items: center;
}
</style>
<i18n>
en:
params:
orderBy: Order By
tag: Tag
value: Value
order: Order
supplier: Supplier
from: From
to: To
active: Is active
visible: Is visible
floramondo: Is floramondo
salesPersonFk: Buyer
categoryFk: Category
typeFk: Type
es:
params:
orderBy: Ordenar por
tag: Etiqueta
value: Valor
order: Orden
supplier: Proveedor
from: Desde
to: Hasta
active: Activo
visible: Visible
floramondo: Floramondo
salesPersonFk: Comprador
categoryFk: Categoría
typeFk: Tipo
Plant: Planta
Flower: Flor
Handmade: Confección
Green: Verde
Accessories: Complemento
Fruit: Fruta
</i18n>