Grid mode

This commit is contained in:
William Buezas 2024-09-22 20:12:25 -03:00
parent ff0d2db8fe
commit 72cd9e6cd6
3 changed files with 158 additions and 65 deletions

View File

@ -104,10 +104,7 @@ onMounted(async () => {
</QBtn> </QBtn>
</Teleport> </Teleport>
<QPage class="vn-w-sm"> <QPage class="vn-w-sm">
<QList <QList class="rounded-borders shadow-1 shadow-transition" separator>
class="rounded-borders shadow-1 shadow-transition"
separator
>
<CardList <CardList
v-for="(address, index) in addresses" v-for="(address, index) in addresses"
:key="index" :key="index"

View File

@ -1,40 +1,37 @@
<script setup> <script setup>
import { onMounted } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import VnImg from 'src/components/ui/VnImg.vue'; import VnImg from 'src/components/ui/VnImg.vue';
import CardList from 'src/components/ui/CardList.vue';
import { currency } from 'src/lib/filters.js'; import { currency } from 'src/lib/filters.js';
defineProps({ defineProps({
item: { type: Object, default: () => {} } item: { type: Object, default: () => {} },
viewMode: { type: String, default: 'grid' }
}); });
const { t } = useI18n(); const { t } = useI18n();
onMounted(async () => {});
</script> </script>
<template> <template>
<QCard v-ripple class="catalog-card"> <QCard v-if="viewMode === 'grid'" v-ripple class="catalog-card">
<div style="height: 210px"> <div style="height: 210px">
<VnImg <VnImg
storage="catalog" storage="catalog"
size="200x200" size="200x200"
:id="item.image" :id="item.image"
width="80px"
height="80px"
rounded="bottom" rounded="bottom"
class="full-height full-width" class="full-height full-width"
/> />
</div> </div>
<div class="column" style="height: 205px; padding: 10px"> <div class="column" style="height: 205px; padding: 10px">
<div class="column" style="margin-bottom: auto"> <div class="column" style="margin-bottom: auto">
<div class="text-subtitle2"> <div class="text-subtitle2 ellipsis-2-lines">
{{ item.item }} {{ item.item }}
</div> </div>
<div <div
class="row justify-between sub-name text-uppercase text-subtitle1 text-grey-7" class="row justify-between text-uppercase text-subtitle1 text-grey-7"
> >
<span class="text-subtitle2"> <span class="text-subtitle2">
{{ item.subName }} {{ item.subName }}
@ -42,29 +39,15 @@ onMounted(async () => {});
<span> #{{ item.id }}</span> <span> #{{ item.id }}</span>
</div> </div>
<div class="tags q-pt-xs text-caption"> <div class="tags q-pt-xs text-caption">
<div class="full-width row"> <div
v-for="(tag, index) in item.previewTags"
:key="index"
class="full-width row"
>
<span class="text-grey-7 col"> <span class="text-grey-7 col">
{{ item.tag5 }} {{ tag.name }}
</span> </span>
<span class="col">{{ item.value5 }}</span> <span class="col ellipsis">{{ tag.value }}</span>
</div>
<div class="full-width row">
<span class="text-grey-7 col">
{{ item.tag6 }}
</span>
<span class="col">{{ item.value6 }}</span>
</div>
<div class="full-width row">
<span class="text-grey-7 col">
{{ item.tag7 }}
</span>
<span class="col">{{ item.value7 }}</span>
</div>
<div class="full-width row">
<span class="text-grey-7 col">
{{ item.tag8 }}
</span>
<span class="col">{{ item.value8 }}</span>
</div> </div>
</div> </div>
</div> </div>
@ -103,6 +86,71 @@ onMounted(async () => {});
</div> </div>
</div> </div>
</QCard> </QCard>
<CardList v-else class="vn-w-sm">
<template #prepend>
<div style="min-height: 105px; min-width: 105px" class="q-mr-md">
<VnImg
storage="catalog"
size="200x200"
:id="item.image"
rounded="bottom"
class="full-height full-width"
/>
</div>
</template>
<template #content>
<span class="ellipsis-2-lines">
{{ item.item }}
</span>
<div class="row justify-between text-uppercase text-grey-7">
<span>{{ item.subName }}</span>
<span>#{{ item.id }}</span>
</div>
<div
v-for="(tag, index) in item.previewTags"
:key="index"
class="full-width row"
>
<span class="text-grey-7 col">
{{ tag.name }}
</span>
<span class="col ellipsis">{{ tag.value }}</span>
</div>
<div class="row justify-end items-center q-gutter-x-xs q-mt-sm">
<QBadge
:label="`x${item.grouping}`"
color="grey"
class="col-2 justify-end text-body2"
>
<QTooltip>
{{ t('minGrouping') }}
</QTooltip>
</QBadge>
<QBadge
outline
:label="item.available"
color="accent"
text-color="black"
class="col-3 justify-end text-body2"
>
<QTooltip>
{{ t('available') }}
</QTooltip>
</QBadge>
<QBadge
outline
:label="currency(item.price)"
color="accent"
text-color="black"
class="col-3 justify-end text-body2"
>
<QTooltip>
{{ t('groupingPrice') }}
</QTooltip>
</QBadge>
</div>
</template>
</CardList>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -118,12 +166,17 @@ onMounted(async () => {});
<i18n lang="yaml"> <i18n lang="yaml">
en-US: en-US:
groupingPrice: Price per group groupingPrice: Price per group
minGrouping: Minimum packing
es-ES: es-ES:
groupingPrice: Precio por grupo groupingPrice: Precio por grupo
minGrouping: Cantidad mínima
ca-ES: ca-ES:
groupingPrice: Preu per grup groupingPrice: Preu per grup
minGrouping: Empaquetament mínim
fr-FR: fr-FR:
groupingPrice: Prix par groupe groupingPrice: Prix par groupe
minGrouping: Emballage minimum
pt-PT: pt-PT:
groupingPrice: Preço por grupo groupingPrice: Preço por grupo
minGrouping: Embalagem mínima
</i18n> </i18n>

View File

@ -20,20 +20,28 @@
/> />
</template> </template>
</QInput> --> </QInput> -->
<!-- <QBtn <QBtn
:icon="$t(viewMode == 'list' ? 'view_list' : 'grid_on')" :icon="viewTypeButtonContent.icon"
:label="$t(viewMode == 'list' ? 'listView' : 'gridView')" :label="viewTypeButtonContent.label"
@click="onViewModeClick()" @click="onViewModeClick()"
rounded rounded
no-caps no-caps
/> --> >
<QTooltip>
{{ viewTypeButtonContent.label }}
</QTooltip>
</QBtn>
<QBtn <QBtn
icon="shopping_cart_checkout" icon="shopping_cart_checkout"
:label="t('shoppingCart')" :label="t('shoppingCart')"
:to="{ name: 'basket' }" :to="{ name: 'basket' }"
rounded rounded
no-caps no-caps
/> >
<QTooltip>
{{ t('shoppingCart') }}
</QTooltip>
</QBtn>
</Teleport> </Teleport>
<div style="padding-bottom: 5em"> <div style="padding-bottom: 5em">
<QDrawer v-model="rightDrawerOpen" side="right" :width="250"> <QDrawer v-model="rightDrawerOpen" side="right" :width="250">
@ -214,7 +222,13 @@
</div> --> </div> -->
</QDrawer> </QDrawer>
<QInfiniteScroll> <QInfiniteScroll>
<div class="q-pa-md row justify-center q-gutter-md"> <div
:class="
viewMode === 'grid'
? 'q-pa-md row justify-center q-gutter-md'
: 'column items-center'
"
>
<QSpinner <QSpinner
v-if="loading" v-if="loading"
color="primary" color="primary"
@ -233,6 +247,7 @@
v-for="_item in items" v-for="_item in items"
:key="_item.id" :key="_item.id"
:item="_item" :item="_item"
:view-mode="viewMode"
@click="showItem(_item)" @click="showItem(_item)"
/> />
</div> </div>
@ -354,6 +369,7 @@ const selectedItem = ref(null);
const showItemDialog = ref(false); const showItemDialog = ref(false);
const loading = ref(false); const loading = ref(false);
const isGuest = ref(false); // TODO: Integrate isGuest logic const isGuest = ref(false); // TODO: Integrate isGuest logic
const viewMode = ref('grid');
// Filters options // Filters options
const categories = ref([]); const categories = ref([]);
@ -423,10 +439,10 @@ const selectedCategory = computed({
category.value = value; category.value = value;
router.push({ params: { category: category.value, type: null } }); router.push({ params: { category: category.value, type: null } });
onCategoryChange(); onCategoryChange();
refreshTitle();
if (!value) return; if (!value) return;
getFilters(); getFilters();
getItems(); getItems();
refreshTitle();
} }
}); });
@ -511,7 +527,7 @@ const queryFilter = computed(() => {
// Filtro principal // Filtro principal
if (selectedCategory.value) { if (selectedCategory.value) {
filters.push(`t.categoryFk = ${selectedCategory.value}`); filters.push(`(t.categoryFk = ${selectedCategory.value})`);
} }
const otherFilters = { const otherFilters = {
@ -524,7 +540,7 @@ const queryFilter = computed(() => {
// Añadir solo aquellos filtros que tengan valor // Añadir solo aquellos filtros que tengan valor
Object.entries(otherFilters).forEach(([key, value]) => { Object.entries(otherFilters).forEach(([key, value]) => {
if (value) { if (value) {
filters.push(`${key} = ${value}`); filters.push(`(${key} = ${value})`);
} }
}); });
@ -542,6 +558,13 @@ const isSomeFilterSelected = computed(() => {
); );
}); });
const viewTypeButtonContent = computed(() => {
return {
label: t(viewMode.value === 'list' ? 'listView' : 'gridView'),
icon: viewMode.value === 'list' ? 'view_list' : 'grid_on'
};
});
const getOrder = async () => { const getOrder = async () => {
try { try {
const [data] = await jApi.query( const [data] = await jApi.query(
@ -619,10 +642,26 @@ const getItemColors = async () => {
} }
}; };
const onItemsFetched = async () => {
items.value.forEach(item => {
const previewTags = [
{ name: item.tag5, value: item.value5 },
{ name: item.tag6, value: item.value6 },
{ name: item.tag7, value: item.value7 }
];
item.previewTags = previewTags;
});
};
const getItems = async () => { const getItems = async () => {
try { try {
if (
!selectedCategory.value ||
!basketOrderId.value ||
!isSomeFilterSelected.value
)
return;
loading.value = true; loading.value = true;
if (!selectedCategory.value || !basketOrderId.value) return;
const res = await jApi.execQuery( const res = await jApi.execQuery(
`DROP TEMPORARY TABLE IF EXISTS tmp.item; `DROP TEMPORARY TABLE IF EXISTS tmp.item;
@ -656,11 +695,10 @@ const getItems = async () => {
{ orderId: basketOrderId.value } { orderId: basketOrderId.value }
); );
items.value = res.results[3].data; items.value = res.results[3].data;
console.log('get items: ', items.value); await onItemsFetched();
loading.value = false;
} catch (error) { } catch (error) {
console.error('Error getting items:', error); console.error('Error getting items:', error);
} finally {
loading.value = false;
} }
}; };
@ -709,13 +747,14 @@ const getSubcategories = async () => {
try { try {
const res = await jApi.execQuery( const res = await jApi.execQuery(
`CALL myOrder_getAvailable(#orderId); `CALL myOrder_getAvailable(#orderId);
SELECT DISTINCT i.category, i.category SELECT DISTINCT i.category
FROM vn.item i FROM vn.item i
JOIN vn.itemType t ON t.id = i.typeFk JOIN vn.itemType t ON t.id = i.typeFk
JOIN tmp.itemAvailable a ON a.id = i.id JOIN tmp.itemAvailable a ON a.id = i.id
WHERE #filter WHERE (${queryFilter.value})
ORDER BY category; ORDER BY category;
DROP TEMPORARY TABLE tmp.itemAvailable;` DROP TEMPORARY TABLE tmp.itemAvailable;`,
{ orderId: basketOrderId.value }
); );
itemSubcategories.value = res.results[1].data; itemSubcategories.value = res.results[1].data;
} catch (error) { } catch (error) {
@ -739,12 +778,11 @@ const showItem = async item => {
if (isGuest.value) return; if (isGuest.value) return;
const itemLots = await calcItem(item.id); const itemLots = await calcItem(item.id);
const tags = await getItemTags(item.id); const tags = getItemTags(item.id);
item.tags = tags;
item.lots = itemLots; item.lots = itemLots;
item.tags = tags;
showItemDialog.value = true; showItemDialog.value = true;
selectedItem.value = item; selectedItem.value = item;
console.log('selected item: ', selectedItem.value);
}; };
const removeCategory = () => { const removeCategory = () => {
@ -759,7 +797,6 @@ const onCategoryChange = () => {
selectedOrigin.value = null; selectedOrigin.value = null;
selectedSubcategory.value = null; selectedSubcategory.value = null;
items.value = []; items.value = [];
router.push({ params: { category: null, type: null } });
}; };
const getItemTags = async itemFk => { const getItemTags = async itemFk => {
@ -891,7 +928,6 @@ const refreshTitle = () => {
const _category = categories.value.find( const _category = categories.value.find(
i => i.id === selectedCategory.value i => i.id === selectedCategory.value
); );
if (_category) { if (_category) {
title = _category.name; title = _category.name;
@ -899,7 +935,6 @@ const refreshTitle = () => {
const _type = itemFamilies.value.find( const _type = itemFamilies.value.find(
i => i.id === selectedType.value i => i.id === selectedType.value
); );
if (_type) { if (_type) {
subtitle = title; subtitle = title;
title = _type.name; title = _type.name;
@ -911,6 +946,10 @@ const refreshTitle = () => {
appStore.$patch({ title, subtitle }); appStore.$patch({ title, subtitle });
}; };
const onViewModeClick = () => {
viewMode.value = viewMode.value === 'list' ? 'grid' : 'list';
};
onBeforeMount(async () => { onBeforeMount(async () => {
if (!isGuest.value) { if (!isGuest.value) {
await appStore.check('catalog'); await appStore.check('catalog');
@ -924,8 +963,9 @@ onBeforeMount(async () => {
await getOrder(); await getOrder();
await getCategories(); await getCategories();
if (route.params.category) selectedCategory.value = route.params.category; if (route.params.category)
if (route.params.type) selectedType.value = route.params.type; selectedCategory.value = Number(route.params.category);
if (route.params.type) selectedType.value = Number(route.params.type);
}); });
</script> </script>
@ -977,12 +1017,11 @@ en-US:
higherSize: Higher size higherSize: Higher size
lowerPrice: Lower price lowerPrice: Lower price
higherPrice: Higher price higherPrice: Higher price
minGrouping: Minimum packing
add: Add add: Add
added: Added added: Added
listView: List view
gridView: Grid view
es-ES: es-ES:
gridView: Vista de rejilla
listView: Vista de lista
warehouse: Almacén warehouse: Almacén
agency: Agencia agency: Agencia
modify: Modificar modify: Modificar
@ -1002,9 +1041,10 @@ es-ES:
higherSize: Medida más grande higherSize: Medida más grande
lowerPrice: Precio más bajo lowerPrice: Precio más bajo
higherPrice: Precio más alto higherPrice: Precio más alto
minGrouping: Cantidad mínima
add: Añadir add: Añadir
added: Añadido added: Añadido
listView: Vista de lista
gridView: Vista de rejilla
ca-ES: ca-ES:
category: Categoría category: Categoría
deleteFilter: Eliminar filtro deleteFilter: Eliminar filtro
@ -1020,8 +1060,9 @@ ca-ES:
higherSize: Mida més gran higherSize: Mida més gran
lowerPrice: Preu més baix lowerPrice: Preu més baix
higherPrice: Preu més alt higherPrice: Preu més alt
minGrouping: Empaquetament mínim
add: Afegir add: Afegir
listView: Vista de llista
gridView: Vista de graella
fr-FR: fr-FR:
category: Catégorie category: Catégorie
deleteFilter: Supprimer le filtre deleteFilter: Supprimer le filtre
@ -1037,8 +1078,9 @@ fr-FR:
higherSize: Taille le plus élevé higherSize: Taille le plus élevé
lowerPrice: Prix le plus bas lowerPrice: Prix le plus bas
higherPrice: Prix le plus élevé higherPrice: Prix le plus élevé
minGrouping: Emballage minimum
add: Ajouter add: Ajouter
listView: Vue en liste
gridView: Vue en grille
pt-PT: pt-PT:
category: Categoria category: Categoria
deleteFilter: Apagar filtro deleteFilter: Apagar filtro
@ -1054,6 +1096,7 @@ pt-PT:
higherSize: Tamanho maior higherSize: Tamanho maior
lowerPrice: Preço mais baixo lowerPrice: Preço mais baixo
higherPrice: Preço mais alto higherPrice: Preço mais alto
minGrouping: Embalagem mínima
add: Adicionar add: Adicionar
listView: Vista de lista
gridView: Vista de grade
</i18n> </i18n>