0
0
Fork 0

Add catalog filter

This commit is contained in:
Kevin Martinez 2023-12-20 01:52:28 -04:00
parent ecad464366
commit af5f87a6a1
3 changed files with 229 additions and 14 deletions

View File

@ -31,11 +31,21 @@ const props = defineProps({
description: description:
'Algunos filtros vienen con parametros de búsqueda por default y necesitan tener si o si un valor, por eso de ser necesario, esta prop nos sirve para saber que filtros podemos remover y cuales no', 'Algunos filtros vienen con parametros de búsqueda por default y necesitan tener si o si un valor, por eso de ser necesario, esta prop nos sirve para saber que filtros podemos remover y cuales no',
}, },
exprBuilder: {
type: Function,
default: null,
},
hiddenTags: {
type: Array,
default: () => [],
},
}); });
const emit = defineEmits(['refresh', 'clear', 'search']); const emit = defineEmits(['refresh', 'clear', 'search', 'init']);
const arrayData = useArrayData(props.dataKey); const arrayData = useArrayData(props.dataKey, {
exprBuilder: props.exprBuilder,
});
const store = arrayData.store; const store = arrayData.store;
const userParams = ref({}); const userParams = ref({});
@ -44,9 +54,11 @@ onMounted(() => {
if (Object.keys(store.userParams).length > 0) { if (Object.keys(store.userParams).length > 0) {
userParams.value = JSON.parse(JSON.stringify(store.userParams)); userParams.value = JSON.parse(JSON.stringify(store.userParams));
} }
emit('init', { params: userParams.value });
}); });
const isLoading = ref(false); const isLoading = ref(false);
async function search() { async function search() {
isLoading.value = true; isLoading.value = true;
const params = { ...userParams.value }; const params = { ...userParams.value };
@ -93,17 +105,12 @@ async function clearFilters() {
} }
const tags = computed(() => { const tags = computed(() => {
const params = []; return Object.entries(userParams.value)
.filter(([key, value]) => value && !(props.hiddenTags || []).includes(key))
for (const param in userParams.value) { .map(([key, value]) => ({
if (!userParams.value[param]) continue; label: key,
params.push({ value: value,
label: param, }));
value: userParams.value[param],
});
}
return params;
}); });
async function remove(key) { async function remove(key) {

View File

@ -0,0 +1,205 @@
<script setup>
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelectFilter from 'components/common/VnSelectFilter.vue';
import axios from 'axios';
import { useRoute } from 'vue-router';
const { t } = useI18n();
const route = useRoute();
const props = defineProps({
dataKey: {
type: String,
required: true,
},
});
const categoryList = ref(null);
const selectedCategoryFk = ref(null);
const typeList = ref(null);
const selectedTypeFk = ref(null);
const selectCategory = (params, category) => {
if (params.categoryFk === category?.id) {
selectedCategoryFk.value = null;
params.categoryFk = null;
typeList.value = null;
} else {
selectedCategoryFk.value = category?.id;
params.categoryFk = category?.id;
loadTypes(category?.id);
}
};
const loadTypes = async (categoryFk) => {
const { data } = await axios.get(`Orders/${route.params.id}/getItemTypeAvailable`, {
params: { itemCategoryId: categoryFk },
});
typeList.value = data;
};
const onFilterInit = async ({ params }) => {
if (params.typeFk) {
selectedTypeFk.value = params.typeFk;
}
if (params.categoryFk) {
await loadTypes(params.categoryFk);
selectedCategoryFk.value = params.categoryFk;
}
};
const selectedCategory = computed(() =>
(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':
case 'typeFk':
return { [param]: value };
}
}
</script>
<template>
<FetchData
url="ItemCategories"
limit="30"
auto-load
@on-fetch="
(data) => {
categoryList = (data || [])
.filter((category) => category.display)
.map((category) => ({
...category,
icon: `vn:${(category.icon || '').split('-')[1]}`,
}));
}
"
/>
<VnFilterPanel
:data-key="props.dataKey"
:search-button="true"
:hidden-tags="['orderFk', 'orderBy']"
:expr-builder="exprBuilder"
@init="onFilterInit"
>
<template #tags="{ tag, formatFn }">
<strong v-if="tag.label === 'categoryFk'">
{{ t(selectedCategory?.name || '') }}
</strong>
<strong v-else-if="tag.label === 'typeFk'">
{{ t(selectedType?.name || '') }}
</strong>
<div v-else class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong>
<span>{{ formatFn(tag.value) }}</span>
</div>
</template>
<template #body="{ params }">
<QList dense>
<QItem class="category-filter q-mt-md">
<div
v-for="category in categoryList"
:key="category.name"
:class="[
'category',
category.id === params?.categoryFk && 'active',
]"
>
<QIcon
:name="category.icon"
class="category-icon"
@click="selectCategory(params, category)"
>
<QTooltip>
{{ t(category.name) }}
</QTooltip>
</QIcon>
</div>
</QItem>
<QItem>
<QItemSection>
<VnSelectFilter
:label="t('params.type')"
v-model="params.typeFk"
:options="typeList"
option-value="id"
option-label="name"
emit-value
use-input
:disable="!selectedCategoryFk"
@update:model-value="(value) => (selectedTypeFk = value)"
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel caption>
{{ opt.categoryName }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</QItemSection>
</QItem>
</QList>
</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-label);
font-size: 2.6rem;
padding: 8px;
cursor: pointer;
}
}
</style>
<i18n>
en:
params:
type: Type
orderBy: Order By
es:
params:
type: Tipo
orderBy: Ordenar por
Plant: Planta
Flower: Flor
Handmade: Confección
Green: Verde
Accessories: Complemento
Fruit: Fruta
</i18n>

View File

@ -6,6 +6,7 @@ import { useI18n } from 'vue-i18n';
import VnPaginate from 'components/ui/VnPaginate.vue'; import VnPaginate from 'components/ui/VnPaginate.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue'; import VnSearchbar from 'components/ui/VnSearchbar.vue';
import OrderCatalogItem from 'pages/Order/Card/OrderCatalogItem.vue'; import OrderCatalogItem from 'pages/Order/Card/OrderCatalogItem.vue';
import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
const route = useRoute(); const route = useRoute();
const stateStore = useStateStore(); const stateStore = useStateStore();
@ -54,7 +55,9 @@ function exprBuilder(param, value) {
</div> </div>
</Teleport> </Teleport>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above> <QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
<QScrollArea class="fit text-grey-8"></QScrollArea> <QScrollArea class="fit text-grey-8">
<OrderCatalogFilter data-key="OrderCatalogList" />
</QScrollArea>
</QDrawer> </QDrawer>
<QPage class="column items-center q-pa-md"> <QPage class="column items-center q-pa-md">
<div class="card-list"> <div class="card-list">