Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 21 additions & 127 deletions packages/api-client/src/api/productDetail/productDetailsQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -134,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
Expand Down Expand Up @@ -234,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
Expand Down
19 changes: 15 additions & 4 deletions packages/theme/modules/catalog/pages/product.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,20 @@ import {
useRoute,
defineComponent,
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';
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',
Expand All @@ -65,6 +69,7 @@ export default defineComponent({
},
transition: 'fade',
setup() {
const { query } = useApi();
const product = ref<Product | null>(null);
const { addTags } = useCache();
const { localePath } = useContext();
Expand Down Expand Up @@ -97,12 +102,12 @@ 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;
product.value = merge({}, product.value, result.items[0] as Product ?? null);
};

useFetch(async () => {
Expand All @@ -126,6 +131,12 @@ export default defineComponent({
addTags([...tags, ...productTags]);
});

onMounted(async () => {
const { data } = await query<ProductDetailsQuery>(getProductPriceBySkuGql, { sku: id });

product.value = merge({}, product.value, data.products?.items?.[0] as Product);
});

return {
renderer,
loading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,19 @@
<div class="product__price">
<span class="product__price-label">{{ $t('From') }}</span>
<SfPrice
:regular="$fc(productPrice)"
:special="productSpecialPrice && $fc(productSpecialPrice)"
:regular="$fc(productPrices.regular)"
:special="productPrices.special && $fc(productPrices.special)"
/>
<span class="product__price-label">{{ $t('To') }}</span>
<SfPrice
:regular="$fc(productMaximumPrice)"
/>
<span class="product__price-label">{{ $t('Your customization') }}</span>
<SfPrice
:regular="$fc(customizationPrice)"
:regular="$fc(productPrices.maximum)"
/>
<div v-if="customizationPrice">
<span class="product__price-label">{{ $t('Your customization') }}</span>
<SfPrice
:regular="$fc(customizationPrice)"
/>
</div>
</div>
<div>
<div class="product__rating">
Expand Down Expand Up @@ -89,10 +91,16 @@
class="product__description desktop-only"
/>
<BundleProductSelector
v-if="productPrices.regular"
:can-add-to-cart="canAddToCart(product, qty)"
:product="product"
@update-price="customizationPrice = $event"
/>
<div v-else>
<BundleProductOptionSkeleton />
<BundleProductOptionSkeleton />
<BundleProductOptionSkeleton />
</div>
<div class="product__additional-actions">
<AddToWishlist
:is-in-wishlist="isInWishlist"
Expand Down Expand Up @@ -151,10 +159,13 @@ import ProductTabs from '~/modules/catalog/product/components/tabs/ProductTabs.v
import { useProductGallery } from '~/modules/catalog/product/composables/useProductGallery';
import { Product } from '~/modules/catalog/product/types';
import { TabsConfig, useProductTabs } from '~/modules/catalog/product/composables/useProductTabs';
import BundleProductOptionSkeleton
from '~/modules/catalog/product/components/product-types/bundle/BundleProductOptionSkeleton.vue';

export default defineComponent({
name: 'BundleProduct',
components: {
BundleProductOptionSkeleton,
BundleProductSelector,
HTMLContent,
LazyHydrate,
Expand Down Expand Up @@ -195,11 +206,8 @@ export default defineComponent({
() => 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));

Expand All @@ -214,9 +222,7 @@ export default defineComponent({
productGallery,
getProductName,
getProductSwatchData,
productPrice,
productSpecialPrice,
productMaximumPrice,
productPrices,
customizationPrice,
productShortDescription,
qty,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<template>
<div>
<SkeletonLoader
width="100%"
height="23px"
/>
<SkeletonLoader
width="100%"
height="240px"
/>
<div>
<SkeletonLoader
width="80px"
height="23px"
/>
</div>
<SkeletonLoader
width="108px"
height="52px"
/>
</div>
</template>
<script lang="ts">
import {
defineComponent,
} from '@nuxtjs/composition-api';
import SkeletonLoader from '~/components/SkeletonLoader/index.vue';

export default defineComponent({
name: 'BundleProductOptionSkeleton',
components: {
SkeletonLoader,
},
});
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ export default defineComponent({

emit('fetchProduct', { query: getBaseSearchQuery() });
};

return {
addItem,
addItemToWishlist: addOrRemoveItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ export default defineComponent({

watch(
() => props.product,
(product) => {
const price = getGroupedProductPriceCommand(product);
(productNewValue) => {
const price = getGroupedProductPriceCommand(productNewValue);
emit('update-price', price);
},
{
Expand Down
Loading