From 45b12e019fae18bea58ace758d5efab6bc92300e Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Mon, 20 Jun 2022 14:47:10 +0200 Subject: [PATCH 1/2] fix: m2-668. product pricing --- .../api/productDetail/productDetailsQuery.ts | 44 ------------- .../theme/modules/catalog/pages/product.vue | 21 +++++- .../product-types/bundle/BundleProduct.vue | 44 +++++++------ .../configurable/ConfigurableProduct.vue | 10 +-- .../product-types/grouped/GroupedProduct.vue | 22 ++++--- .../product-types/simple/SimpleProduct.vue | 10 +-- .../queries/getProductPriceBySku.gql.ts | 64 +++++++++++++++++++ 7 files changed, 131 insertions(+), 84 deletions(-) create mode 100644 packages/theme/modules/catalog/product/queries/getProductPriceBySku.gql.ts diff --git a/packages/api-client/src/api/productDetail/productDetailsQuery.ts b/packages/api-client/src/api/productDetail/productDetailsQuery.ts index f4e0b60bb..69d398009 100644 --- a/packages/api-client/src/api/productDetail/productDetailsQuery.ts +++ b/packages/api-client/src/api/productDetail/productDetailsQuery.ts @@ -30,28 +30,6 @@ export default gql` url_rewrites { url } - price_range { - maximum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - minimum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - } categories { uid name @@ -73,28 +51,6 @@ export default gql` } } } - price_range { - maximum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - minimum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - } small_image { url position diff --git a/packages/theme/modules/catalog/pages/product.vue b/packages/theme/modules/catalog/pages/product.vue index 806977d80..48728945d 100644 --- a/packages/theme/modules/catalog/pages/product.vue +++ b/packages/theme/modules/catalog/pages/product.vue @@ -36,6 +36,7 @@ import { useRoute, defineComponent, useFetch, + onMounted, } from '@nuxtjs/composition-api'; import { useCache, CacheTagPrefix } from '@vue-storefront/cache'; import { SfBreadcrumbs, SfLoader } from '@storefront-ui/vue'; @@ -43,9 +44,11 @@ import { getBreadcrumbs } from '~/modules/catalog/product/getters/productGetters import { useProduct } from '~/modules/catalog/product/composables/useProduct'; import { ProductTypeEnum } from '~/modules/catalog/product/enums/ProductTypeEnum'; import LoadWhenVisible from '~/components/utils/LoadWhenVisible.vue'; - +import { useApi } from '~/composables'; import type { Product } from '~/modules/catalog/product/types'; +import type { ProductDetailsQuery } from '~/modules/GraphQL/types'; import ProductSkeleton from '~/modules/catalog/product/components/ProductSkeleton.vue'; +import getProductPriceBySkuGql from '~/modules/catalog/product/queries/getProductPriceBySku.gql'; export default defineComponent({ name: 'ProductPage', @@ -65,6 +68,7 @@ export default defineComponent({ }, transition: 'fade', setup() { + const { query } = useApi(); const product = ref(null); const { addTags } = useCache(); const { localePath } = useContext(); @@ -97,9 +101,9 @@ export default defineComponent({ // eslint-disable-next-line no-underscore-dangle const renderer = computed(() => product.value?.__typename ?? ProductTypeEnum.SIMPLE_PRODUCT); - const fetchProduct = async (query = getBaseSearchQuery()) => { + const fetchProduct = async (searchQuery = getBaseSearchQuery()) => { const result = await getProductDetails({ - ...query, + ...searchQuery, }); product.value = result.items[0] as Product ?? null; @@ -126,6 +130,17 @@ export default defineComponent({ addTags([...tags, ...productTags]); }); + onMounted(async () => { + if (product.value) { + const { data } = await query(getProductPriceBySkuGql, { sku: product.value.sku }); + + product.value = { + ...product.value, + price_range: data.products?.items?.[0].price_range, + }; + } + }); + return { renderer, loading, diff --git a/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProduct.vue b/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProduct.vue index 9da480ab3..2b8063948 100644 --- a/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProduct.vue +++ b/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProduct.vue @@ -37,21 +37,23 @@ />
-
- {{ $t('From') }} - - {{ $t('To') }} - - {{ $t('Your customization') }} - -
+ +
+ {{ $t('From') }} + + {{ $t('To') }} + + {{ $t('Your customization') }} + +
+
- + + +
- + + +
- + + +
- + + +
- + + +
Date: Tue, 21 Jun 2022 14:18:50 +0200 Subject: [PATCH 2/2] fix: m2-668. fixed pricing calculation on pdp --- .../api/productDetail/productDetailsQuery.ts | 104 ++++-------------- .../theme/modules/catalog/pages/product.vue | 12 +- .../pricing/getGroupedProductPriceCommand.ts | 4 +- .../product-types/bundle/BundleProduct.vue | 56 +++++----- .../bundle/BundleProductOptionSkeleton.vue | 35 ++++++ .../configurable/ConfigurableProduct.vue | 11 +- .../product-types/grouped/GroupedProduct.vue | 22 ++-- .../grouped/GroupedProductSelector.vue | 4 +- .../product-types/simple/SimpleProduct.vue | 10 +- .../queries/getProductPriceBySku.gql.ts | 73 +++++++++++- 10 files changed, 179 insertions(+), 152 deletions(-) create mode 100644 packages/theme/modules/catalog/product/components/product-types/bundle/BundleProductOptionSkeleton.vue diff --git a/packages/api-client/src/api/productDetail/productDetailsQuery.ts b/packages/api-client/src/api/productDetail/productDetailsQuery.ts index 69d398009..026b29d53 100644 --- a/packages/api-client/src/api/productDetail/productDetailsQuery.ts +++ b/packages/api-client/src/api/productDetail/productDetailsQuery.ts @@ -90,51 +90,29 @@ export default gql` } options_container special_to_date - ... on BundleProduct { - items { - position - required - sku - title - type - uid - options { - can_change_quantity - is_default - position - uid - quantity - product { - uid - sku - name - price_range { - maximum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - minimum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - } + ... on ConfigurableProduct { + price_range { + maximum_price { + final_price { + currency + value + } + regular_price { + currency + value + } + } + minimum_price { + final_price { + currency + value + } + regular_price { + currency + value } } } - } - ... on ConfigurableProduct { configurable_options { attribute_code attribute_uid @@ -190,47 +168,7 @@ export default gql` } } } - ... on GroupedProduct { - items { - position - qty - product { - uid - sku - name - stock_status - only_x_left_in_stock - price_range { - maximum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - minimum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - } - thumbnail { - url - position - disabled - label - } - } - } - } + ... on DownloadableProduct { downloadable_product_samples { sample_url diff --git a/packages/theme/modules/catalog/pages/product.vue b/packages/theme/modules/catalog/pages/product.vue index 48728945d..0b1a6de34 100644 --- a/packages/theme/modules/catalog/pages/product.vue +++ b/packages/theme/modules/catalog/pages/product.vue @@ -38,6 +38,7 @@ import { useFetch, onMounted, } from '@nuxtjs/composition-api'; +import { merge } from 'lodash-es'; import { useCache, CacheTagPrefix } from '@vue-storefront/cache'; import { SfBreadcrumbs, SfLoader } from '@storefront-ui/vue'; import { getBreadcrumbs } from '~/modules/catalog/product/getters/productGetters'; @@ -106,7 +107,7 @@ export default defineComponent({ ...searchQuery, }); - product.value = result.items[0] as Product ?? null; + product.value = merge({}, product.value, result.items[0] as Product ?? null); }; useFetch(async () => { @@ -131,14 +132,9 @@ export default defineComponent({ }); onMounted(async () => { - if (product.value) { - const { data } = await query(getProductPriceBySkuGql, { sku: product.value.sku }); + const { data } = await query(getProductPriceBySkuGql, { sku: id }); - product.value = { - ...product.value, - price_range: data.products?.items?.[0].price_range, - }; - } + product.value = merge({}, product.value, data.products?.items?.[0] as Product); }); return { diff --git a/packages/theme/modules/catalog/pricing/getGroupedProductPriceCommand.ts b/packages/theme/modules/catalog/pricing/getGroupedProductPriceCommand.ts index 601373a24..fbd69ee17 100644 --- a/packages/theme/modules/catalog/pricing/getGroupedProductPriceCommand.ts +++ b/packages/theme/modules/catalog/pricing/getGroupedProductPriceCommand.ts @@ -8,8 +8,8 @@ export function getGroupedProductPriceCommand(product: GroupedProduct): number { return regular > special && special !== null ? special : regular; }; - return product.items.reduce( + return product.items?.reduce( (acc, curr) => curr.qty * evalProductPrice(curr.product) + acc, 0, - ); + ) ?? 0; } diff --git a/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProduct.vue b/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProduct.vue index 2b8063948..385220dee 100644 --- a/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProduct.vue +++ b/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProduct.vue @@ -37,23 +37,23 @@ />
- -
- {{ $t('From') }} - - {{ $t('To') }} - +
+ {{ $t('From') }} + + {{ $t('To') }} + +
{{ $t('Your customization') }}
- +
- - - + +
+ + + +
props.product?.description?.html || '', ); - const productPrice = ref(getProductPrice(props.product).regular); - const productSpecialPrice = ref(getProductPrice(props.product).special); - const productMaximumPrice = ref(getProductPrice(props.product).maximum); - const customizationPrice = ref(productSpecialPrice.value ?? productPrice.value); - + const productPrices = computed(() => getProductPrice(props.product)); + const customizationPrice = ref(productPrices.value.special ?? productPrices.value.regular); const totalReviews = computed(() => getTotalReviews(props.product)); const averageRating = computed(() => getAverageRating(props.product)); @@ -218,9 +222,7 @@ export default defineComponent({ productGallery, getProductName, getProductSwatchData, - productPrice, - productSpecialPrice, - productMaximumPrice, + productPrices, customizationPrice, productShortDescription, qty, diff --git a/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProductOptionSkeleton.vue b/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProductOptionSkeleton.vue new file mode 100644 index 000000000..ff1d74967 --- /dev/null +++ b/packages/theme/modules/catalog/product/components/product-types/bundle/BundleProductOptionSkeleton.vue @@ -0,0 +1,35 @@ + + diff --git a/packages/theme/modules/catalog/product/components/product-types/configurable/ConfigurableProduct.vue b/packages/theme/modules/catalog/product/components/product-types/configurable/ConfigurableProduct.vue index 4fed3886a..1117710ea 100644 --- a/packages/theme/modules/catalog/product/components/product-types/configurable/ConfigurableProduct.vue +++ b/packages/theme/modules/catalog/product/components/product-types/configurable/ConfigurableProduct.vue @@ -37,12 +37,10 @@ />
- - - +
- - - +
- - - +
props.product, - (product) => { - const price = getGroupedProductPriceCommand(product); + (productNewValue) => { + const price = getGroupedProductPriceCommand(productNewValue); emit('update-price', price); }, { diff --git a/packages/theme/modules/catalog/product/components/product-types/simple/SimpleProduct.vue b/packages/theme/modules/catalog/product/components/product-types/simple/SimpleProduct.vue index 8d6ed225d..776bc2b08 100644 --- a/packages/theme/modules/catalog/product/components/product-types/simple/SimpleProduct.vue +++ b/packages/theme/modules/catalog/product/components/product-types/simple/SimpleProduct.vue @@ -37,12 +37,10 @@ />
- - - +