From a93df26819f442bd500d77aa8ffcbcfb50357820 Mon Sep 17 00:00:00 2001 From: tuannguyenh1 Date: Thu, 26 Sep 2024 17:34:17 +0700 Subject: [PATCH] #1064 [BACKOFFICE] [Bugs] Product Variations - show images ith thumbnail --- .../common/components/ProductImageGallery.tsx | 7 +- .../catalog/components/ProductDetails.tsx | 91 ++++++++++++++----- 2 files changed, 73 insertions(+), 25 deletions(-) diff --git a/storefront/common/components/ProductImageGallery.tsx b/storefront/common/components/ProductImageGallery.tsx index 89f0ce4b11..a7139af3c3 100644 --- a/storefront/common/components/ProductImageGallery.tsx +++ b/storefront/common/components/ProductImageGallery.tsx @@ -20,12 +20,13 @@ export function ProductImageGallery({ listImages }: IProductImageGalleryProps) { const currentMax = Math.max(currentIndex - Math.floor(NO_SLIDER_IMAGE / 2), 0); - if (currentMax < listImages.length - NO_SLIDER_IMAGE) { + let remainingImages = listImages.length - NO_SLIDER_IMAGE; + if (currentMax < remainingImages) { // If there are enough images after the current index to fill the slider, start the slider at the current max startSliderIndex = currentMax; - } else { + } else if (remainingImages >= 0) { // Otherwise, start the slider at the end of the list minus the maximum number of images to show - startSliderIndex = listImages.length - NO_SLIDER_IMAGE; + startSliderIndex = remainingImages; } const visibleImages = diff --git a/storefront/modules/catalog/components/ProductDetails.tsx b/storefront/modules/catalog/components/ProductDetails.tsx index 60d77925af..97bf1788b5 100644 --- a/storefront/modules/catalog/components/ProductDetails.tsx +++ b/storefront/modules/catalog/components/ProductDetails.tsx @@ -42,7 +42,10 @@ export default function ProductDetails({ const initCurrentSelectedOption = useMemo(() => { if (!productOptions?.length || !productVariations?.length) { - setListImages(product.productImageMediaUrls); + setListImages([ + ...(product.thumbnailMediaUrl ? [product.thumbnailMediaUrl] : []), + ...product.productImageMediaUrls, + ]); return {}; } @@ -58,8 +61,14 @@ export default function ProductDetails({ setListImages( productWithColor - ? productWithColor.productImages.map((image) => image.url) - : product.productImageMediaUrls + ? [ + ...(productWithColor.thumbnail?.url ? [productWithColor.thumbnail.url] : []), + ...productWithColor.productImages.map((image) => image.url), + ] + : [ + ...(product.thumbnailMediaUrl ? [product.thumbnailMediaUrl] : []), + ...product.productImageMediaUrls, + ] ); return productWithColor ? productWithColor.options : productVariations[0].options; }, [productOptions, productVariations, pvid]); @@ -84,30 +93,68 @@ export default function ProductDetails({ }, [productOptions, productVariations, pvid, currentProduct.id]); useEffect(() => { - if (productOptions?.length && productVariations?.length) { - const productVariation = productVariations.find((item) => { + const isOptionSelected = ( + key: string, + currentSelectedOption: CurrentSelectedOption, + item: ProductVariation + ) => { + return currentSelectedOption[+key] === item.options[+key]; + }; + + const areAllOptionsSelected = ( + optionKeys: string[], + currentSelectedOption: CurrentSelectedOption, + item: ProductVariation + ) => { + return optionKeys.every((key: string) => isOptionSelected(key, currentSelectedOption, item)); + }; + + const findProductVariation = () => { + return productVariations?.find((item) => { + const optionKeys = Object.keys(item.options); return ( - Object.keys(item.options).length === Object.keys(currentSelectedOption).length && - Object.keys(item.options).every((key) => { - return currentSelectedOption[+key] === item.options[+key]; - }) + optionKeys.length === Object.keys(currentSelectedOption).length && + areAllOptionsSelected(optionKeys, currentSelectedOption, item) ); }); + }; + + const updateListImages = (variation: ProductVariation) => { + const urls = [ + ...(variation.thumbnail?.url ? [variation.thumbnail.url] : []), + ...variation.productImages.map((image) => image.url), + ]; + setListImages(urls); + setCurrentProduct(variation); + }; + + const updateListImagesBySelectedProduct = ( + productVariations: ProductVariation[], + productOptions: ProductOptions[] + ) => { + const productSelected = productVariations.find((item) => { + return item.options[+Object.keys(optionSelected)[0]] == Object.values(optionSelected)[0]; + }); + + if (productSelected) { + const colorId = getColorId(productOptions); + if (colorId === +Object.keys(optionSelected)[0]) { + const urlList = productSelected.productImages.map((image) => image.url); + setListImages([ + ...(productSelected.thumbnail?.url ? [productSelected.thumbnail.url] : []), + ...urlList, + ]); + } + setCurrentProduct(productSelected); + } + }; + + if (productOptions?.length && productVariations?.length) { + const productVariation = findProductVariation(); if (productVariation) { - setListImages(productVariation.productImages.map((image) => image.url)); - setCurrentProduct(productVariation); + updateListImages(productVariation); } else { - const productSelected = productVariations.find((item) => { - return item.options[+Object.keys(optionSelected)[0]] == Object.values(optionSelected)[0]; - }); - if (productSelected) { - const colorId = getColorId(productOptions); - if (colorId === +Object.keys(optionSelected)[0]) { - const urlList = productSelected.productImages.map((image) => image.url); - setListImages(urlList); - } - setCurrentProduct(productSelected); - } + updateListImagesBySelectedProduct(productVariations, productOptions); } } // eslint-disable-next-line react-hooks/exhaustive-deps