Catalog view #87

Merged
jsegarra merged 14 commits from wbuezas/hedera-web-mindshore:feature/Catalog into 4922-vueMigration 2024-10-01 19:27:15 +00:00
3 changed files with 158 additions and 65 deletions
Showing only changes of commit 72cd9e6cd6 - Show all commits

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">

Echo en falta el carro en rojo que representa la cantidad mínima
x1, representa el empaquetado mínimo. Esta traducción no está presente en el componente vue

Echo en falta el carro en rojo que representa la cantidad mínima x1, representa el empaquetado mínimo. Esta traducción no está presente en el componente vue

minQuantity handleado.

Commit: 0f5014088d

minQuantity handleado. Commit: https://gitea.verdnatura.es/verdnatura/hedera-web/commit/0f5014088d670c3e5cdbf63913672f14c6c3a4bf
<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>