Skip to content

Commit

Permalink
refactor(Category Card): new action menu with OFF & Share links (#711)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphodn authored Aug 17, 2024
1 parent aaef501 commit 3beedda
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 39 deletions.
54 changes: 54 additions & 0 deletions src/components/CategoryActionMenuButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<template>
<v-btn :style="style" icon size="small" density="comfortable" variant="text">
<v-icon>mdi-dots-vertical</v-icon>
<v-menu activator="parent" scroll-strategy="close" transition="slide-y-transition">
<v-list>
<PriceAddLink v-if="!hidePriceAddLink" class="mr-2" :productCode="category.id" display="list-item" :disabled="!categoryFound" />
<ShareLink :overrideUrl="getShareLinkUrl" display="list-item" :disabled="!categoryFound" />
<v-divider />
<OpenFoodFactsLink facet="category" :value="category.id" display="list-item" :disabled="!categoryFound" />
</v-list>
</v-menu>
</v-btn>
</template>

<script>
import { defineAsyncComponent } from 'vue'
export default {
components: {
PriceAddLink: defineAsyncComponent(() => import('../components/PriceAddLink.vue')),
ShareLink: defineAsyncComponent(() => import('../components/ShareLink.vue')),
OpenFoodFactsLink: defineAsyncComponent(() => import('../components/OpenFoodFactsLink.vue'))
},
props: {
category: {
type: Object,
default: null
},
source: {
type: String,
default: 'category',
examples: ['category', 'product']
},
style: {
type: String,
default: 'position:absolute;bottom:6px;right:0;'
}
},
computed: {
categoryFound() {
return this.category && !this.category.status
},
hidePriceAddLink() {
return this.source === 'category'
},
getShareLinkUrl() {
if (this.source === 'category') {
return `/categories/${this.category.id}`
}
return `/products/${this.category.id}`
}
}
}
</script>
30 changes: 27 additions & 3 deletions src/components/CategoryCard.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
<template>
<v-card v-if="category" :title="category.name" prepend-icon="mdi-fruit-watermelon" data-name="category-card">
<v-card-text>
<PriceCountChip :count="priceCount" />
<CategoryTagChip v-if="category && !category.status && showProductCategoryTag" :category="category" />
<v-chip v-if="sourceCategory" label size="small" density="comfortable" class="mr-1">
<v-icon start icon="mdi-food-outline" />
{{ $t('CategoryDetail.CategoryProductTotal', { count: productCount }) }}
</v-chip>
<PriceCountChip v-else-if="sourceProduct" :count="priceCount" />
<CategoryTagChip v-if="showProductCategoryTag" :category="category" />
<CategoryActionMenuButton :category="category" :source="source" />
</v-card-text>
</v-card>
</template>
Expand All @@ -16,22 +21,41 @@ export default {
components: {
PriceCountChip: defineAsyncComponent(() => import('../components/PriceCountChip.vue')),
CategoryTagChip: defineAsyncComponent(() => import('../components/CategoryTagChip.vue')),
CategoryActionMenuButton: defineAsyncComponent(() => import('../components/CategoryActionMenuButton.vue')),
},
props: {
category: {
type: Object,
default: null,
example: { 'id': 'en:croissants', 'name': 'Croissants' }
},
source: {
type: String,
default: 'category',
examples: ['category', 'product']
},
productCount: {
type: Number,
default: 0
},
priceCount: {
type: Number,
default: 0
}
},
computed: {
...mapStores(useAppStore),
categoryFound() {
return this.category && !this.category.status
},
sourceCategory() {
return this.source === 'category'
},
sourceProduct() {
return this.source === 'product'
},
showProductCategoryTag() {
return this.appStore.user.username && this.appStore.user.product_display_category_tag
return this.appStore.user.username && this.sourceProduct && this.appStore.user.product_display_category_tag
}
}
}
Expand Down
30 changes: 5 additions & 25 deletions src/views/CategoryDetail.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,10 @@
<template>
<v-row>
<v-col cols="12" sm="6">
<v-card
:title="category"
prepend-icon="mdi-list-box-outline"
>
<v-card-text>
<v-chip label size="small" density="comfortable" class="mr-1">
<v-icon start icon="mdi-food-outline" />
{{ $t('CategoryDetail.CategoryProductTotal', { count: categoryProductTotal }) }}
</v-chip>
</v-card-text>
</v-card>
<CategoryCard v-if="category" :category="category" source="category" :productCount="categoryProductTotal" />
</v-col>
</v-row>

<v-row class="mt-0">
<v-col cols="12">
<OpenFoodFactsLink facet="category" :value="category" display="button" />
<ShareLink display="button" />
</v-col>
</v-row>

<br>

<v-row>
<v-col>
<h2 class="text-h6 d-inline mr-2">
Expand Down Expand Up @@ -57,11 +38,10 @@ import api from '../services/api'
export default {
components: {
CategoryCard: defineAsyncComponent(() => import('../components/CategoryCard.vue')),
FilterMenu: defineAsyncComponent(() => import('../components/FilterMenu.vue')),
OrderMenu: defineAsyncComponent(() => import('../components/OrderMenu.vue')),
ProductCard: defineAsyncComponent(() => import('../components/ProductCard.vue')),
OpenFoodFactsLink: defineAsyncComponent(() => import('../components/OpenFoodFactsLink.vue')),
ShareLink: defineAsyncComponent(() => import('../components/ShareLink.vue'))
ProductCard: defineAsyncComponent(() => import('../components/ProductCard.vue'))
},
data() {
return {
Expand All @@ -78,7 +58,7 @@ export default {
},
computed: {
getProductsParams() {
let defaultParams = { categories_tags__contains: this.category, order_by: `${this.currentOrder}`, page: this.categoryProductPage }
let defaultParams = { categories_tags__contains: this.category.id, order_by: `${this.currentOrder}`, page: this.categoryProductPage }
if (this.currentFilter && this.currentFilter === 'hide_price_count_gte_1') {
defaultParams['price_count'] = 0
}
Expand All @@ -99,7 +79,7 @@ export default {
},
methods: {
initCategory() {
this.category = this.$route.params.id
this.category = {'id': this.$route.params.id, 'name': this.$route.params.id}
this.categoryProductList = []
this.categoryProductTotal = null
this.categoryProductPage = 0
Expand Down
18 changes: 7 additions & 11 deletions src/views/ProductDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<v-row>
<v-col cols="12" sm="6">
<ProductCard v-if="!productIsCategory" :product="product" />
<CategoryCard v-else :category="category" :priceCount="productPriceTotal" />
<CategoryCard v-else :category="category" source="product" :priceCount="productPriceTotal" />
</v-col>
</v-row>

Expand All @@ -18,18 +18,12 @@
</p>
<OpenFoodFactsAddMenu :productCode="productId" />
</v-alert>
<v-alert v-else-if="!categoryFound" data-name="category-not-found-alert" type="error" variant="outlined" icon="mdi-alert">
<v-alert v-else-if="categoryNotFound" data-name="category-not-found-alert" type="error" variant="outlined" icon="mdi-alert">
<i>{{ $t('ProductDetail.CategoryNotFound') }}</i>
</v-alert>
</v-col>
</v-row>

<v-row v-if="categoryFound" class="mt-0">
<v-col cols="12">
<PriceAddLink v-if="category" class="mr-2" :productCode="category.name" display="button" />
</v-col>
</v-row>

<v-row>
<v-col>
<h2 class="text-h6 d-inline mr-2">
Expand Down Expand Up @@ -80,7 +74,6 @@ export default {
components: {
ProductCard: defineAsyncComponent(() => import('../components/ProductCard.vue')),
CategoryCard: defineAsyncComponent(() => import('../components/CategoryCard.vue')),
PriceAddLink: defineAsyncComponent(() => import('../components/PriceAddLink.vue')),
FilterMenu: defineAsyncComponent(() => import('../components/FilterMenu.vue')),
OrderMenu: defineAsyncComponent(() => import('../components/OrderMenu.vue')),
DisplayMenu: defineAsyncComponent(() => import('../components/DisplayMenu.vue')),
Expand Down Expand Up @@ -116,10 +109,13 @@ export default {
return !this.productIsCategory && this.product && !this.product.source
},
categoryFound() {
return this.productIsCategory && this.category && (this.category.status !== 'unknown')
return this.category && !this.category.status
},
categoryNotFound() {
return this.productIsCategory && !this.categoryFound
},
productOrCategoryNotFound() {
return !this.loading && (this.productNotFound || !this.categoryFound)
return !this.loading && (this.productNotFound || this.categoryNotFound)
},
getPricesParams() {
let defaultParams = { [this.productIsCategory ? 'category_tag' : 'product_code']: this.productId, order_by: `${this.currentOrder}`, page: this.productPricePage }
Expand Down
4 changes: 4 additions & 0 deletions tests/e2e/spec.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe('Basic tests', () => {
cy.get('#price-count').contains('1')
cy.get('[data-name="product-missing-chip"]').should('have.length', 0)
cy.get('[data-name="product-not-found-alert"]').should('have.length', 0)
cy.get('[data-name="category-not-found-alert"]').should('have.length', 0)
cy.get('[data-name="price-card"]').should('have.length', 1)
cy.contains('Load more').should('not.exist')
})
Expand All @@ -62,6 +63,7 @@ describe('Basic tests', () => {
cy.get('#price-count').contains('0')
cy.get('[data-name="product-missing-chip"]').should('have.length', 1)
cy.get('[data-name="product-not-found-alert"]').should('have.length', 1)
cy.get('[data-name="category-not-found-alert"]').should('have.length', 0)
cy.get('[data-name="price-card"]').should('have.length', 0)
cy.contains('Load more').should('not.exist')
})
Expand All @@ -72,6 +74,7 @@ describe('Basic tests', () => {
cy.get('.v-card-title').contains('Pitted apricot')
cy.get('#price-count').contains('2')
cy.get('[data-name="product-missing-chip"]').should('have.length', 0)
cy.get('[data-name="product-not-found-alert"]').should('have.length', 0)
cy.get('[data-name="category-not-found-alert"]').should('have.length', 0)
cy.get('[data-name="price-card"]').should('have.length', 2)
cy.contains('Load more').should('not.exist')
Expand All @@ -83,6 +86,7 @@ describe('Basic tests', () => {
cy.get('.v-card-title').contains('en:aaaaaaaaaaaa')
cy.get('#price-count').contains('0')
// cy.get('[data-name="product-missing-chip"]').should('have.length', 1)
cy.get('[data-name="product-not-found-alert"]').should('have.length', 0)
cy.get('[data-name="category-not-found-alert"]').should('have.length', 1)
cy.get('[data-name="price-card"]').should('have.length', 0)
cy.contains('Load more').should('not.exist')
Expand Down

0 comments on commit 3beedda

Please sign in to comment.