{"version":3,"sources":["webpack:///./src/themes/newsunshine-dev/views/components/product.component.tsx?4c29","webpack:///./src/themes/newsunshine/views/components/product.component.tsx?43ac","webpack:///./src/themes/newsunshine-dev-b2c/views/components/product.component.tsx?a70f","webpack:///src/modules/adventureworks/views/components/product.component.tsx?f602","webpack:///./src/themes/newsunshine-b2c/views/components/product.component.tsx?7628"],"names":["getDefaultSwatchSelected","coreContext","productData","_productData$Attribut","_attributeSwatches$fi","AttributeValues","dimensionToPreSelectInProductCard","app","config","attributeSwatches","find","attributeValue","_attributeValue$KeyNa","KeyName","toLocaleLowerCase","Swatches","ArrayExtensions","hasElements","item","IsDefault","updateProductUrl","productDetailsPageUrl","queryString","sourceUrl","URL","request","apiSettings","baseUrl","search","href","pathname","renderProductUnitOfMeasure","unitOfMeasure","React","createElement","className","renderLabel","name","price","rating","ratingAriaLabelText","reviewCount","ratingCountAriaLabelText","reviewCountArialableText","getReviewAriaLabel","getRatingAriaLabel","ratingAriaLabel","roundedRating","toFixed","format","renderPrice","context","typeName","id","basePrice","adjustedPrice","savingsText","freePriceText","originalPriceText","currentPriceText","isPriceMinMaxEnabled","priceResources","BasePrice","AdjustedPrice","CustomerContextualPrice","PriceComponent","data","renderProductPlacementImage","imageSettings","gridSettings","imageUrl","fallbackImageUrl","altText","_context$app$config","contextConfig","placeholderImageName","fallbackImageSource","img","src","fallBackSrc","imageProps","cropFocalRegion","Image","Object","assign","requestContext","actionContext","loadFailureBehavior","bypassHideOnFailure","ProductComponent","msdyn365Commerce","createComponentOverride","_objectSpread","component","_ref","_product$Name","_product$RecordId","_getProductImageUrlFr","_getProductPageUrlFro","_data$product","_data$product2","_data$product3","_product$Name2","_product$Name3","ratingCountAriaLabel","allowBack","telemetryContent","quickViewButton","productComparisonButton","isEnabledProductDescription","inventoryLabel","dimensionAvailabilities","swatchItemAriaLabel","product","productUrl","getProductPageUrlSync","Name","RecordId","Number","MIN_VALUE","undefined","productImageUrlFromSwatch","defaultSwatch","swatchProductImageUrls","ProductImageUrls","generateImageUrl","PrimaryImageUrl","getProductImageUrlFromDefaultSwatch","productPageUrlFromSwatch","SwatchValue","encodeURIComponent","getProductPageUrlFromDefaultSwatch","productPageUrl","setProductPageUrl","useState","productImageUrl","setProductImageUrl","useEffect","selectedSwatchItems","Dictionary","enableStockCheck","updatePageAndImageUrl","useCallback","swatchItem","dimensionType","setValue","StringExtensions","isNullOrWhitespace","value","productPageUrlWithSwatch","includes","newUrl","searchParams","delete","toString","swatchProductImageUrl","productImageUrls","newImageUrl","payLoad","getPayloadObject","attribute","getTelemetryAttributes","isUnitOfMeasureEnabled","unitOfMeasureDisplayType","brandName","brandNameAttributeRecordId","productSize","productSizeAttributeRecordId","productUnit","productUnitAttributeRecordId","productNameLength","length","Fragment","onClick","onTelemetryClick","cultureFormatter","formatCurrency","Price","AverageRating","TotalRatings","DefaultUnitOfMeasure","description","Description","TextValue","FloatValue","attributeValues","map","_item$KeyName$toLocal","_item$KeyName","_item$Swatches$map","_item$Swatches","dimensionTypeValue","dimensionsToDisplayOnProductCard","dimensionsInProductCard","DimensionTypes","none","shouldDisplayDimension","swatches","_item$RecordId","_swatchItem$SwatchVal","_swatchItem$SwatchVal2","_dimensionAvailabilit","itemId","colorHexCode","SwatchColorHexCode","SwatchImageUrl","isDefault","isDisabled","dimensionAvailability","_swatchItem$SwatchVal3","some","swatch","ProductComponentSwatchComponent","onSelectDimension","key","hideRating","moduleTypeName","moduleId","avgRating","totalRatings","ariaLabel","numberRatings","RatingComponent","ratingCount","readOnly","renderRating","inventoryAvailabilityLabel","quickview","selectedDimensions","getValues","DimensionTypeValue","convertDimensionTypeToProductDimensionType","DimensionValue","Value","cloneElement","selectedProductId","renderQuickView","catalogId","validateCatalogId","renderProductComparisonButton","getCatalogId","brandNameAttributeName","productSizeAttributeName","productUnitAttributeName"],"mappings":"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","file":"static/js/20.0862b4016d1f94fac183.chunk.js","sourcesContent":["/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { IProductsDimensionsAvailabilities } from '@msdyn365-commerce/commerce-entities';\r\nimport {\r\n IPriceComponentResources,\r\n ISwatchItem,\r\n PriceComponent,\r\n ProductComponentSwatchComponent,\r\n RatingComponent\r\n} from '@msdyn365-commerce/components';\r\nimport {\r\n getCatalogId,\r\n IAny,\r\n IComponent,\r\n IComponentProps,\r\n ICoreContext,\r\n IGeneric,\r\n IGridSettings,\r\n IImageData,\r\n IImageSettings,\r\n Image,\r\n msdyn365Commerce\r\n} from '@msdyn365-commerce/core';\r\nimport { AttributeSwatch, AttributeValue, ProductDimension, ProductPrice, ProductSearchResult } from '@msdyn365-commerce/retail-proxy';\r\nimport {\r\n ArrayExtensions,\r\n convertDimensionTypeToProductDimensionType,\r\n Dictionary,\r\n DimensionTypes,\r\n generateImageUrl,\r\n getProductPageUrlSync,\r\n IDimensionsApp,\r\n StringExtensions,\r\n validateCatalogId\r\n} from '@msdyn365-commerce-modules/retail-actions';\r\nimport {\r\n format,\r\n getPayloadObject,\r\n getTelemetryAttributes,\r\n ITelemetryContent,\r\n onTelemetryClick\r\n} from '@msdyn365-commerce-modules/utilities';\r\nimport React, { useState } from 'react';\r\n\r\nexport interface IProductComponentProps extends IComponentProps<{ product?: ProductSearchResult }> {\r\n className?: string;\r\n imageSettings?: IImageSettings;\r\n savingsText?: string;\r\n freePriceText?: string;\r\n originalPriceText?: string;\r\n currentPriceText?: string;\r\n ratingAriaLabel?: string;\r\n ratingCountAriaLabel?: string;\r\n allowBack?: boolean;\r\n telemetryContent?: ITelemetryContent;\r\n quickViewButton?: React.ReactNode;\r\n productComparisonButton?: React.ReactNode;\r\n isEnabledProductDescription?: boolean;\r\n isPriceMinMaxEnabled?: boolean;\r\n priceResources?: IPriceComponentResources;\r\n inventoryLabel?: string;\r\n dimensionAvailabilities?: IProductsDimensionsAvailabilities[];\r\n swatchItemAriaLabel?: string;\r\n}\r\n\r\nexport interface IProductComponent extends IComponent {}\r\n\r\nconst PriceComponentActions = {};\r\n\r\n/**\r\n * Gets the product page url from the default swatch selected.\r\n * @param productData - Product card to be rendered.\r\n * @returns The default color swatch selected if any.\r\n */\r\nfunction getDefaultSwatchSelected(coreContext: ICoreContext, productData?: ProductSearchResult): AttributeSwatch | null {\r\n if (!productData || !productData.AttributeValues) {\r\n return null;\r\n }\r\n\r\n const siteContext = coreContext as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n const attributeSwatches = productData.AttributeValues.find(\r\n attributeValue => attributeValue.KeyName?.toLocaleLowerCase() === dimensionToPreSelectInProductCard\r\n )?.Swatches;\r\n\r\n if (!ArrayExtensions.hasElements(attributeSwatches)) {\r\n return null;\r\n }\r\n\r\n const defaultSwatch = attributeSwatches.find(item => item.IsDefault === true) ?? attributeSwatches[0];\r\n return defaultSwatch;\r\n}\r\n\r\n/**\r\n * Gets the product image from the default swatch selected.\r\n * @param coreContext - Context of the module using the component.\r\n * @param productData - Product card to be rendered.\r\n * @returns The product card image url.\r\n */\r\nfunction getProductImageUrlFromDefaultSwatch(coreContext: ICoreContext, productData?: ProductSearchResult): string | undefined {\r\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\r\n const swatchProductImageUrls = defaultSwatch?.ProductImageUrls;\r\n if (!ArrayExtensions.hasElements(swatchProductImageUrls)) {\r\n return productData?.PrimaryImageUrl;\r\n }\r\n\r\n return generateImageUrl(swatchProductImageUrls[0], coreContext.request.apiSettings);\r\n}\r\n\r\n/**\r\n * Updates the product url link to product details page.\r\n * @param productDetailsPageUrl - Product page url.\r\n * @param coreContext - Context of the module using the component.\r\n * @param queryString - Querystring to be added to the URL.\r\n * @returns The update product page url.\r\n */\r\nfunction updateProductUrl(productDetailsPageUrl: string, coreContext: ICoreContext, queryString: string): string {\r\n const sourceUrl = new URL(productDetailsPageUrl, coreContext.request.apiSettings.baseUrl);\r\n if (sourceUrl.search) {\r\n sourceUrl.search += `&${queryString}`;\r\n } else {\r\n sourceUrl.search += queryString;\r\n }\r\n\r\n const updatedUrl = new URL(sourceUrl.href);\r\n return updatedUrl.pathname + sourceUrl.search;\r\n}\r\n\r\n/**\r\n * Gets the react node for product unit of measure display.\r\n * @param unitOfMeasure - DefaultUnitOfMeasure property from product.\r\n * @returns The node representing markup for unit of measure component.\r\n */\r\nfunction renderProductUnitOfMeasure(unitOfMeasure?: string): JSX.Element | null {\r\n if (!unitOfMeasure) {\r\n return null;\r\n }\r\n return (\r\n
\r\n {unitOfMeasure}\r\n
\r\n );\r\n}\r\n\r\n/**\r\n * Gets the react node for product availability.\r\n * @param inventoryAvailabilityLabel - The product information.\r\n * @returns The node representing markup for product availability.\r\n */\r\nfunction renderProductAvailability(inventoryAvailabilityLabel: string | undefined): JSX.Element | null {\r\n if (!inventoryAvailabilityLabel || inventoryAvailabilityLabel === '') {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n {inventoryAvailabilityLabel}\r\n
\r\n );\r\n}\r\n\r\n/**\r\n * Renders product comparison button similar to the quick view button.\r\n * @param productComparisonButton - React element of the button.\r\n * @param product - Current product info.\r\n * @param catalogId - Current catalog.\r\n * @returns React element for the specific product.\r\n */\r\nfunction renderProductComparisonButton(\r\n productComparisonButton: React.ReactNode,\r\n product: ProductSearchResult,\r\n catalogId: number\r\n): JSX.Element | undefined {\r\n validateCatalogId(catalogId);\r\n return React.cloneElement(productComparisonButton as React.ReactElement, { product, catalogId });\r\n}\r\n\r\n/**\r\n * Gets the product page url from the default swatch selected.\r\n * @param coreContext - Context of the module using the component.\r\n * @param productUrl - Product page url for the product card.\r\n * @param productData - Product card to be rendered.\r\n * @returns The product card image url.\r\n */\r\nfunction getProductPageUrlFromDefaultSwatch(\r\n coreContext: ICoreContext,\r\n productUrl: string,\r\n productData?: ProductSearchResult\r\n): string | undefined {\r\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\r\n if (!defaultSwatch?.SwatchValue) {\r\n return productUrl;\r\n }\r\n\r\n const siteContext = coreContext as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n const queryStringEncoded = encodeURIComponent(defaultSwatch.SwatchValue);\r\n const queryString = `${dimensionToPreSelectInProductCard}=${queryStringEncoded}`;\r\n return updateProductUrl(productUrl, coreContext, queryString);\r\n}\r\n\r\nconst ProductCard: React.FC = ({\r\n data,\r\n context,\r\n imageSettings,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText,\r\n ratingAriaLabel,\r\n ratingCountAriaLabel,\r\n allowBack,\r\n typeName,\r\n id,\r\n telemetryContent,\r\n quickViewButton,\r\n productComparisonButton,\r\n isEnabledProductDescription,\r\n isPriceMinMaxEnabled,\r\n priceResources,\r\n inventoryLabel,\r\n dimensionAvailabilities,\r\n swatchItemAriaLabel\r\n}) => {\r\n const product = data.product;\r\n\r\n let productUrl = getProductPageUrlSync(product?.Name ?? '', product?.RecordId ?? Number.MIN_VALUE, context.actionContext, undefined);\r\n if (allowBack) {\r\n productUrl = updateProductUrl(productUrl, context, 'back=true');\r\n }\r\n const productImageUrlFromSwatch = getProductImageUrlFromDefaultSwatch(context, product) ?? product?.PrimaryImageUrl;\r\n const productPageUrlFromSwatch = getProductPageUrlFromDefaultSwatch(context, productUrl, product) ?? productUrl;\r\n const [productPageUrl, setProductPageUrl] = useState(productPageUrlFromSwatch);\r\n const [productImageUrl, setProductImageUrl] = useState(productImageUrlFromSwatch);\r\n React.useEffect(() => {\r\n setProductPageUrl(productPageUrlFromSwatch);\r\n setProductImageUrl(productImageUrlFromSwatch);\r\n }, [productUrl, productPageUrlFromSwatch, productImageUrlFromSwatch]);\r\n const [selectedSwatchItems] = useState(new Dictionary());\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access -- app context is generic\r\n const enableStockCheck = context.app.config.enableStockCheck;\r\n\r\n const siteContext = context as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n /**\r\n * Updates the product page and Image url based on swatch selected.\r\n * @param coreContext - Context of the caller.\r\n * @param swatchItem - Dimension swatch selected.\r\n */\r\n const updatePageAndImageUrl = React.useCallback(\r\n (coreContext: ICoreContext, swatchItem: ISwatchItem) => {\r\n const dimensionType = swatchItem.dimensionType;\r\n selectedSwatchItems.setValue(dimensionType, swatchItem);\r\n if (StringExtensions.isNullOrWhitespace(swatchItem.value)) {\r\n return;\r\n }\r\n const queryString = `${dimensionType}=${swatchItem.value}`;\r\n let productPageUrlWithSwatch = '';\r\n if (productPageUrl.includes(dimensionType)) {\r\n const newUrl = new URL(productPageUrl, coreContext.request.apiSettings.baseUrl);\r\n newUrl.searchParams.delete(dimensionType);\r\n productPageUrlWithSwatch = updateProductUrl(newUrl.toString(), context, queryString);\r\n } else {\r\n productPageUrlWithSwatch = updateProductUrl(productPageUrl, context, queryString);\r\n }\r\n setProductPageUrl(productPageUrlWithSwatch);\r\n if (dimensionType === dimensionToPreSelectInProductCard) {\r\n const swatchProductImageUrl = ArrayExtensions.hasElements(swatchItem.productImageUrls)\r\n ? swatchItem.productImageUrls[0]\r\n : undefined;\r\n const newImageUrl = generateImageUrl(swatchProductImageUrl, coreContext.request.apiSettings);\r\n setProductImageUrl(newImageUrl);\r\n }\r\n },\r\n [selectedSwatchItems, context, productPageUrl]\r\n );\r\n\r\n if (!product) {\r\n return null;\r\n }\r\n\r\n /**\r\n * Checks if rendering the particular dimensions is allowed for product card.\r\n * @param dimensionType - Dimension to be displayed.\r\n * @returns Updates the state with new product page url.\r\n */\r\n function shouldDisplayDimension(dimensionType: string): boolean {\r\n const dimensionsContext = context as ICoreContext;\r\n const dimensionsToDisplayOnProductCard = dimensionsContext.app.config.dimensionsInProductCard;\r\n return (\r\n ArrayExtensions.hasElements(dimensionsToDisplayOnProductCard) &&\r\n !dimensionsToDisplayOnProductCard.includes(DimensionTypes.none) &&\r\n dimensionsToDisplayOnProductCard.includes(dimensionType.toLocaleLowerCase() as DimensionTypes)\r\n );\r\n }\r\n\r\n /**\r\n * Gets the react node for product dimension as swatch.\r\n * @param attributeValues - Attribute value property from product.\r\n * @returns The node representing markup for unit of measure component.\r\n */\r\n function renderProductDimensions(attributeValues?: AttributeValue[]): JSX.Element | null {\r\n if (!attributeValues) {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n {attributeValues.map((item: AttributeValue) => {\r\n const dimensionTypeValue = item.KeyName?.toLocaleLowerCase() ?? '';\r\n if (!shouldDisplayDimension(dimensionTypeValue)) {\r\n return null;\r\n }\r\n\r\n const siteContext = context as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n const dimensionType = dimensionTypeValue as DimensionTypes;\r\n const swatches =\r\n item.Swatches?.map(swatchItem => {\r\n return {\r\n itemId: `${item.RecordId ?? ''}-${dimensionTypeValue}-${swatchItem.SwatchValue ?? ''}`,\r\n value: swatchItem.SwatchValue ?? '',\r\n dimensionType,\r\n colorHexCode: swatchItem.SwatchColorHexCode,\r\n imageUrl: swatchItem.SwatchImageUrl,\r\n productImageUrls: swatchItem.ProductImageUrls,\r\n isDefault: swatchItem.IsDefault,\r\n swatchItemAriaLabel: swatchItemAriaLabel ? format(swatchItemAriaLabel, dimensionType) : '',\r\n isDisabled:\r\n enableStockCheck &&\r\n dimensionAvailabilities?.find(\r\n dimensionAvailability => dimensionAvailability.value === (swatchItem.SwatchValue ?? '')\r\n )?.isDisabled\r\n };\r\n }) ?? [];\r\n if (\r\n dimensionType === dimensionToPreSelectInProductCard &&\r\n ArrayExtensions.hasElements(swatches) &&\r\n !swatches.some(swatch => swatch.isDefault)\r\n ) {\r\n swatches[0].isDefault = true;\r\n }\r\n return (\r\n \r\n );\r\n })}\r\n
\r\n );\r\n }\r\n\r\n function renderQuickView(quickview: React.ReactNode, item?: number): JSX.Element | undefined {\r\n if (quickview === null) {\r\n return undefined;\r\n }\r\n const selectedDimensions: ProductDimension[] = selectedSwatchItems.getValues().map(swatches => {\r\n return {\r\n DimensionTypeValue: convertDimensionTypeToProductDimensionType(swatches.dimensionType),\r\n DimensionValue: {\r\n RecordId: 0,\r\n Value: swatches.value\r\n }\r\n };\r\n });\r\n return React.cloneElement(quickview as React.ReactElement, { selectedProductId: item, selectedDimensions });\r\n }\r\n\r\n // Construct telemetry attribute to render\r\n const payLoad = getPayloadObject('click', telemetryContent!, '', product.RecordId.toString());\r\n\r\n const attribute = getTelemetryAttributes(telemetryContent!, payLoad);\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- -- Do not need type check for appsettings\r\n const isUnitOfMeasureEnabled = context.app.config && context.app.config.unitOfMeasureDisplayType === 'buyboxAndBrowse';\r\n\r\n const brandName = data.product?.AttributeValues?.find(attribute => attribute.RecordId === context.app.config.brandNameAttributeRecordId);\r\n const productSize = data.product?.AttributeValues?.find(attribute => attribute.RecordId === context.app.config.productSizeAttributeRecordId);\r\n const productUnit = data.product?.AttributeValues?.find(attribute => attribute.RecordId === context.app.config.productUnitAttributeRecordId);\r\n const productNameLength = product.Name?.length && product.Name?.length < 10;\r\n return (\r\n <>\r\n {isEnabledProductDescription ? (\r\n \r\n
\r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n productImageUrl,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n context\r\n )}\r\n
\r\n
\r\n
{product.Name}
\r\n {renderPrice(\r\n context,\r\n typeName,\r\n id,\r\n product.BasePrice,\r\n product.Price,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText,\r\n isPriceMinMaxEnabled,\r\n priceResources\r\n )}\r\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\r\n {renderDescription(product.Description)}\r\n
\r\n
\r\n \r\n ) : (\r\n \r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n productImageUrl,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n context\r\n )}\r\n
\r\n
\r\n
\r\n {brandName?.TextValue}\r\n
{product.Name}
\r\n
\r\n
\r\n {renderPrice(\r\n context,\r\n typeName,\r\n id,\r\n product.BasePrice,\r\n product.Price,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText\r\n )}\r\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\r\n {productSize?.FloatValue} {productUnit?.TextValue}\r\n
\r\n
\r\n \r\n )}\r\n {renderProductDimensions(product.AttributeValues)}\r\n {!context.app.config.hideRating &&\r\n renderRating(context, typeName, id, product.AverageRating, product.TotalRatings, ratingAriaLabel, ratingCountAriaLabel)}\r\n {renderProductAvailability(inventoryLabel)}\r\n {quickViewButton && renderQuickView(quickViewButton, product.RecordId)}\r\n {productComparisonButton && renderProductComparisonButton(productComparisonButton, product, getCatalogId(context.request))}\r\n \r\n );\r\n};\r\n\r\nfunction renderLabel(\r\n name?: string,\r\n price?: string,\r\n rating?: number,\r\n ratingAriaLabelText?: string,\r\n reviewCount?: number,\r\n ratingCountAriaLabelText?: string\r\n): string {\r\n const reviewCountArialableText = getReviewAriaLabel(reviewCount, ratingCountAriaLabelText ?? '');\r\n return `${name ?? ''} ${price ?? ''} ${getRatingAriaLabel(rating, ratingAriaLabelText)}${\r\n reviewCountArialableText ? ` ${reviewCountArialableText}` : ''\r\n }`;\r\n}\r\n\r\nfunction renderDescription(description?: string): JSX.Element | null {\r\n return

{description}

;\r\n}\r\n\r\nfunction getRatingAriaLabel(rating?: number, ratingAriaLabel?: string): string {\r\n if (rating && ratingAriaLabel) {\r\n const roundedRating = rating.toFixed(2);\r\n return format(ratingAriaLabel || '', roundedRating, '5');\r\n }\r\n return '';\r\n}\r\n\r\nfunction getReviewAriaLabel(reviewCount?: number, ratingCountAriaLabelText?: string): string {\r\n if (reviewCount && ratingCountAriaLabelText) {\r\n return format(ratingCountAriaLabelText || '', reviewCount);\r\n }\r\n return '';\r\n}\r\n\r\nfunction renderRating(\r\n coreContext: ICoreContext,\r\n moduleTypeName: string,\r\n moduleId: string,\r\n avgRating?: number,\r\n totalRatings?: number,\r\n ariaLabel?: string,\r\n ratingCountAriaLabel?: string\r\n): JSX.Element | null {\r\n if (!avgRating) {\r\n return null;\r\n }\r\n\r\n const numberRatings = totalRatings?.toString() || undefined;\r\n const ratingAriaLabelText = getRatingAriaLabel(avgRating, ariaLabel);\r\n const ratingCountAriaLabelText = getReviewAriaLabel(Number(numberRatings), ratingCountAriaLabel);\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nfunction renderPrice(\r\n context: ICoreContext,\r\n typeName: string,\r\n id: string,\r\n basePrice?: number,\r\n adjustedPrice?: number,\r\n savingsText?: string,\r\n freePriceText?: string,\r\n originalPriceText?: string,\r\n currentPriceText?: string,\r\n isPriceMinMaxEnabled?: boolean,\r\n priceResources?: IPriceComponentResources\r\n): JSX.Element | null {\r\n const price: ProductPrice = {\r\n BasePrice: basePrice,\r\n AdjustedPrice: adjustedPrice,\r\n CustomerContextualPrice: adjustedPrice\r\n };\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nfunction renderProductPlacementImage(\r\n imageSettings?: IImageSettings,\r\n gridSettings?: IGridSettings,\r\n imageUrl?: string,\r\n fallbackImageUrl?: string,\r\n altText?: string,\r\n context?: ICoreContext>\r\n): JSX.Element | null {\r\n if (!imageUrl || !gridSettings || !imageSettings) {\r\n return null;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- Site level config can be of any type.\r\n const contextConfig = context?.app.config?.placeholderImageName;\r\n const emptyPlaceHolderImage = contextConfig as string;\r\n let fallbackImageSource = fallbackImageUrl;\r\n if (emptyPlaceHolderImage && fallbackImageUrl) {\r\n fallbackImageSource = `${fallbackImageUrl},${emptyPlaceHolderImage}`;\r\n }\r\n const img: IImageData = {\r\n src: imageUrl,\r\n altText: altText ? altText : '',\r\n fallBackSrc: fallbackImageSource\r\n };\r\n const imageProps = {\r\n gridSettings,\r\n imageSettings\r\n };\r\n imageProps.imageSettings.cropFocalRegion = true;\r\n return (\r\n \r\n );\r\n}\r\n\r\nexport const ProductComponent: React.FunctionComponent = msdyn365Commerce.createComponentOverride<\r\n IProductComponent\r\n>('Product', { component: ProductCard, ...PriceComponentActions });\r\n\r\nexport default ProductComponent;\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { IProductsDimensionsAvailabilities } from '@msdyn365-commerce/commerce-entities';\r\nimport {\r\n IPriceComponentResources,\r\n ISwatchItem,\r\n PriceComponent,\r\n ProductComponentSwatchComponent,\r\n RatingComponent\r\n} from '@msdyn365-commerce/components';\r\nimport {\r\n getCatalogId,\r\n IAny,\r\n IComponent,\r\n IComponentProps,\r\n ICoreContext,\r\n IGeneric,\r\n IGridSettings,\r\n IImageData,\r\n IImageSettings,\r\n Image,\r\n msdyn365Commerce\r\n} from '@msdyn365-commerce/core';\r\nimport { AttributeSwatch, AttributeValue, ProductDimension, ProductPrice, ProductSearchResult } from '@msdyn365-commerce/retail-proxy';\r\nimport {\r\n ArrayExtensions,\r\n convertDimensionTypeToProductDimensionType,\r\n Dictionary,\r\n DimensionTypes,\r\n generateImageUrl,\r\n getProductPageUrlSync,\r\n IDimensionsApp,\r\n StringExtensions,\r\n validateCatalogId\r\n} from '@msdyn365-commerce-modules/retail-actions';\r\nimport {\r\n format,\r\n getPayloadObject,\r\n getTelemetryAttributes,\r\n ITelemetryContent,\r\n onTelemetryClick\r\n} from '@msdyn365-commerce-modules/utilities';\r\nimport React, { useState } from 'react';\r\n\r\nexport interface IProductComponentProps extends IComponentProps<{ product?: ProductSearchResult }> {\r\n className?: string;\r\n imageSettings?: IImageSettings;\r\n savingsText?: string;\r\n freePriceText?: string;\r\n originalPriceText?: string;\r\n currentPriceText?: string;\r\n ratingAriaLabel?: string;\r\n ratingCountAriaLabel?: string;\r\n allowBack?: boolean;\r\n telemetryContent?: ITelemetryContent;\r\n quickViewButton?: React.ReactNode;\r\n productComparisonButton?: React.ReactNode;\r\n isEnabledProductDescription?: boolean;\r\n isPriceMinMaxEnabled?: boolean;\r\n priceResources?: IPriceComponentResources;\r\n inventoryLabel?: string;\r\n dimensionAvailabilities?: IProductsDimensionsAvailabilities[];\r\n swatchItemAriaLabel?: string;\r\n}\r\n\r\nexport interface IProductComponent extends IComponent {}\r\n\r\nconst PriceComponentActions = {};\r\n\r\n/**\r\n * Gets the product page url from the default swatch selected.\r\n * @param productData - Product card to be rendered.\r\n * @returns The default color swatch selected if any.\r\n */\r\nfunction getDefaultSwatchSelected(coreContext: ICoreContext, productData?: ProductSearchResult): AttributeSwatch | null {\r\n if (!productData || !productData.AttributeValues) {\r\n return null;\r\n }\r\n\r\n const siteContext = coreContext as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n const attributeSwatches = productData.AttributeValues.find(\r\n attributeValue => attributeValue.KeyName?.toLocaleLowerCase() === dimensionToPreSelectInProductCard\r\n )?.Swatches;\r\n\r\n if (!ArrayExtensions.hasElements(attributeSwatches)) {\r\n return null;\r\n }\r\n\r\n const defaultSwatch = attributeSwatches.find(item => item.IsDefault === true) ?? attributeSwatches[0];\r\n return defaultSwatch;\r\n}\r\n\r\n/**\r\n * Gets the product image from the default swatch selected.\r\n * @param coreContext - Context of the module using the component.\r\n * @param productData - Product card to be rendered.\r\n * @returns The product card image url.\r\n */\r\nfunction getProductImageUrlFromDefaultSwatch(coreContext: ICoreContext, productData?: ProductSearchResult): string | undefined {\r\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\r\n const swatchProductImageUrls = defaultSwatch?.ProductImageUrls;\r\n if (!ArrayExtensions.hasElements(swatchProductImageUrls)) {\r\n return productData?.PrimaryImageUrl;\r\n }\r\n\r\n return generateImageUrl(swatchProductImageUrls[0], coreContext.request.apiSettings);\r\n}\r\n\r\n/**\r\n * Updates the product url link to product details page.\r\n * @param productDetailsPageUrl - Product page url.\r\n * @param coreContext - Context of the module using the component.\r\n * @param queryString - Querystring to be added to the URL.\r\n * @returns The update product page url.\r\n */\r\nfunction updateProductUrl(productDetailsPageUrl: string, coreContext: ICoreContext, queryString: string): string {\r\n const sourceUrl = new URL(productDetailsPageUrl, coreContext.request.apiSettings.baseUrl);\r\n if (sourceUrl.search) {\r\n sourceUrl.search += `&${queryString}`;\r\n } else {\r\n sourceUrl.search += queryString;\r\n }\r\n\r\n const updatedUrl = new URL(sourceUrl.href);\r\n return updatedUrl.pathname + sourceUrl.search;\r\n}\r\n\r\n/**\r\n * Gets the react node for product unit of measure display.\r\n * @param unitOfMeasure - DefaultUnitOfMeasure property from product.\r\n * @returns The node representing markup for unit of measure component.\r\n */\r\nfunction renderProductUnitOfMeasure(unitOfMeasure?: string): JSX.Element | null {\r\n if (!unitOfMeasure) {\r\n return null;\r\n }\r\n return (\r\n
\r\n {unitOfMeasure}\r\n
\r\n );\r\n}\r\n\r\n/**\r\n * Gets the react node for product availability.\r\n * @param inventoryAvailabilityLabel - The product information.\r\n * @returns The node representing markup for product availability.\r\n */\r\nfunction renderProductAvailability(inventoryAvailabilityLabel: string | undefined): JSX.Element | null {\r\n if (!inventoryAvailabilityLabel || inventoryAvailabilityLabel === '') {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n {inventoryAvailabilityLabel}\r\n
\r\n );\r\n}\r\n\r\n/**\r\n * Renders product comparison button similar to the quick view button.\r\n * @param productComparisonButton - React element of the button.\r\n * @param product - Current product info.\r\n * @param catalogId - Current catalog.\r\n * @returns React element for the specific product.\r\n */\r\nfunction renderProductComparisonButton(\r\n productComparisonButton: React.ReactNode,\r\n product: ProductSearchResult,\r\n catalogId: number\r\n): JSX.Element | undefined {\r\n validateCatalogId(catalogId);\r\n return React.cloneElement(productComparisonButton as React.ReactElement, { product, catalogId });\r\n}\r\n\r\n/**\r\n * Gets the product page url from the default swatch selected.\r\n * @param coreContext - Context of the module using the component.\r\n * @param productUrl - Product page url for the product card.\r\n * @param productData - Product card to be rendered.\r\n * @returns The product card image url.\r\n */\r\nfunction getProductPageUrlFromDefaultSwatch(\r\n coreContext: ICoreContext,\r\n productUrl: string,\r\n productData?: ProductSearchResult\r\n): string | undefined {\r\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\r\n if (!defaultSwatch?.SwatchValue) {\r\n return productUrl;\r\n }\r\n\r\n const siteContext = coreContext as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n const queryStringEncoded = encodeURIComponent(defaultSwatch.SwatchValue);\r\n const queryString = `${dimensionToPreSelectInProductCard}=${queryStringEncoded}`;\r\n return updateProductUrl(productUrl, coreContext, queryString);\r\n}\r\n\r\nconst ProductCard: React.FC = ({\r\n data,\r\n context,\r\n imageSettings,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText,\r\n ratingAriaLabel,\r\n ratingCountAriaLabel,\r\n allowBack,\r\n typeName,\r\n id,\r\n telemetryContent,\r\n quickViewButton,\r\n productComparisonButton,\r\n isEnabledProductDescription,\r\n isPriceMinMaxEnabled,\r\n priceResources,\r\n inventoryLabel,\r\n dimensionAvailabilities,\r\n swatchItemAriaLabel\r\n}) => {\r\n const product = data.product;\r\n\r\n let productUrl = getProductPageUrlSync(product?.Name ?? '', product?.RecordId ?? Number.MIN_VALUE, context.actionContext, undefined);\r\n if (allowBack) {\r\n productUrl = updateProductUrl(productUrl, context, 'back=true');\r\n }\r\n const productImageUrlFromSwatch = getProductImageUrlFromDefaultSwatch(context, product) ?? product?.PrimaryImageUrl;\r\n const productPageUrlFromSwatch = getProductPageUrlFromDefaultSwatch(context, productUrl, product) ?? productUrl;\r\n const [productPageUrl, setProductPageUrl] = useState(productPageUrlFromSwatch);\r\n const [productImageUrl, setProductImageUrl] = useState(productImageUrlFromSwatch);\r\n React.useEffect(() => {\r\n setProductPageUrl(productPageUrlFromSwatch);\r\n setProductImageUrl(productImageUrlFromSwatch);\r\n }, [productUrl, productPageUrlFromSwatch, productImageUrlFromSwatch]);\r\n const [selectedSwatchItems] = useState(new Dictionary());\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access -- app context is generic\r\n const enableStockCheck = context.app.config.enableStockCheck;\r\n\r\n const siteContext = context as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n /**\r\n * Updates the product page and Image url based on swatch selected.\r\n * @param coreContext - Context of the caller.\r\n * @param swatchItem - Dimension swatch selected.\r\n */\r\n const updatePageAndImageUrl = React.useCallback(\r\n (coreContext: ICoreContext, swatchItem: ISwatchItem) => {\r\n const dimensionType = swatchItem.dimensionType;\r\n selectedSwatchItems.setValue(dimensionType, swatchItem);\r\n if (StringExtensions.isNullOrWhitespace(swatchItem.value)) {\r\n return;\r\n }\r\n const queryString = `${dimensionType}=${swatchItem.value}`;\r\n let productPageUrlWithSwatch = '';\r\n if (productPageUrl.includes(dimensionType)) {\r\n const newUrl = new URL(productPageUrl, coreContext.request.apiSettings.baseUrl);\r\n newUrl.searchParams.delete(dimensionType);\r\n productPageUrlWithSwatch = updateProductUrl(newUrl.toString(), context, queryString);\r\n } else {\r\n productPageUrlWithSwatch = updateProductUrl(productPageUrl, context, queryString);\r\n }\r\n setProductPageUrl(productPageUrlWithSwatch);\r\n if (dimensionType === dimensionToPreSelectInProductCard) {\r\n const swatchProductImageUrl = ArrayExtensions.hasElements(swatchItem.productImageUrls)\r\n ? swatchItem.productImageUrls[0]\r\n : undefined;\r\n const newImageUrl = generateImageUrl(swatchProductImageUrl, coreContext.request.apiSettings);\r\n setProductImageUrl(newImageUrl);\r\n }\r\n },\r\n [selectedSwatchItems, context, productPageUrl]\r\n );\r\n\r\n if (!product) {\r\n return null;\r\n }\r\n\r\n /**\r\n * Checks if rendering the particular dimensions is allowed for product card.\r\n * @param dimensionType - Dimension to be displayed.\r\n * @returns Updates the state with new product page url.\r\n */\r\n function shouldDisplayDimension(dimensionType: string): boolean {\r\n const dimensionsContext = context as ICoreContext;\r\n const dimensionsToDisplayOnProductCard = dimensionsContext.app.config.dimensionsInProductCard;\r\n return (\r\n ArrayExtensions.hasElements(dimensionsToDisplayOnProductCard) &&\r\n !dimensionsToDisplayOnProductCard.includes(DimensionTypes.none) &&\r\n dimensionsToDisplayOnProductCard.includes(dimensionType.toLocaleLowerCase() as DimensionTypes)\r\n );\r\n }\r\n\r\n /**\r\n * Gets the react node for product dimension as swatch.\r\n * @param attributeValues - Attribute value property from product.\r\n * @returns The node representing markup for unit of measure component.\r\n */\r\n function renderProductDimensions(attributeValues?: AttributeValue[]): JSX.Element | null {\r\n if (!attributeValues) {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n {attributeValues.map((item: AttributeValue) => {\r\n const dimensionTypeValue = item.KeyName?.toLocaleLowerCase() ?? '';\r\n if (!shouldDisplayDimension(dimensionTypeValue)) {\r\n return null;\r\n }\r\n\r\n const siteContext = context as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n const dimensionType = dimensionTypeValue as DimensionTypes;\r\n const swatches =\r\n item.Swatches?.map(swatchItem => {\r\n return {\r\n itemId: `${item.RecordId ?? ''}-${dimensionTypeValue}-${swatchItem.SwatchValue ?? ''}`,\r\n value: swatchItem.SwatchValue ?? '',\r\n dimensionType,\r\n colorHexCode: swatchItem.SwatchColorHexCode,\r\n imageUrl: swatchItem.SwatchImageUrl,\r\n productImageUrls: swatchItem.ProductImageUrls,\r\n isDefault: swatchItem.IsDefault,\r\n swatchItemAriaLabel: swatchItemAriaLabel ? format(swatchItemAriaLabel, dimensionType) : '',\r\n isDisabled:\r\n enableStockCheck &&\r\n dimensionAvailabilities?.find(\r\n dimensionAvailability => dimensionAvailability.value === (swatchItem.SwatchValue ?? '')\r\n )?.isDisabled\r\n };\r\n }) ?? [];\r\n if (\r\n dimensionType === dimensionToPreSelectInProductCard &&\r\n ArrayExtensions.hasElements(swatches) &&\r\n !swatches.some(swatch => swatch.isDefault)\r\n ) {\r\n swatches[0].isDefault = true;\r\n }\r\n return (\r\n \r\n );\r\n })}\r\n
\r\n );\r\n }\r\n\r\n function renderQuickView(quickview: React.ReactNode, item?: number): JSX.Element | undefined {\r\n if (quickview === null) {\r\n return undefined;\r\n }\r\n const selectedDimensions: ProductDimension[] = selectedSwatchItems.getValues().map(swatches => {\r\n return {\r\n DimensionTypeValue: convertDimensionTypeToProductDimensionType(swatches.dimensionType),\r\n DimensionValue: {\r\n RecordId: 0,\r\n Value: swatches.value\r\n }\r\n };\r\n });\r\n return React.cloneElement(quickview as React.ReactElement, { selectedProductId: item, selectedDimensions });\r\n }\r\n\r\n // Construct telemetry attribute to render\r\n const payLoad = getPayloadObject('click', telemetryContent!, '', product.RecordId.toString());\r\n\r\n const attribute = getTelemetryAttributes(telemetryContent!, payLoad);\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- -- Do not need type check for appsettings\r\n const isUnitOfMeasureEnabled = context.app.config && context.app.config.unitOfMeasureDisplayType === 'buyboxAndBrowse';\r\n\r\n const brandName = data.product?.AttributeValues?.find(attribute => attribute.Name === context.app.config.brandNameAttributeName);\r\n const productSize = data.product?.AttributeValues?.find(attribute => attribute.Name === context.app.config.productSizeAttributeName);\r\n const productUnit = data.product?.AttributeValues?.find(attribute => attribute.Name === context.app.config.productUnitAttributeName);\r\n const productNameLength = product.Name?.length && product.Name?.length < 10;\r\n return (\r\n <>\r\n {isEnabledProductDescription ? (\r\n \r\n
\r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n productImageUrl,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n context\r\n )}\r\n
\r\n
\r\n
{product.Name}
\r\n {renderPrice(\r\n context,\r\n typeName,\r\n id,\r\n product.BasePrice,\r\n product.Price,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText,\r\n isPriceMinMaxEnabled,\r\n priceResources\r\n )}\r\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\r\n {renderDescription(product.Description)}\r\n
\r\n
\r\n \r\n ) : (\r\n \r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n productImageUrl,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n context\r\n )}\r\n
\r\n
\r\n
\r\n {brandName?.TextValue}\r\n
{product.Name}
\r\n
\r\n
\r\n {renderPrice(\r\n context,\r\n typeName,\r\n id,\r\n product.BasePrice,\r\n product.Price,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText\r\n )}\r\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\r\n {productSize?.FloatValue} {productUnit?.TextValue}\r\n
\r\n
\r\n \r\n )}\r\n {renderProductDimensions(product.AttributeValues)}\r\n {!context.app.config.hideRating &&\r\n renderRating(context, typeName, id, product.AverageRating, product.TotalRatings, ratingAriaLabel, ratingCountAriaLabel)}\r\n {renderProductAvailability(inventoryLabel)}\r\n {quickViewButton && renderQuickView(quickViewButton, product.RecordId)}\r\n {productComparisonButton && renderProductComparisonButton(productComparisonButton, product, getCatalogId(context.request))}\r\n \r\n );\r\n};\r\n\r\nfunction renderLabel(\r\n name?: string,\r\n price?: string,\r\n rating?: number,\r\n ratingAriaLabelText?: string,\r\n reviewCount?: number,\r\n ratingCountAriaLabelText?: string\r\n): string {\r\n const reviewCountArialableText = getReviewAriaLabel(reviewCount, ratingCountAriaLabelText ?? '');\r\n return `${name ?? ''} ${price ?? ''} ${getRatingAriaLabel(rating, ratingAriaLabelText)}${\r\n reviewCountArialableText ? ` ${reviewCountArialableText}` : ''\r\n }`;\r\n}\r\n\r\nfunction renderDescription(description?: string): JSX.Element | null {\r\n return

{description}

;\r\n}\r\n\r\nfunction getRatingAriaLabel(rating?: number, ratingAriaLabel?: string): string {\r\n if (rating && ratingAriaLabel) {\r\n const roundedRating = rating.toFixed(2);\r\n return format(ratingAriaLabel || '', roundedRating, '5');\r\n }\r\n return '';\r\n}\r\n\r\nfunction getReviewAriaLabel(reviewCount?: number, ratingCountAriaLabelText?: string): string {\r\n if (reviewCount && ratingCountAriaLabelText) {\r\n return format(ratingCountAriaLabelText || '', reviewCount);\r\n }\r\n return '';\r\n}\r\n\r\nfunction renderRating(\r\n coreContext: ICoreContext,\r\n moduleTypeName: string,\r\n moduleId: string,\r\n avgRating?: number,\r\n totalRatings?: number,\r\n ariaLabel?: string,\r\n ratingCountAriaLabel?: string\r\n): JSX.Element | null {\r\n if (!avgRating) {\r\n return null;\r\n }\r\n\r\n const numberRatings = totalRatings?.toString() || undefined;\r\n const ratingAriaLabelText = getRatingAriaLabel(avgRating, ariaLabel);\r\n const ratingCountAriaLabelText = getReviewAriaLabel(Number(numberRatings), ratingCountAriaLabel);\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nfunction renderPrice(\r\n context: ICoreContext,\r\n typeName: string,\r\n id: string,\r\n basePrice?: number,\r\n adjustedPrice?: number,\r\n savingsText?: string,\r\n freePriceText?: string,\r\n originalPriceText?: string,\r\n currentPriceText?: string,\r\n isPriceMinMaxEnabled?: boolean,\r\n priceResources?: IPriceComponentResources\r\n): JSX.Element | null {\r\n const price: ProductPrice = {\r\n BasePrice: basePrice,\r\n AdjustedPrice: adjustedPrice,\r\n CustomerContextualPrice: adjustedPrice\r\n };\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nfunction renderProductPlacementImage(\r\n imageSettings?: IImageSettings,\r\n gridSettings?: IGridSettings,\r\n imageUrl?: string,\r\n fallbackImageUrl?: string,\r\n altText?: string,\r\n context?: ICoreContext>\r\n): JSX.Element | null {\r\n if (!imageUrl || !gridSettings || !imageSettings) {\r\n return null;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- Site level config can be of any type.\r\n const contextConfig = context?.app.config?.placeholderImageName;\r\n const emptyPlaceHolderImage = contextConfig as string;\r\n let fallbackImageSource = fallbackImageUrl;\r\n if (emptyPlaceHolderImage && fallbackImageUrl) {\r\n fallbackImageSource = `${fallbackImageUrl},${emptyPlaceHolderImage}`;\r\n }\r\n const img: IImageData = {\r\n src: imageUrl,\r\n altText: altText ? altText : '',\r\n fallBackSrc: fallbackImageSource\r\n };\r\n const imageProps = {\r\n gridSettings,\r\n imageSettings\r\n };\r\n imageProps.imageSettings.cropFocalRegion = true;\r\n return (\r\n \r\n );\r\n}\r\n\r\nexport const ProductComponent: React.FunctionComponent = msdyn365Commerce.createComponentOverride<\r\n IProductComponent\r\n>('Product', { component: ProductCard, ...PriceComponentActions });\r\n\r\nexport default ProductComponent;\r\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { IProductsDimensionsAvailabilities } from '@msdyn365-commerce/commerce-entities';\r\nimport {\r\n IPriceComponentResources,\r\n ISwatchItem,\r\n PriceComponent,\r\n ProductComponentSwatchComponent,\r\n RatingComponent\r\n} from '@msdyn365-commerce/components';\r\nimport {\r\n getCatalogId,\r\n IAny,\r\n IComponent,\r\n IComponentProps,\r\n ICoreContext,\r\n IGeneric,\r\n IGridSettings,\r\n IImageData,\r\n IImageSettings,\r\n Image,\r\n msdyn365Commerce\r\n} from '@msdyn365-commerce/core';\r\nimport { AttributeSwatch, AttributeValue, ProductDimension, ProductPrice, ProductSearchResult } from '@msdyn365-commerce/retail-proxy';\r\nimport {\r\n ArrayExtensions,\r\n convertDimensionTypeToProductDimensionType,\r\n Dictionary,\r\n DimensionTypes,\r\n generateImageUrl,\r\n getProductPageUrlSync,\r\n IDimensionsApp,\r\n StringExtensions,\r\n validateCatalogId\r\n} from '@msdyn365-commerce-modules/retail-actions';\r\nimport {\r\n format,\r\n getPayloadObject,\r\n getTelemetryAttributes,\r\n ITelemetryContent,\r\n onTelemetryClick\r\n} from '@msdyn365-commerce-modules/utilities';\r\nimport React, { useState } from 'react';\r\n\r\nexport interface IProductComponentProps extends IComponentProps<{ product?: ProductSearchResult }> {\r\n className?: string;\r\n imageSettings?: IImageSettings;\r\n savingsText?: string;\r\n freePriceText?: string;\r\n originalPriceText?: string;\r\n currentPriceText?: string;\r\n ratingAriaLabel?: string;\r\n ratingCountAriaLabel?: string;\r\n allowBack?: boolean;\r\n telemetryContent?: ITelemetryContent;\r\n quickViewButton?: React.ReactNode;\r\n productComparisonButton?: React.ReactNode;\r\n isEnabledProductDescription?: boolean;\r\n isPriceMinMaxEnabled?: boolean;\r\n priceResources?: IPriceComponentResources;\r\n inventoryLabel?: string;\r\n dimensionAvailabilities?: IProductsDimensionsAvailabilities[];\r\n swatchItemAriaLabel?: string;\r\n}\r\n\r\nexport interface IProductComponent extends IComponent {}\r\n\r\nconst PriceComponentActions = {};\r\n\r\n/**\r\n * Gets the product page url from the default swatch selected.\r\n * @param productData - Product card to be rendered.\r\n * @returns The default color swatch selected if any.\r\n */\r\nfunction getDefaultSwatchSelected(coreContext: ICoreContext, productData?: ProductSearchResult): AttributeSwatch | null {\r\n if (!productData || !productData.AttributeValues) {\r\n return null;\r\n }\r\n\r\n const siteContext = coreContext as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n const attributeSwatches = productData.AttributeValues.find(\r\n attributeValue => attributeValue.KeyName?.toLocaleLowerCase() === dimensionToPreSelectInProductCard\r\n )?.Swatches;\r\n\r\n if (!ArrayExtensions.hasElements(attributeSwatches)) {\r\n return null;\r\n }\r\n\r\n const defaultSwatch = attributeSwatches.find(item => item.IsDefault === true) ?? attributeSwatches[0];\r\n return defaultSwatch;\r\n}\r\n\r\n/**\r\n * Gets the product image from the default swatch selected.\r\n * @param coreContext - Context of the module using the component.\r\n * @param productData - Product card to be rendered.\r\n * @returns The product card image url.\r\n */\r\nfunction getProductImageUrlFromDefaultSwatch(coreContext: ICoreContext, productData?: ProductSearchResult): string | undefined {\r\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\r\n const swatchProductImageUrls = defaultSwatch?.ProductImageUrls;\r\n if (!ArrayExtensions.hasElements(swatchProductImageUrls)) {\r\n return productData?.PrimaryImageUrl;\r\n }\r\n\r\n return generateImageUrl(swatchProductImageUrls[0], coreContext.request.apiSettings);\r\n}\r\n\r\n/**\r\n * Updates the product url link to product details page.\r\n * @param productDetailsPageUrl - Product page url.\r\n * @param coreContext - Context of the module using the component.\r\n * @param queryString - Querystring to be added to the URL.\r\n * @returns The update product page url.\r\n */\r\nfunction updateProductUrl(productDetailsPageUrl: string, coreContext: ICoreContext, queryString: string): string {\r\n const sourceUrl = new URL(productDetailsPageUrl, coreContext.request.apiSettings.baseUrl);\r\n if (sourceUrl.search) {\r\n sourceUrl.search += `&${queryString}`;\r\n } else {\r\n sourceUrl.search += queryString;\r\n }\r\n\r\n const updatedUrl = new URL(sourceUrl.href);\r\n return updatedUrl.pathname + sourceUrl.search;\r\n}\r\n\r\n/**\r\n * Gets the react node for product unit of measure display.\r\n * @param unitOfMeasure - DefaultUnitOfMeasure property from product.\r\n * @returns The node representing markup for unit of measure component.\r\n */\r\nfunction renderProductUnitOfMeasure(unitOfMeasure?: string): JSX.Element | null {\r\n if (!unitOfMeasure) {\r\n return null;\r\n }\r\n return (\r\n
\r\n {unitOfMeasure}\r\n
\r\n );\r\n}\r\n\r\n/**\r\n * Gets the react node for product availability.\r\n * @param inventoryAvailabilityLabel - The product information.\r\n * @returns The node representing markup for product availability.\r\n */\r\nfunction renderProductAvailability(inventoryAvailabilityLabel: string | undefined): JSX.Element | null {\r\n if (!inventoryAvailabilityLabel || inventoryAvailabilityLabel === '') {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n {inventoryAvailabilityLabel}\r\n
\r\n );\r\n}\r\n\r\n/**\r\n * Renders product comparison button similar to the quick view button.\r\n * @param productComparisonButton - React element of the button.\r\n * @param product - Current product info.\r\n * @param catalogId - Current catalog.\r\n * @returns React element for the specific product.\r\n */\r\nfunction renderProductComparisonButton(\r\n productComparisonButton: React.ReactNode,\r\n product: ProductSearchResult,\r\n catalogId: number\r\n): JSX.Element | undefined {\r\n validateCatalogId(catalogId);\r\n return React.cloneElement(productComparisonButton as React.ReactElement, { product, catalogId });\r\n}\r\n\r\n/**\r\n * Gets the product page url from the default swatch selected.\r\n * @param coreContext - Context of the module using the component.\r\n * @param productUrl - Product page url for the product card.\r\n * @param productData - Product card to be rendered.\r\n * @returns The product card image url.\r\n */\r\nfunction getProductPageUrlFromDefaultSwatch(\r\n coreContext: ICoreContext,\r\n productUrl: string,\r\n productData?: ProductSearchResult\r\n): string | undefined {\r\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\r\n if (!defaultSwatch?.SwatchValue) {\r\n return productUrl;\r\n }\r\n\r\n const siteContext = coreContext as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n const queryStringEncoded = encodeURIComponent(defaultSwatch.SwatchValue);\r\n const queryString = `${dimensionToPreSelectInProductCard}=${queryStringEncoded}`;\r\n return updateProductUrl(productUrl, coreContext, queryString);\r\n}\r\n\r\nconst ProductCard: React.FC = ({\r\n data,\r\n context,\r\n imageSettings,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText,\r\n ratingAriaLabel,\r\n ratingCountAriaLabel,\r\n allowBack,\r\n typeName,\r\n id,\r\n telemetryContent,\r\n quickViewButton,\r\n productComparisonButton,\r\n isEnabledProductDescription,\r\n isPriceMinMaxEnabled,\r\n priceResources,\r\n inventoryLabel,\r\n dimensionAvailabilities,\r\n swatchItemAriaLabel\r\n}) => {\r\n const product = data.product;\r\n\r\n let productUrl = getProductPageUrlSync(product?.Name ?? '', product?.RecordId ?? Number.MIN_VALUE, context.actionContext, undefined);\r\n if (allowBack) {\r\n productUrl = updateProductUrl(productUrl, context, 'back=true');\r\n }\r\n const productImageUrlFromSwatch = getProductImageUrlFromDefaultSwatch(context, product) ?? product?.PrimaryImageUrl;\r\n const productPageUrlFromSwatch = getProductPageUrlFromDefaultSwatch(context, productUrl, product) ?? productUrl;\r\n const [productPageUrl, setProductPageUrl] = useState(productPageUrlFromSwatch);\r\n const [productImageUrl, setProductImageUrl] = useState(productImageUrlFromSwatch);\r\n React.useEffect(() => {\r\n setProductPageUrl(productPageUrlFromSwatch);\r\n setProductImageUrl(productImageUrlFromSwatch);\r\n }, [productUrl, productPageUrlFromSwatch, productImageUrlFromSwatch]);\r\n const [selectedSwatchItems] = useState(new Dictionary());\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access -- app context is generic\r\n const enableStockCheck = context.app.config.enableStockCheck;\r\n\r\n const siteContext = context as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n /**\r\n * Updates the product page and Image url based on swatch selected.\r\n * @param coreContext - Context of the caller.\r\n * @param swatchItem - Dimension swatch selected.\r\n */\r\n const updatePageAndImageUrl = React.useCallback(\r\n (coreContext: ICoreContext, swatchItem: ISwatchItem) => {\r\n const dimensionType = swatchItem.dimensionType;\r\n selectedSwatchItems.setValue(dimensionType, swatchItem);\r\n if (StringExtensions.isNullOrWhitespace(swatchItem.value)) {\r\n return;\r\n }\r\n const queryString = `${dimensionType}=${swatchItem.value}`;\r\n let productPageUrlWithSwatch = '';\r\n if (productPageUrl.includes(dimensionType)) {\r\n const newUrl = new URL(productPageUrl, coreContext.request.apiSettings.baseUrl);\r\n newUrl.searchParams.delete(dimensionType);\r\n productPageUrlWithSwatch = updateProductUrl(newUrl.toString(), context, queryString);\r\n } else {\r\n productPageUrlWithSwatch = updateProductUrl(productPageUrl, context, queryString);\r\n }\r\n setProductPageUrl(productPageUrlWithSwatch);\r\n if (dimensionType === dimensionToPreSelectInProductCard) {\r\n const swatchProductImageUrl = ArrayExtensions.hasElements(swatchItem.productImageUrls)\r\n ? swatchItem.productImageUrls[0]\r\n : undefined;\r\n const newImageUrl = generateImageUrl(swatchProductImageUrl, coreContext.request.apiSettings);\r\n setProductImageUrl(newImageUrl);\r\n }\r\n },\r\n [selectedSwatchItems, context, productPageUrl]\r\n );\r\n\r\n if (!product) {\r\n return null;\r\n }\r\n\r\n /**\r\n * Checks if rendering the particular dimensions is allowed for product card.\r\n * @param dimensionType - Dimension to be displayed.\r\n * @returns Updates the state with new product page url.\r\n */\r\n function shouldDisplayDimension(dimensionType: string): boolean {\r\n const dimensionsContext = context as ICoreContext;\r\n const dimensionsToDisplayOnProductCard = dimensionsContext.app.config.dimensionsInProductCard;\r\n return (\r\n ArrayExtensions.hasElements(dimensionsToDisplayOnProductCard) &&\r\n !dimensionsToDisplayOnProductCard.includes(DimensionTypes.none) &&\r\n dimensionsToDisplayOnProductCard.includes(dimensionType.toLocaleLowerCase() as DimensionTypes)\r\n );\r\n }\r\n\r\n /**\r\n * Gets the react node for product dimension as swatch.\r\n * @param attributeValues - Attribute value property from product.\r\n * @returns The node representing markup for unit of measure component.\r\n */\r\n function renderProductDimensions(attributeValues?: AttributeValue[]): JSX.Element | null {\r\n if (!attributeValues) {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n {attributeValues.map((item: AttributeValue) => {\r\n const dimensionTypeValue = item.KeyName?.toLocaleLowerCase() ?? '';\r\n if (!shouldDisplayDimension(dimensionTypeValue)) {\r\n return null;\r\n }\r\n\r\n const siteContext = context as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n const dimensionType = dimensionTypeValue as DimensionTypes;\r\n const swatches =\r\n item.Swatches?.map(swatchItem => {\r\n return {\r\n itemId: `${item.RecordId ?? ''}-${dimensionTypeValue}-${swatchItem.SwatchValue ?? ''}`,\r\n value: swatchItem.SwatchValue ?? '',\r\n dimensionType,\r\n colorHexCode: swatchItem.SwatchColorHexCode,\r\n imageUrl: swatchItem.SwatchImageUrl,\r\n productImageUrls: swatchItem.ProductImageUrls,\r\n isDefault: swatchItem.IsDefault,\r\n swatchItemAriaLabel: swatchItemAriaLabel ? format(swatchItemAriaLabel, dimensionType) : '',\r\n isDisabled:\r\n enableStockCheck &&\r\n dimensionAvailabilities?.find(\r\n dimensionAvailability => dimensionAvailability.value === (swatchItem.SwatchValue ?? '')\r\n )?.isDisabled\r\n };\r\n }) ?? [];\r\n if (\r\n dimensionType === dimensionToPreSelectInProductCard &&\r\n ArrayExtensions.hasElements(swatches) &&\r\n !swatches.some(swatch => swatch.isDefault)\r\n ) {\r\n swatches[0].isDefault = true;\r\n }\r\n return (\r\n \r\n );\r\n })}\r\n
\r\n );\r\n }\r\n\r\n function renderQuickView(quickview: React.ReactNode, item?: number): JSX.Element | undefined {\r\n if (quickview === null) {\r\n return undefined;\r\n }\r\n const selectedDimensions: ProductDimension[] = selectedSwatchItems.getValues().map(swatches => {\r\n return {\r\n DimensionTypeValue: convertDimensionTypeToProductDimensionType(swatches.dimensionType),\r\n DimensionValue: {\r\n RecordId: 0,\r\n Value: swatches.value\r\n }\r\n };\r\n });\r\n return React.cloneElement(quickview as React.ReactElement, { selectedProductId: item, selectedDimensions });\r\n }\r\n\r\n // Construct telemetry attribute to render\r\n const payLoad = getPayloadObject('click', telemetryContent!, '', product.RecordId.toString());\r\n\r\n const attribute = getTelemetryAttributes(telemetryContent!, payLoad);\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- -- Do not need type check for appsettings\r\n const isUnitOfMeasureEnabled = context.app.config && context.app.config.unitOfMeasureDisplayType === 'buyboxAndBrowse';\r\n\r\n const brandName = data.product?.AttributeValues?.find(attribute => attribute.RecordId === context.app.config.brandNameAttributeRecordId);\r\n const productSize = data.product?.AttributeValues?.find(attribute => attribute.RecordId === context.app.config.productSizeAttributeRecordId);\r\n const productUnit = data.product?.AttributeValues?.find(attribute => attribute.RecordId === context.app.config.productUnitAttributeRecordId);\r\n const productNameLength = product.Name?.length && product.Name?.length < 10;\r\n return (\r\n <>\r\n {isEnabledProductDescription ? (\r\n \r\n
\r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n productImageUrl,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n context\r\n )}\r\n
\r\n
\r\n
{product.Name}
\r\n {renderPrice(\r\n context,\r\n typeName,\r\n id,\r\n product.BasePrice,\r\n product.Price,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText,\r\n isPriceMinMaxEnabled,\r\n priceResources\r\n )}\r\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\r\n {renderDescription(product.Description)}\r\n
\r\n
\r\n \r\n ) : (\r\n \r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n productImageUrl,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n context\r\n )}\r\n
\r\n
\r\n
\r\n {brandName?.TextValue}\r\n
{product.Name}
\r\n
\r\n
\r\n {renderPrice(\r\n context,\r\n typeName,\r\n id,\r\n product.BasePrice,\r\n product.Price,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText\r\n )}\r\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\r\n {productSize?.FloatValue} {productUnit?.TextValue}\r\n
\r\n
\r\n \r\n )}\r\n {renderProductDimensions(product.AttributeValues)}\r\n {!context.app.config.hideRating &&\r\n renderRating(context, typeName, id, product.AverageRating, product.TotalRatings, ratingAriaLabel, ratingCountAriaLabel)}\r\n {renderProductAvailability(inventoryLabel)}\r\n {quickViewButton && renderQuickView(quickViewButton, product.RecordId)}\r\n {productComparisonButton && renderProductComparisonButton(productComparisonButton, product, getCatalogId(context.request))}\r\n \r\n );\r\n};\r\n\r\nfunction renderLabel(\r\n name?: string,\r\n price?: string,\r\n rating?: number,\r\n ratingAriaLabelText?: string,\r\n reviewCount?: number,\r\n ratingCountAriaLabelText?: string\r\n): string {\r\n const reviewCountArialableText = getReviewAriaLabel(reviewCount, ratingCountAriaLabelText ?? '');\r\n return `${name ?? ''} ${price ?? ''} ${getRatingAriaLabel(rating, ratingAriaLabelText)}${\r\n reviewCountArialableText ? ` ${reviewCountArialableText}` : ''\r\n }`;\r\n}\r\n\r\nfunction renderDescription(description?: string): JSX.Element | null {\r\n return

{description}

;\r\n}\r\n\r\nfunction getRatingAriaLabel(rating?: number, ratingAriaLabel?: string): string {\r\n if (rating && ratingAriaLabel) {\r\n const roundedRating = rating.toFixed(2);\r\n return format(ratingAriaLabel || '', roundedRating, '5');\r\n }\r\n return '';\r\n}\r\n\r\nfunction getReviewAriaLabel(reviewCount?: number, ratingCountAriaLabelText?: string): string {\r\n if (reviewCount && ratingCountAriaLabelText) {\r\n return format(ratingCountAriaLabelText || '', reviewCount);\r\n }\r\n return '';\r\n}\r\n\r\nfunction renderRating(\r\n coreContext: ICoreContext,\r\n moduleTypeName: string,\r\n moduleId: string,\r\n avgRating?: number,\r\n totalRatings?: number,\r\n ariaLabel?: string,\r\n ratingCountAriaLabel?: string\r\n): JSX.Element | null {\r\n if (!avgRating) {\r\n return null;\r\n }\r\n\r\n const numberRatings = totalRatings?.toString() || undefined;\r\n const ratingAriaLabelText = getRatingAriaLabel(avgRating, ariaLabel);\r\n const ratingCountAriaLabelText = getReviewAriaLabel(Number(numberRatings), ratingCountAriaLabel);\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nfunction renderPrice(\r\n context: ICoreContext,\r\n typeName: string,\r\n id: string,\r\n basePrice?: number,\r\n adjustedPrice?: number,\r\n savingsText?: string,\r\n freePriceText?: string,\r\n originalPriceText?: string,\r\n currentPriceText?: string,\r\n isPriceMinMaxEnabled?: boolean,\r\n priceResources?: IPriceComponentResources\r\n): JSX.Element | null {\r\n const price: ProductPrice = {\r\n BasePrice: basePrice,\r\n AdjustedPrice: adjustedPrice,\r\n CustomerContextualPrice: adjustedPrice\r\n };\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nfunction renderProductPlacementImage(\r\n imageSettings?: IImageSettings,\r\n gridSettings?: IGridSettings,\r\n imageUrl?: string,\r\n fallbackImageUrl?: string,\r\n altText?: string,\r\n context?: ICoreContext>\r\n): JSX.Element | null {\r\n if (!imageUrl || !gridSettings || !imageSettings) {\r\n return null;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- Site level config can be of any type.\r\n const contextConfig = context?.app.config?.placeholderImageName;\r\n const emptyPlaceHolderImage = contextConfig as string;\r\n let fallbackImageSource = fallbackImageUrl;\r\n if (emptyPlaceHolderImage && fallbackImageUrl) {\r\n fallbackImageSource = `${fallbackImageUrl},${emptyPlaceHolderImage}`;\r\n }\r\n const img: IImageData = {\r\n src: imageUrl,\r\n altText: altText ? altText : '',\r\n fallBackSrc: fallbackImageSource\r\n };\r\n const imageProps = {\r\n gridSettings,\r\n imageSettings\r\n };\r\n imageProps.imageSettings.cropFocalRegion = true;\r\n return (\r\n \r\n );\r\n}\r\n\r\nexport const ProductComponent: React.FunctionComponent = msdyn365Commerce.createComponentOverride<\r\n IProductComponent\r\n>('Product', { component: ProductCard, ...PriceComponentActions });\r\n\r\nexport default ProductComponent;\r\n","/*!\n * Copyright (c) Microsoft Corporation.\n * All rights reserved. See LICENSE in the project root for license information.\n */\n\nimport { IProductsDimensionsAvailabilities } from '@msdyn365-commerce/commerce-entities';\nimport {\n IPriceComponentResources,\n ISwatchItem,\n PriceComponent,\n ProductComponentSwatchComponent,\n RatingComponent\n} from '@msdyn365-commerce/components';\nimport {\n getCatalogId,\n IAny,\n IComponent,\n IComponentProps,\n ICoreContext,\n IGeneric,\n IGridSettings,\n IImageData,\n IImageSettings,\n Image,\n msdyn365Commerce\n} from '@msdyn365-commerce/core';\nimport { AttributeSwatch, AttributeValue, ProductDimension, ProductPrice, ProductSearchResult } from '@msdyn365-commerce/retail-proxy';\nimport {\n ArrayExtensions,\n convertDimensionTypeToProductDimensionType,\n Dictionary,\n DimensionTypes,\n generateImageUrl,\n getProductPageUrlSync,\n IDimensionsApp,\n StringExtensions,\n validateCatalogId\n} from '@msdyn365-commerce-modules/retail-actions';\nimport {\n format,\n getPayloadObject,\n getTelemetryAttributes,\n ITelemetryContent,\n onTelemetryClick\n} from '@msdyn365-commerce-modules/utilities';\nimport React, { useState } from 'react';\n\nexport interface IProductComponentProps extends IComponentProps<{ product?: ProductSearchResult }> {\n className?: string;\n imageSettings?: IImageSettings;\n savingsText?: string;\n freePriceText?: string;\n originalPriceText?: string;\n currentPriceText?: string;\n ratingAriaLabel?: string;\n ratingCountAriaLabel?: string;\n allowBack?: boolean;\n telemetryContent?: ITelemetryContent;\n quickViewButton?: React.ReactNode;\n productComparisonButton?: React.ReactNode;\n isEnabledProductDescription?: boolean;\n isPriceMinMaxEnabled?: boolean;\n priceResources?: IPriceComponentResources;\n inventoryLabel?: string;\n dimensionAvailabilities?: IProductsDimensionsAvailabilities[];\n swatchItemAriaLabel?: string;\n}\n\nexport interface IProductComponent extends IComponent {}\n\nconst PriceComponentActions = {};\n\n/**\n * Gets the product page url from the default swatch selected.\n * @param productData - Product card to be rendered.\n * @returns The default color swatch selected if any.\n */\nfunction getDefaultSwatchSelected(coreContext: ICoreContext, productData?: ProductSearchResult): AttributeSwatch | null {\n if (!productData || !productData.AttributeValues) {\n return null;\n }\n\n const siteContext = coreContext as ICoreContext;\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\n\n const attributeSwatches = productData.AttributeValues.find(\n attributeValue => attributeValue.KeyName?.toLocaleLowerCase() === dimensionToPreSelectInProductCard\n )?.Swatches;\n\n if (!ArrayExtensions.hasElements(attributeSwatches)) {\n return null;\n }\n\n const defaultSwatch = attributeSwatches.find(item => item.IsDefault === true) ?? attributeSwatches[0];\n return defaultSwatch;\n}\n\n/**\n * Gets the product image from the default swatch selected.\n * @param coreContext - Context of the module using the component.\n * @param productData - Product card to be rendered.\n * @returns The product card image url.\n */\nfunction getProductImageUrlFromDefaultSwatch(coreContext: ICoreContext, productData?: ProductSearchResult): string | undefined {\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\n const swatchProductImageUrls = defaultSwatch?.ProductImageUrls;\n if (!ArrayExtensions.hasElements(swatchProductImageUrls)) {\n return productData?.PrimaryImageUrl;\n }\n\n return generateImageUrl(swatchProductImageUrls[0], coreContext.request.apiSettings);\n}\n\n/**\n * Updates the product url link to product details page.\n * @param productDetailsPageUrl - Product page url.\n * @param coreContext - Context of the module using the component.\n * @param queryString - Querystring to be added to the URL.\n * @returns The update product page url.\n */\nfunction updateProductUrl(productDetailsPageUrl: string, coreContext: ICoreContext, queryString: string): string {\n const sourceUrl = new URL(productDetailsPageUrl, coreContext.request.apiSettings.baseUrl);\n if (sourceUrl.search) {\n sourceUrl.search += `&${queryString}`;\n } else {\n sourceUrl.search += queryString;\n }\n\n const updatedUrl = new URL(sourceUrl.href);\n return updatedUrl.pathname + sourceUrl.search;\n}\n\n/**\n * Gets the react node for product unit of measure display.\n * @param unitOfMeasure - DefaultUnitOfMeasure property from product.\n * @returns The node representing markup for unit of measure component.\n */\nfunction renderProductUnitOfMeasure(unitOfMeasure?: string): JSX.Element | null {\n if (!unitOfMeasure) {\n return null;\n }\n return (\n
\n {unitOfMeasure}\n
\n );\n}\n\n/**\n * Gets the react node for product availability.\n * @param inventoryAvailabilityLabel - The product information.\n * @returns The node representing markup for product availability.\n */\nfunction renderProductAvailability(inventoryAvailabilityLabel: string | undefined): JSX.Element | null {\n if (!inventoryAvailabilityLabel || inventoryAvailabilityLabel === '') {\n return null;\n }\n\n return (\n
\n {inventoryAvailabilityLabel}\n
\n );\n}\n\n/**\n * Renders product comparison button similar to the quick view button.\n * @param productComparisonButton - React element of the button.\n * @param product - Current product info.\n * @param catalogId - Current catalog.\n * @returns React element for the specific product.\n */\nfunction renderProductComparisonButton(\n productComparisonButton: React.ReactNode,\n product: ProductSearchResult,\n catalogId: number\n): JSX.Element | undefined {\n validateCatalogId(catalogId);\n return React.cloneElement(productComparisonButton as React.ReactElement, { product, catalogId });\n}\n\n/**\n * Gets the product page url from the default swatch selected.\n * @param coreContext - Context of the module using the component.\n * @param productUrl - Product page url for the product card.\n * @param productData - Product card to be rendered.\n * @returns The product card image url.\n */\nfunction getProductPageUrlFromDefaultSwatch(\n coreContext: ICoreContext,\n productUrl: string,\n productData?: ProductSearchResult\n): string | undefined {\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\n if (!defaultSwatch?.SwatchValue) {\n return productUrl;\n }\n\n const siteContext = coreContext as ICoreContext;\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\n\n const queryStringEncoded = encodeURIComponent(defaultSwatch.SwatchValue);\n const queryString = `${dimensionToPreSelectInProductCard}=${queryStringEncoded}`;\n return updateProductUrl(productUrl, coreContext, queryString);\n}\n\nconst ProductCard: React.FC = ({\n data,\n context,\n imageSettings,\n savingsText,\n freePriceText,\n originalPriceText,\n currentPriceText,\n ratingAriaLabel,\n ratingCountAriaLabel,\n allowBack,\n typeName,\n id,\n telemetryContent,\n quickViewButton,\n productComparisonButton,\n isEnabledProductDescription,\n isPriceMinMaxEnabled,\n priceResources,\n inventoryLabel,\n dimensionAvailabilities,\n swatchItemAriaLabel\n}) => {\n const product = data.product;\n\n let productUrl = getProductPageUrlSync(product?.Name ?? '', product?.RecordId ?? Number.MIN_VALUE, context.actionContext, undefined);\n if (allowBack) {\n productUrl = updateProductUrl(productUrl, context, 'back=true');\n }\n const productImageUrlFromSwatch = getProductImageUrlFromDefaultSwatch(context, product) ?? product?.PrimaryImageUrl;\n const productPageUrlFromSwatch = getProductPageUrlFromDefaultSwatch(context, productUrl, product) ?? productUrl;\n const [productPageUrl, setProductPageUrl] = useState(productPageUrlFromSwatch);\n const [productImageUrl, setProductImageUrl] = useState(productImageUrlFromSwatch);\n React.useEffect(() => {\n setProductPageUrl(productPageUrlFromSwatch);\n setProductImageUrl(productImageUrlFromSwatch);\n }, [productUrl, productPageUrlFromSwatch, productImageUrlFromSwatch]);\n const [selectedSwatchItems] = useState(new Dictionary());\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access -- app context is generic\n const enableStockCheck = context.app.config.enableStockCheck;\n\n const siteContext = context as ICoreContext;\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\n\n /**\n * Updates the product page and Image url based on swatch selected.\n * @param coreContext - Context of the caller.\n * @param swatchItem - Dimension swatch selected.\n */\n const updatePageAndImageUrl = React.useCallback(\n (coreContext: ICoreContext, swatchItem: ISwatchItem) => {\n const dimensionType = swatchItem.dimensionType;\n selectedSwatchItems.setValue(dimensionType, swatchItem);\n if (StringExtensions.isNullOrWhitespace(swatchItem.value)) {\n return;\n }\n const queryString = `${dimensionType}=${swatchItem.value}`;\n let productPageUrlWithSwatch = '';\n if (productPageUrl.includes(dimensionType)) {\n const newUrl = new URL(productPageUrl, coreContext.request.apiSettings.baseUrl);\n newUrl.searchParams.delete(dimensionType);\n productPageUrlWithSwatch = updateProductUrl(newUrl.toString(), context, queryString);\n } else {\n productPageUrlWithSwatch = updateProductUrl(productPageUrl, context, queryString);\n }\n setProductPageUrl(productPageUrlWithSwatch);\n if (dimensionType === dimensionToPreSelectInProductCard) {\n const swatchProductImageUrl = ArrayExtensions.hasElements(swatchItem.productImageUrls)\n ? swatchItem.productImageUrls[0]\n : undefined;\n const newImageUrl = generateImageUrl(swatchProductImageUrl, coreContext.request.apiSettings);\n setProductImageUrl(newImageUrl);\n }\n },\n [selectedSwatchItems, context, productPageUrl]\n );\n\n if (!product) {\n return null;\n }\n\n /**\n * Checks if rendering the particular dimensions is allowed for product card.\n * @param dimensionType - Dimension to be displayed.\n * @returns Updates the state with new product page url.\n */\n function shouldDisplayDimension(dimensionType: string): boolean {\n const dimensionsContext = context as ICoreContext;\n const dimensionsToDisplayOnProductCard = dimensionsContext.app.config.dimensionsInProductCard;\n return (\n ArrayExtensions.hasElements(dimensionsToDisplayOnProductCard) &&\n !dimensionsToDisplayOnProductCard.includes(DimensionTypes.none) &&\n dimensionsToDisplayOnProductCard.includes(dimensionType.toLocaleLowerCase() as DimensionTypes)\n );\n }\n\n /**\n * Gets the react node for product dimension as swatch.\n * @param attributeValues - Attribute value property from product.\n * @returns The node representing markup for unit of measure component.\n */\n function renderProductDimensions(attributeValues?: AttributeValue[]): JSX.Element | null {\n if (!attributeValues) {\n return null;\n }\n\n return (\n
\n {attributeValues.map((item: AttributeValue) => {\n const dimensionTypeValue = item.KeyName?.toLocaleLowerCase() ?? '';\n if (!shouldDisplayDimension(dimensionTypeValue)) {\n return null;\n }\n\n const siteContext = context as ICoreContext;\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\n const dimensionType = dimensionTypeValue as DimensionTypes;\n const swatches =\n item.Swatches?.map(swatchItem => {\n return {\n itemId: `${item.RecordId ?? ''}-${dimensionTypeValue}-${swatchItem.SwatchValue ?? ''}`,\n value: swatchItem.SwatchValue ?? '',\n dimensionType,\n colorHexCode: swatchItem.SwatchColorHexCode,\n imageUrl: swatchItem.SwatchImageUrl,\n productImageUrls: swatchItem.ProductImageUrls,\n isDefault: swatchItem.IsDefault,\n swatchItemAriaLabel: swatchItemAriaLabel ? format(swatchItemAriaLabel, dimensionType) : '',\n isDisabled:\n enableStockCheck &&\n dimensionAvailabilities?.find(\n dimensionAvailability => dimensionAvailability.value === (swatchItem.SwatchValue ?? '')\n )?.isDisabled\n };\n }) ?? [];\n if (\n dimensionType === dimensionToPreSelectInProductCard &&\n ArrayExtensions.hasElements(swatches) &&\n !swatches.some(swatch => swatch.isDefault)\n ) {\n swatches[0].isDefault = true;\n }\n return (\n \n );\n })}\n
\n );\n }\n\n function renderQuickView(quickview: React.ReactNode, item?: number): JSX.Element | undefined {\n if (quickview === null) {\n return undefined;\n }\n const selectedDimensions: ProductDimension[] = selectedSwatchItems.getValues().map(swatches => {\n return {\n DimensionTypeValue: convertDimensionTypeToProductDimensionType(swatches.dimensionType),\n DimensionValue: {\n RecordId: 0,\n Value: swatches.value\n }\n };\n });\n return React.cloneElement(quickview as React.ReactElement, { selectedProductId: item, selectedDimensions });\n }\n\n // Construct telemetry attribute to render\n const payLoad = getPayloadObject('click', telemetryContent!, '', product.RecordId.toString());\n\n const attribute = getTelemetryAttributes(telemetryContent!, payLoad);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- -- Do not need type check for appsettings\n const isUnitOfMeasureEnabled = context.app.config && context.app.config.unitOfMeasureDisplayType === 'buyboxAndBrowse';\n\n return (\n <>\n {isEnabledProductDescription ? (\n \n
\n
\n {renderProductPlacementImage(\n imageSettings,\n context.request.gridSettings,\n productImageUrl,\n product.PrimaryImageUrl,\n product.Name,\n context\n )}\n
\n
\n
{product.Name}
\n {renderPrice(\n context,\n typeName,\n id,\n product.BasePrice,\n product.Price,\n savingsText,\n freePriceText,\n originalPriceText,\n currentPriceText,\n isPriceMinMaxEnabled,\n priceResources\n )}\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\n {renderDescription(product.Description)}\n
\n
\n \n ) : (\n \n
\n {renderProductPlacementImage(\n imageSettings,\n context.request.gridSettings,\n productImageUrl,\n product.PrimaryImageUrl,\n product.Name,\n context\n )}\n
\n
\n
{product.Name}
\n {renderPrice(\n context,\n typeName,\n id,\n product.BasePrice,\n product.Price,\n savingsText,\n freePriceText,\n originalPriceText,\n currentPriceText\n )}\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\n
\n \n )}\n {renderProductDimensions(product.AttributeValues)}\n {!context.app.config.hideRating &&\n renderRating(context, typeName, id, product.AverageRating, product.TotalRatings, ratingAriaLabel, ratingCountAriaLabel)}\n {renderProductAvailability(inventoryLabel)}\n {quickViewButton && renderQuickView(quickViewButton, product.RecordId)}\n {productComparisonButton && renderProductComparisonButton(productComparisonButton, product, getCatalogId(context.request))}\n \n );\n};\n\nfunction renderLabel(\n name?: string,\n price?: string,\n rating?: number,\n ratingAriaLabelText?: string,\n reviewCount?: number,\n ratingCountAriaLabelText?: string\n): string {\n const reviewCountArialableText = getReviewAriaLabel(reviewCount, ratingCountAriaLabelText ?? '');\n return `${name ?? ''} ${price ?? ''} ${getRatingAriaLabel(rating, ratingAriaLabelText)}${\n reviewCountArialableText ? ` ${reviewCountArialableText}` : ''\n }`;\n}\n\nfunction renderDescription(description?: string): JSX.Element | null {\n return

{description}

;\n}\n\nfunction getRatingAriaLabel(rating?: number, ratingAriaLabel?: string): string {\n if (rating && ratingAriaLabel) {\n const roundedRating = rating.toFixed(2);\n return format(ratingAriaLabel || '', roundedRating, '5');\n }\n return '';\n}\n\nfunction getReviewAriaLabel(reviewCount?: number, ratingCountAriaLabelText?: string): string {\n if (reviewCount && ratingCountAriaLabelText) {\n return format(ratingCountAriaLabelText || '', reviewCount);\n }\n return '';\n}\n\nfunction renderRating(\n coreContext: ICoreContext,\n moduleTypeName: string,\n moduleId: string,\n avgRating?: number,\n totalRatings?: number,\n ariaLabel?: string,\n ratingCountAriaLabel?: string\n): JSX.Element | null {\n if (!avgRating) {\n return null;\n }\n\n const numberRatings = totalRatings?.toString() || undefined;\n const ratingAriaLabelText = getRatingAriaLabel(avgRating, ariaLabel);\n const ratingCountAriaLabelText = getReviewAriaLabel(Number(numberRatings), ratingCountAriaLabel);\n\n return (\n \n );\n}\n\nfunction renderPrice(\n context: ICoreContext,\n typeName: string,\n id: string,\n basePrice?: number,\n adjustedPrice?: number,\n savingsText?: string,\n freePriceText?: string,\n originalPriceText?: string,\n currentPriceText?: string,\n isPriceMinMaxEnabled?: boolean,\n priceResources?: IPriceComponentResources\n): JSX.Element | null {\n const price: ProductPrice = {\n BasePrice: basePrice,\n AdjustedPrice: adjustedPrice,\n CustomerContextualPrice: adjustedPrice\n };\n\n return (\n \n );\n}\n\nfunction renderProductPlacementImage(\n imageSettings?: IImageSettings,\n gridSettings?: IGridSettings,\n imageUrl?: string,\n fallbackImageUrl?: string,\n altText?: string,\n context?: ICoreContext>\n): JSX.Element | null {\n if (!imageUrl || !gridSettings || !imageSettings) {\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- Site level config can be of any type.\n const contextConfig = context?.app.config?.placeholderImageName;\n const emptyPlaceHolderImage = contextConfig as string;\n let fallbackImageSource = fallbackImageUrl;\n if (emptyPlaceHolderImage && fallbackImageUrl) {\n fallbackImageSource = `${fallbackImageUrl},${emptyPlaceHolderImage}`;\n }\n const img: IImageData = {\n src: imageUrl,\n altText: altText ? altText : '',\n fallBackSrc: fallbackImageSource\n };\n const imageProps = {\n gridSettings,\n imageSettings\n };\n imageProps.imageSettings.cropFocalRegion = true;\n return (\n \n );\n}\n\nexport const ProductComponent: React.FunctionComponent = msdyn365Commerce.createComponentOverride<\n IProductComponent\n>('Product', { component: ProductCard, ...PriceComponentActions });\n\nexport default ProductComponent;\n","/*!\r\n * Copyright (c) Microsoft Corporation.\r\n * All rights reserved. See LICENSE in the project root for license information.\r\n */\r\n\r\nimport { IProductsDimensionsAvailabilities } from '@msdyn365-commerce/commerce-entities';\r\nimport {\r\n IPriceComponentResources,\r\n ISwatchItem,\r\n PriceComponent,\r\n ProductComponentSwatchComponent,\r\n RatingComponent\r\n} from '@msdyn365-commerce/components';\r\nimport {\r\n getCatalogId,\r\n IAny,\r\n IComponent,\r\n IComponentProps,\r\n ICoreContext,\r\n IGeneric,\r\n IGridSettings,\r\n IImageData,\r\n IImageSettings,\r\n Image,\r\n msdyn365Commerce\r\n} from '@msdyn365-commerce/core';\r\nimport { AttributeSwatch, AttributeValue, ProductDimension, ProductPrice, ProductSearchResult } from '@msdyn365-commerce/retail-proxy';\r\nimport {\r\n ArrayExtensions,\r\n convertDimensionTypeToProductDimensionType,\r\n Dictionary,\r\n DimensionTypes,\r\n generateImageUrl,\r\n getProductPageUrlSync,\r\n IDimensionsApp,\r\n StringExtensions,\r\n validateCatalogId\r\n} from '@msdyn365-commerce-modules/retail-actions';\r\nimport {\r\n format,\r\n getPayloadObject,\r\n getTelemetryAttributes,\r\n ITelemetryContent,\r\n onTelemetryClick\r\n} from '@msdyn365-commerce-modules/utilities';\r\nimport React, { useState } from 'react';\r\n\r\nexport interface IProductComponentProps extends IComponentProps<{ product?: ProductSearchResult }> {\r\n className?: string;\r\n imageSettings?: IImageSettings;\r\n savingsText?: string;\r\n freePriceText?: string;\r\n originalPriceText?: string;\r\n currentPriceText?: string;\r\n ratingAriaLabel?: string;\r\n ratingCountAriaLabel?: string;\r\n allowBack?: boolean;\r\n telemetryContent?: ITelemetryContent;\r\n quickViewButton?: React.ReactNode;\r\n productComparisonButton?: React.ReactNode;\r\n isEnabledProductDescription?: boolean;\r\n isPriceMinMaxEnabled?: boolean;\r\n priceResources?: IPriceComponentResources;\r\n inventoryLabel?: string;\r\n dimensionAvailabilities?: IProductsDimensionsAvailabilities[];\r\n swatchItemAriaLabel?: string;\r\n}\r\n\r\nexport interface IProductComponent extends IComponent {}\r\n\r\nconst PriceComponentActions = {};\r\n\r\n/**\r\n * Gets the product page url from the default swatch selected.\r\n * @param productData - Product card to be rendered.\r\n * @returns The default color swatch selected if any.\r\n */\r\nfunction getDefaultSwatchSelected(coreContext: ICoreContext, productData?: ProductSearchResult): AttributeSwatch | null {\r\n if (!productData || !productData.AttributeValues) {\r\n return null;\r\n }\r\n\r\n const siteContext = coreContext as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n const attributeSwatches = productData.AttributeValues.find(\r\n attributeValue => attributeValue.KeyName?.toLocaleLowerCase() === dimensionToPreSelectInProductCard\r\n )?.Swatches;\r\n\r\n if (!ArrayExtensions.hasElements(attributeSwatches)) {\r\n return null;\r\n }\r\n\r\n const defaultSwatch = attributeSwatches.find(item => item.IsDefault === true) ?? attributeSwatches[0];\r\n return defaultSwatch;\r\n}\r\n\r\n/**\r\n * Gets the product image from the default swatch selected.\r\n * @param coreContext - Context of the module using the component.\r\n * @param productData - Product card to be rendered.\r\n * @returns The product card image url.\r\n */\r\nfunction getProductImageUrlFromDefaultSwatch(coreContext: ICoreContext, productData?: ProductSearchResult): string | undefined {\r\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\r\n const swatchProductImageUrls = defaultSwatch?.ProductImageUrls;\r\n if (!ArrayExtensions.hasElements(swatchProductImageUrls)) {\r\n return productData?.PrimaryImageUrl;\r\n }\r\n\r\n return generateImageUrl(swatchProductImageUrls[0], coreContext.request.apiSettings);\r\n}\r\n\r\n/**\r\n * Updates the product url link to product details page.\r\n * @param productDetailsPageUrl - Product page url.\r\n * @param coreContext - Context of the module using the component.\r\n * @param queryString - Querystring to be added to the URL.\r\n * @returns The update product page url.\r\n */\r\nfunction updateProductUrl(productDetailsPageUrl: string, coreContext: ICoreContext, queryString: string): string {\r\n const sourceUrl = new URL(productDetailsPageUrl, coreContext.request.apiSettings.baseUrl);\r\n if (sourceUrl.search) {\r\n sourceUrl.search += `&${queryString}`;\r\n } else {\r\n sourceUrl.search += queryString;\r\n }\r\n\r\n const updatedUrl = new URL(sourceUrl.href);\r\n return updatedUrl.pathname + sourceUrl.search;\r\n}\r\n\r\n/**\r\n * Gets the react node for product unit of measure display.\r\n * @param unitOfMeasure - DefaultUnitOfMeasure property from product.\r\n * @returns The node representing markup for unit of measure component.\r\n */\r\nfunction renderProductUnitOfMeasure(unitOfMeasure?: string): JSX.Element | null {\r\n if (!unitOfMeasure) {\r\n return null;\r\n }\r\n return (\r\n
\r\n {unitOfMeasure}\r\n
\r\n );\r\n}\r\n\r\n/**\r\n * Gets the react node for product availability.\r\n * @param inventoryAvailabilityLabel - The product information.\r\n * @returns The node representing markup for product availability.\r\n */\r\nfunction renderProductAvailability(inventoryAvailabilityLabel: string | undefined): JSX.Element | null {\r\n if (!inventoryAvailabilityLabel || inventoryAvailabilityLabel === '') {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n {inventoryAvailabilityLabel}\r\n
\r\n );\r\n}\r\n\r\n/**\r\n * Renders product comparison button similar to the quick view button.\r\n * @param productComparisonButton - React element of the button.\r\n * @param product - Current product info.\r\n * @param catalogId - Current catalog.\r\n * @returns React element for the specific product.\r\n */\r\nfunction renderProductComparisonButton(\r\n productComparisonButton: React.ReactNode,\r\n product: ProductSearchResult,\r\n catalogId: number\r\n): JSX.Element | undefined {\r\n validateCatalogId(catalogId);\r\n return React.cloneElement(productComparisonButton as React.ReactElement, { product, catalogId });\r\n}\r\n\r\n/**\r\n * Gets the product page url from the default swatch selected.\r\n * @param coreContext - Context of the module using the component.\r\n * @param productUrl - Product page url for the product card.\r\n * @param productData - Product card to be rendered.\r\n * @returns The product card image url.\r\n */\r\nfunction getProductPageUrlFromDefaultSwatch(\r\n coreContext: ICoreContext,\r\n productUrl: string,\r\n productData?: ProductSearchResult\r\n): string | undefined {\r\n const defaultSwatch = getDefaultSwatchSelected(coreContext, productData);\r\n if (!defaultSwatch?.SwatchValue) {\r\n return productUrl;\r\n }\r\n\r\n const siteContext = coreContext as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n const queryStringEncoded = encodeURIComponent(defaultSwatch.SwatchValue);\r\n const queryString = `${dimensionToPreSelectInProductCard}=${queryStringEncoded}`;\r\n return updateProductUrl(productUrl, coreContext, queryString);\r\n}\r\n\r\nconst ProductCard: React.FC = ({\r\n data,\r\n context,\r\n imageSettings,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText,\r\n ratingAriaLabel,\r\n ratingCountAriaLabel,\r\n allowBack,\r\n typeName,\r\n id,\r\n telemetryContent,\r\n quickViewButton,\r\n productComparisonButton,\r\n isEnabledProductDescription,\r\n isPriceMinMaxEnabled,\r\n priceResources,\r\n inventoryLabel,\r\n dimensionAvailabilities,\r\n swatchItemAriaLabel\r\n}) => {\r\n const product = data.product;\r\n\r\n let productUrl = getProductPageUrlSync(product?.Name ?? '', product?.RecordId ?? Number.MIN_VALUE, context.actionContext, undefined);\r\n if (allowBack) {\r\n productUrl = updateProductUrl(productUrl, context, 'back=true');\r\n }\r\n const productImageUrlFromSwatch = getProductImageUrlFromDefaultSwatch(context, product) ?? product?.PrimaryImageUrl;\r\n const productPageUrlFromSwatch = getProductPageUrlFromDefaultSwatch(context, productUrl, product) ?? productUrl;\r\n const [productPageUrl, setProductPageUrl] = useState(productPageUrlFromSwatch);\r\n const [productImageUrl, setProductImageUrl] = useState(productImageUrlFromSwatch);\r\n React.useEffect(() => {\r\n setProductPageUrl(productPageUrlFromSwatch);\r\n setProductImageUrl(productImageUrlFromSwatch);\r\n }, [productUrl, productPageUrlFromSwatch, productImageUrlFromSwatch]);\r\n const [selectedSwatchItems] = useState(new Dictionary());\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access -- app context is generic\r\n const enableStockCheck = context.app.config.enableStockCheck;\r\n\r\n const siteContext = context as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n\r\n /**\r\n * Updates the product page and Image url based on swatch selected.\r\n * @param coreContext - Context of the caller.\r\n * @param swatchItem - Dimension swatch selected.\r\n */\r\n const updatePageAndImageUrl = React.useCallback(\r\n (coreContext: ICoreContext, swatchItem: ISwatchItem) => {\r\n const dimensionType = swatchItem.dimensionType;\r\n selectedSwatchItems.setValue(dimensionType, swatchItem);\r\n if (StringExtensions.isNullOrWhitespace(swatchItem.value)) {\r\n return;\r\n }\r\n const queryString = `${dimensionType}=${swatchItem.value}`;\r\n let productPageUrlWithSwatch = '';\r\n if (productPageUrl.includes(dimensionType)) {\r\n const newUrl = new URL(productPageUrl, coreContext.request.apiSettings.baseUrl);\r\n newUrl.searchParams.delete(dimensionType);\r\n productPageUrlWithSwatch = updateProductUrl(newUrl.toString(), context, queryString);\r\n } else {\r\n productPageUrlWithSwatch = updateProductUrl(productPageUrl, context, queryString);\r\n }\r\n setProductPageUrl(productPageUrlWithSwatch);\r\n if (dimensionType === dimensionToPreSelectInProductCard) {\r\n const swatchProductImageUrl = ArrayExtensions.hasElements(swatchItem.productImageUrls)\r\n ? swatchItem.productImageUrls[0]\r\n : undefined;\r\n const newImageUrl = generateImageUrl(swatchProductImageUrl, coreContext.request.apiSettings);\r\n setProductImageUrl(newImageUrl);\r\n }\r\n },\r\n [selectedSwatchItems, context, productPageUrl]\r\n );\r\n\r\n if (!product) {\r\n return null;\r\n }\r\n\r\n /**\r\n * Checks if rendering the particular dimensions is allowed for product card.\r\n * @param dimensionType - Dimension to be displayed.\r\n * @returns Updates the state with new product page url.\r\n */\r\n function shouldDisplayDimension(dimensionType: string): boolean {\r\n const dimensionsContext = context as ICoreContext;\r\n const dimensionsToDisplayOnProductCard = dimensionsContext.app.config.dimensionsInProductCard;\r\n return (\r\n ArrayExtensions.hasElements(dimensionsToDisplayOnProductCard) &&\r\n !dimensionsToDisplayOnProductCard.includes(DimensionTypes.none) &&\r\n dimensionsToDisplayOnProductCard.includes(dimensionType.toLocaleLowerCase() as DimensionTypes)\r\n );\r\n }\r\n\r\n /**\r\n * Gets the react node for product dimension as swatch.\r\n * @param attributeValues - Attribute value property from product.\r\n * @returns The node representing markup for unit of measure component.\r\n */\r\n function renderProductDimensions(attributeValues?: AttributeValue[]): JSX.Element | null {\r\n if (!attributeValues) {\r\n return null;\r\n }\r\n\r\n return (\r\n
\r\n {attributeValues.map((item: AttributeValue) => {\r\n const dimensionTypeValue = item.KeyName?.toLocaleLowerCase() ?? '';\r\n if (!shouldDisplayDimension(dimensionTypeValue)) {\r\n return null;\r\n }\r\n\r\n const siteContext = context as ICoreContext;\r\n const dimensionToPreSelectInProductCard = siteContext.app.config.dimensionToPreSelectInProductCard;\r\n const dimensionType = dimensionTypeValue as DimensionTypes;\r\n const swatches =\r\n item.Swatches?.map(swatchItem => {\r\n return {\r\n itemId: `${item.RecordId ?? ''}-${dimensionTypeValue}-${swatchItem.SwatchValue ?? ''}`,\r\n value: swatchItem.SwatchValue ?? '',\r\n dimensionType,\r\n colorHexCode: swatchItem.SwatchColorHexCode,\r\n imageUrl: swatchItem.SwatchImageUrl,\r\n productImageUrls: swatchItem.ProductImageUrls,\r\n isDefault: swatchItem.IsDefault,\r\n swatchItemAriaLabel: swatchItemAriaLabel ? format(swatchItemAriaLabel, dimensionType) : '',\r\n isDisabled:\r\n enableStockCheck &&\r\n dimensionAvailabilities?.find(\r\n dimensionAvailability => dimensionAvailability.value === (swatchItem.SwatchValue ?? '')\r\n )?.isDisabled\r\n };\r\n }) ?? [];\r\n if (\r\n dimensionType === dimensionToPreSelectInProductCard &&\r\n ArrayExtensions.hasElements(swatches) &&\r\n !swatches.some(swatch => swatch.isDefault)\r\n ) {\r\n swatches[0].isDefault = true;\r\n }\r\n return (\r\n \r\n );\r\n })}\r\n
\r\n );\r\n }\r\n\r\n function renderQuickView(quickview: React.ReactNode, item?: number): JSX.Element | undefined {\r\n if (quickview === null) {\r\n return undefined;\r\n }\r\n const selectedDimensions: ProductDimension[] = selectedSwatchItems.getValues().map(swatches => {\r\n return {\r\n DimensionTypeValue: convertDimensionTypeToProductDimensionType(swatches.dimensionType),\r\n DimensionValue: {\r\n RecordId: 0,\r\n Value: swatches.value\r\n }\r\n };\r\n });\r\n return React.cloneElement(quickview as React.ReactElement, { selectedProductId: item, selectedDimensions });\r\n }\r\n\r\n // Construct telemetry attribute to render\r\n const payLoad = getPayloadObject('click', telemetryContent!, '', product.RecordId.toString());\r\n\r\n const attribute = getTelemetryAttributes(telemetryContent!, payLoad);\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- -- Do not need type check for appsettings\r\n const isUnitOfMeasureEnabled = context.app.config && context.app.config.unitOfMeasureDisplayType === 'buyboxAndBrowse';\r\n\r\n const brandName = data.product?.AttributeValues?.find(attribute => attribute.Name === context.app.config.brandNameAttributeName);\r\n const productSize = data.product?.AttributeValues?.find(attribute => attribute.Name === context.app.config.productSizeAttributeName);\r\n const productUnit = data.product?.AttributeValues?.find(attribute => attribute.Name === context.app.config.productUnitAttributeName);\r\n const productNameLength = product.Name?.length && product.Name?.length < 10;\r\n return (\r\n <>\r\n {isEnabledProductDescription ? (\r\n \r\n
\r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n productImageUrl,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n context\r\n )}\r\n
\r\n
\r\n
{product.Name}
\r\n {renderPrice(\r\n context,\r\n typeName,\r\n id,\r\n product.BasePrice,\r\n product.Price,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText,\r\n isPriceMinMaxEnabled,\r\n priceResources\r\n )}\r\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\r\n {renderDescription(product.Description)}\r\n
\r\n
\r\n \r\n ) : (\r\n \r\n
\r\n {renderProductPlacementImage(\r\n imageSettings,\r\n context.request.gridSettings,\r\n productImageUrl,\r\n product.PrimaryImageUrl,\r\n product.Name,\r\n context\r\n )}\r\n
\r\n
\r\n
\r\n {brandName?.TextValue}\r\n
{product.Name}
\r\n
\r\n
\r\n {renderPrice(\r\n context,\r\n typeName,\r\n id,\r\n product.BasePrice,\r\n product.Price,\r\n savingsText,\r\n freePriceText,\r\n originalPriceText,\r\n currentPriceText\r\n )}\r\n {isUnitOfMeasureEnabled && renderProductUnitOfMeasure(product.DefaultUnitOfMeasure)}\r\n {productSize?.FloatValue} {productUnit?.TextValue}\r\n
\r\n
\r\n \r\n )}\r\n {renderProductDimensions(product.AttributeValues)}\r\n {!context.app.config.hideRating &&\r\n renderRating(context, typeName, id, product.AverageRating, product.TotalRatings, ratingAriaLabel, ratingCountAriaLabel)}\r\n {renderProductAvailability(inventoryLabel)}\r\n {quickViewButton && renderQuickView(quickViewButton, product.RecordId)}\r\n {productComparisonButton && renderProductComparisonButton(productComparisonButton, product, getCatalogId(context.request))}\r\n \r\n );\r\n};\r\n\r\nfunction renderLabel(\r\n name?: string,\r\n price?: string,\r\n rating?: number,\r\n ratingAriaLabelText?: string,\r\n reviewCount?: number,\r\n ratingCountAriaLabelText?: string\r\n): string {\r\n const reviewCountArialableText = getReviewAriaLabel(reviewCount, ratingCountAriaLabelText ?? '');\r\n return `${name ?? ''} ${price ?? ''} ${getRatingAriaLabel(rating, ratingAriaLabelText)}${\r\n reviewCountArialableText ? ` ${reviewCountArialableText}` : ''\r\n }`;\r\n}\r\n\r\nfunction renderDescription(description?: string): JSX.Element | null {\r\n return

{description}

;\r\n}\r\n\r\nfunction getRatingAriaLabel(rating?: number, ratingAriaLabel?: string): string {\r\n if (rating && ratingAriaLabel) {\r\n const roundedRating = rating.toFixed(2);\r\n return format(ratingAriaLabel || '', roundedRating, '5');\r\n }\r\n return '';\r\n}\r\n\r\nfunction getReviewAriaLabel(reviewCount?: number, ratingCountAriaLabelText?: string): string {\r\n if (reviewCount && ratingCountAriaLabelText) {\r\n return format(ratingCountAriaLabelText || '', reviewCount);\r\n }\r\n return '';\r\n}\r\n\r\nfunction renderRating(\r\n coreContext: ICoreContext,\r\n moduleTypeName: string,\r\n moduleId: string,\r\n avgRating?: number,\r\n totalRatings?: number,\r\n ariaLabel?: string,\r\n ratingCountAriaLabel?: string\r\n): JSX.Element | null {\r\n if (!avgRating) {\r\n return null;\r\n }\r\n\r\n const numberRatings = totalRatings?.toString() || undefined;\r\n const ratingAriaLabelText = getRatingAriaLabel(avgRating, ariaLabel);\r\n const ratingCountAriaLabelText = getReviewAriaLabel(Number(numberRatings), ratingCountAriaLabel);\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nfunction renderPrice(\r\n context: ICoreContext,\r\n typeName: string,\r\n id: string,\r\n basePrice?: number,\r\n adjustedPrice?: number,\r\n savingsText?: string,\r\n freePriceText?: string,\r\n originalPriceText?: string,\r\n currentPriceText?: string,\r\n isPriceMinMaxEnabled?: boolean,\r\n priceResources?: IPriceComponentResources\r\n): JSX.Element | null {\r\n const price: ProductPrice = {\r\n BasePrice: basePrice,\r\n AdjustedPrice: adjustedPrice,\r\n CustomerContextualPrice: adjustedPrice\r\n };\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nfunction renderProductPlacementImage(\r\n imageSettings?: IImageSettings,\r\n gridSettings?: IGridSettings,\r\n imageUrl?: string,\r\n fallbackImageUrl?: string,\r\n altText?: string,\r\n context?: ICoreContext>\r\n): JSX.Element | null {\r\n if (!imageUrl || !gridSettings || !imageSettings) {\r\n return null;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- Site level config can be of any type.\r\n const contextConfig = context?.app.config?.placeholderImageName;\r\n const emptyPlaceHolderImage = contextConfig as string;\r\n let fallbackImageSource = fallbackImageUrl;\r\n if (emptyPlaceHolderImage && fallbackImageUrl) {\r\n fallbackImageSource = `${fallbackImageUrl},${emptyPlaceHolderImage}`;\r\n }\r\n const img: IImageData = {\r\n src: imageUrl,\r\n altText: altText ? altText : '',\r\n fallBackSrc: fallbackImageSource\r\n };\r\n const imageProps = {\r\n gridSettings,\r\n imageSettings\r\n };\r\n imageProps.imageSettings.cropFocalRegion = true;\r\n return (\r\n \r\n );\r\n}\r\n\r\nexport const ProductComponent: React.FunctionComponent = msdyn365Commerce.createComponentOverride<\r\n IProductComponent\r\n>('Product', { component: ProductCard, ...PriceComponentActions });\r\n\r\nexport default ProductComponent;\r\n"],"sourceRoot":""}