diff --git a/src/content/queries/cs-product.js b/src/content/queries/cs-product.js index a8f1d32..975959f 100644 --- a/src/content/queries/cs-product.js +++ b/src/content/queries/cs-product.js @@ -19,14 +19,6 @@ import { gql, parseRating, parseSpecialToDate } from '../../utils/product.js'; * @returns {Product} */ export const adapter = (config, productData) => { - let minPrice = productData.priceRange?.minimum ?? productData.price; - let maxPrice = productData.priceRange?.maximum ?? productData.price; - - if (minPrice == null) { - minPrice = maxPrice; - } else if (maxPrice == null) { - maxPrice = minPrice; - } /** @type {Product} */ const product = { sku: productData.sku, @@ -45,7 +37,12 @@ export const adapter = (config, productData) => { attributes: productData.attributes ?? [], attributeMap: Object.fromEntries((productData.attributes ?? []) .map(({ name, value }) => [name, value])), - options: (productData.options ?? []).map((option) => ({ + // eslint-disable-next-line no-underscore-dangle + type: productData.__typename === 'SimpleProductView' ? 'simple' : 'complex', + }; + + if (productData.options) { + product.options = productData.options.map((option) => ({ id: option.id, label: option.title, // eslint-disable-next-line no-underscore-dangle @@ -62,7 +59,7 @@ export const adapter = (config, productData) => { ? { sku: value.product.sku, name: value.product.name, - prices: value.product.price ? { + price: value.product.price ? { regular: value.product.price.regular, final: value.product.price.final, visible: value.product.price.roles?.includes('visible'), @@ -72,25 +69,31 @@ export const adapter = (config, productData) => { quantity: value.quantity, isDefault: value.isDefault, })), - })), - prices: (minPrice && maxPrice) ? { - regular: { - // TODO: determine whether to use min or max - amount: minPrice.regular.amount.value, - currency: minPrice.regular.amount.currency, - maximumAmount: maxPrice.regular.amount.value, - minimumAmount: minPrice.regular.amount.value, + })); + } + + if (productData.price) { + product.price = { + regular: productData.price.regular, + final: productData.price.final, + visible: productData.price.roles?.includes('visible'), + }; + } + + if (productData.priceRange) { + product.priceRange = { + minimum: { + regular: productData.priceRange.minimum.regular, + final: productData.priceRange.minimum.final, + visible: productData.priceRange.minimum.roles?.includes('visible'), }, - final: { - // TODO: determine whether to use min or max - amount: minPrice.final.amount.value, - currency: minPrice.final.amount.currency, - maximumAmount: maxPrice.final.amount.value, - minimumAmount: minPrice.final.amount.value, + maximum: { + regular: productData.priceRange.maximum.regular, + final: productData.priceRange.maximum.final, + visible: productData.priceRange.maximum.roles?.includes('visible'), }, - visible: minPrice.roles?.includes('visible'), - } : null, - }; + }; + } if (config.attributeOverrides?.product) { Object.entries(config.attributeOverrides.product).forEach(([key, value]) => { @@ -122,6 +125,7 @@ export default ({ sku, imageRoles = [] }) => gql`{ products( skus: ["${sku}"] ) { + __typename id sku name diff --git a/src/content/queries/cs-variants.js b/src/content/queries/cs-variants.js index a380dce..1f8a5fe 100644 --- a/src/content/queries/cs-variants.js +++ b/src/content/queries/cs-variants.js @@ -19,9 +19,6 @@ import { gql, parseRating, parseSpecialToDate } from '../../utils/product.js'; * @returns {Variant[]} */ export const adapter = (config, variants) => variants.map(({ selections, product }) => { - const minPrice = product.priceRange?.minimum ?? product.price; - const maxPrice = product.priceRange?.maximum ?? product.price; - /** @type {Variant} */ const variant = { name: product.name, @@ -34,25 +31,34 @@ export const adapter = (config, variants) => variants.map(({ selections, product attributeMap: Object.fromEntries((product.attributes ?? []) .map(({ name, value }) => [name, value])), externalId: product.externalId, - prices: { - regular: { - // TODO: determine whether to use min or max - amount: minPrice?.regular.amount.value, - currency: minPrice?.regular.amount.currency, - maximumAmount: maxPrice?.regular.amount.value, - minimumAmount: minPrice?.regular.amount.value, - }, - final: { - // TODO: determine whether to use min or max - amount: minPrice?.final.amount.value, - currency: minPrice?.final.amount.currency, - maximumAmount: maxPrice?.final.amount.value, - minimumAmount: minPrice?.final.amount.value, - }, - }, selections: (selections ?? []).sort(), + // eslint-disable-next-line no-underscore-dangle + type: product.__typename === 'SimpleProductView' ? 'simple' : 'complex', }; + if (product.price) { + variant.price = { + regular: product.price.regular, + final: product.price.final, + visible: product.price.roles?.includes('visible'), + }; + } + + if (product.priceRange) { + variant.priceRange = { + minimum: { + regular: product.priceRange.minimum.regular, + final: product.priceRange.minimum.final, + visible: product.priceRange.minimum.roles?.includes('visible'), + }, + maximum: { + regular: product.priceRange.maximum.regular, + final: product.priceRange.maximum.final, + visible: product.priceRange.maximum.roles?.includes('visible'), + }, + }; + } + if (config.attributeOverrides?.variant) { Object.entries(config.attributeOverrides.variant).forEach(([key, value]) => { variant.attributeMap[key] = variant.attributeMap[value] ?? variant[key]; @@ -84,6 +90,7 @@ export default ({ sku, imageRoles = [] }) => gql` variants { selections product { + __typename name sku inStock diff --git a/src/templates/html/HTMLTemplate.js b/src/templates/html/HTMLTemplate.js index 3fcfaee..86cd39f 100644 --- a/src/templates/html/HTMLTemplate.js +++ b/src/templates/html/HTMLTemplate.js @@ -38,7 +38,7 @@ export class HTMLTemplate { * @param {number|undefined} max * @returns {string} */ - static priceRange = (min, max) => (min !== max ? ` (${min} - ${max})` : ''); + static priceRange = (min, max) => (min !== max ? `${min} - ${max}` : `${min}`); /** * @param {string} str @@ -108,7 +108,7 @@ ${HTMLTemplate.metaName('twitter:card', 'summary_large_image')} ${HTMLTemplate.metaName('twitter:title', product.name)} ${HTMLTemplate.metaName('twitter:description', product.metaDescription)} ${HTMLTemplate.metaName('twitter:label1', 'Price')} -${HTMLTemplate.metaName('twitter:data1', product.prices?.final?.amount)} +${HTMLTemplate.metaName('twitter:data1', product.price?.final?.amount?.value ?? product.priceRange?.minimum?.final?.amount?.value)} ${HTMLTemplate.metaName('twitter:label2', 'Availability')} ${HTMLTemplate.metaName('twitter:data2', product.inStock ? 'In stock' : 'Out of stock')}`; } @@ -126,8 +126,9 @@ ${HTMLTemplate.metaName('externalId', product.externalId)} ${HTMLTemplate.metaName('addToCartAllowed', product.addToCartAllowed)} ${HTMLTemplate.metaName('inStock', product.inStock ? 'true' : 'false')} ${HTMLTemplate.metaProperty('product:availability', product.inStock ? 'In stock' : 'Out of stock')} -${HTMLTemplate.metaProperty('product:price.amount', product.prices?.final?.amount)} -${HTMLTemplate.metaProperty('product:price.currency', product.prices?.final?.currency)}`; +${HTMLTemplate.metaProperty('product:price.amount', product.price?.final?.amount?.value ?? product.priceRange?.minimum?.final?.amount?.value)} +${HTMLTemplate.metaProperty('product:price.currency', product.price?.final?.amount?.currency ?? product.priceRange?.minimum?.final?.amount?.currency)} +${HTMLTemplate.metaProperty('product:type', product.type)}`; } /** @@ -169,6 +170,38 @@ ${HTMLTemplate.indent(this.renderJSONLD(), 2)} `; } + /** + * Render product price block + * @param {Product} product + * @returns {string} + */ + renderProductPrices(product) { + const { price, priceRange } = product; + const hasFinal = price + ? price.final?.amount?.value < price.regular?.amount?.value + : priceRange?.minimum?.final.amount.value < priceRange?.minimum?.regular.amount.value; + const isRange = !!priceRange + && priceRange.minimum?.final?.amount?.value !== priceRange.maximum?.final?.amount?.value; + + const regularPrice = price ? price.regular?.amount : priceRange.minimum?.regular?.amount; + const finalPrice = price ? price.final?.amount : priceRange.minimum?.final?.amount; + + return /* html */ `\ +