mirror of
https://github.com/vercel/commerce.git
synced 2025-07-04 12:11:22 +00:00
Allow placeholder images for products and line items without images
This commit is contained in:
parent
448100290d
commit
be0e246699
@ -14,3 +14,5 @@ NEXT_PUBLIC_SPREE_CATEGORIES_TAXONOMY_ID=1
|
|||||||
NEXT_PUBLIC_SPREE_BRANDS_TAXONOMY_ID=27
|
NEXT_PUBLIC_SPREE_BRANDS_TAXONOMY_ID=27
|
||||||
NEXT_PUBLIC_SPREE_SHOW_SINGLE_VARIANT_OPTIONS=false
|
NEXT_PUBLIC_SPREE_SHOW_SINGLE_VARIANT_OPTIONS=false
|
||||||
NEXT_PUBLIC_SPREE_LAST_UPDATED_PRODUCTS_PRERENDER_COUNT=10
|
NEXT_PUBLIC_SPREE_LAST_UPDATED_PRODUCTS_PRERENDER_COUNT=10
|
||||||
|
NEXT_PUBLIC_SPREE_PRODUCT_PLACEHOLDER_IMAGE_URL=/product-img-placeholder.svg
|
||||||
|
NEXT_PUBLIC_SPREE_LINE_ITEM_PLACEHOLDER_IMAGE_URL=/product-img-placeholder.svg
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import forceIsomorphicConfigValues from './utils/force-isomorphic-config-values'
|
import forceIsomorphicConfigValues from './utils/force-isomorphic-config-values'
|
||||||
import requireConfig from './utils/require-config'
|
import requireConfig from './utils/require-config'
|
||||||
import validateCookieExpire from './utils/validate-cookie-expire'
|
import validateCookieExpire from './utils/validate-cookie-expire'
|
||||||
|
import validatePlaceholderImageUrl from './utils/validate-placeholder-image-url'
|
||||||
import validateProductsPrerenderCount from './utils/validate-products-prerender-count'
|
import validateProductsPrerenderCount from './utils/validate-products-prerender-count'
|
||||||
|
|
||||||
const isomorphicConfig = {
|
const isomorphicConfig = {
|
||||||
@ -18,6 +19,12 @@ const isomorphicConfig = {
|
|||||||
lastUpdatedProductsPrerenderCount: validateProductsPrerenderCount(
|
lastUpdatedProductsPrerenderCount: validateProductsPrerenderCount(
|
||||||
process.env.NEXT_PUBLIC_SPREE_LAST_UPDATED_PRODUCTS_PRERENDER_COUNT
|
process.env.NEXT_PUBLIC_SPREE_LAST_UPDATED_PRODUCTS_PRERENDER_COUNT
|
||||||
),
|
),
|
||||||
|
productPlaceholderImageUrl: validatePlaceholderImageUrl(
|
||||||
|
process.env.NEXT_PUBLIC_SPREE_PRODUCT_PLACEHOLDER_IMAGE_URL
|
||||||
|
),
|
||||||
|
lineItemPlaceholderImageUrl: validatePlaceholderImageUrl(
|
||||||
|
process.env.NEXT_PUBLIC_SPREE_LINE_ITEM_PLACEHOLDER_IMAGE_URL
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default forceIsomorphicConfigValues(
|
export default forceIsomorphicConfigValues(
|
||||||
@ -33,6 +40,8 @@ export default forceIsomorphicConfigValues(
|
|||||||
'brandsTaxonomyId',
|
'brandsTaxonomyId',
|
||||||
'showSingleVariantOptions',
|
'showSingleVariantOptions',
|
||||||
'lastUpdatedProductsPrerenderCount',
|
'lastUpdatedProductsPrerenderCount',
|
||||||
|
'productPlaceholderImageUrl',
|
||||||
|
'lineItemPlaceholderImageUrl',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,6 +21,11 @@ import type {
|
|||||||
OptionTypeAttr,
|
OptionTypeAttr,
|
||||||
VariantAttr,
|
VariantAttr,
|
||||||
} from '@framework/types'
|
} from '@framework/types'
|
||||||
|
import type { Image } from '@commerce/types/common'
|
||||||
|
|
||||||
|
const placeholderImage = requireConfigValue('lineItemPlaceholderImageUrl') as
|
||||||
|
| string
|
||||||
|
| false
|
||||||
|
|
||||||
const isColorProductOption = (productOptionType: OptionTypeAttr) => {
|
const isColorProductOption = (productOptionType: OptionTypeAttr) => {
|
||||||
return productOptionType.attributes.presentation === 'Color'
|
return productOptionType.attributes.presentation === 'Color'
|
||||||
@ -74,6 +79,10 @@ const normalizeVariant = (
|
|||||||
lineItemImage = productImage
|
lineItemImage = productImage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const image: Image =
|
||||||
|
lineItemImage ??
|
||||||
|
(placeholderImage === false ? undefined : { url: placeholderImage })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: spreeVariant.id,
|
id: spreeVariant.id,
|
||||||
sku: spreeVariant.attributes.sku,
|
sku: spreeVariant.attributes.sku,
|
||||||
@ -81,7 +90,7 @@ const normalizeVariant = (
|
|||||||
requiresShipping: true,
|
requiresShipping: true,
|
||||||
price: parseFloat(spreeVariant.attributes.price),
|
price: parseFloat(spreeVariant.attributes.price),
|
||||||
listPrice: parseFloat(spreeVariant.attributes.price),
|
listPrice: parseFloat(spreeVariant.attributes.price),
|
||||||
image: lineItemImage,
|
image,
|
||||||
isInStock: spreeVariant.attributes.in_stock,
|
isInStock: spreeVariant.attributes.in_stock,
|
||||||
availableForSale: spreeVariant.attributes.purchasable,
|
availableForSale: spreeVariant.attributes.purchasable,
|
||||||
...(spreeVariant.attributes.weight === '0.0'
|
...(spreeVariant.attributes.weight === '0.0'
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type {
|
import type {
|
||||||
Product,
|
Product,
|
||||||
|
ProductImage,
|
||||||
ProductOption,
|
ProductOption,
|
||||||
ProductPrice,
|
ProductPrice,
|
||||||
ProductVariant,
|
ProductVariant,
|
||||||
@ -18,6 +19,10 @@ import { findIncluded, findIncludedOfType } from './find-json-api-documents'
|
|||||||
import getProductPath from './get-product-path'
|
import getProductPath from './get-product-path'
|
||||||
import MissingPrimaryVariantError from '@framework/errors/MissingPrimaryVariantError'
|
import MissingPrimaryVariantError from '@framework/errors/MissingPrimaryVariantError'
|
||||||
|
|
||||||
|
const placeholderImage = requireConfigValue('productPlaceholderImageUrl') as
|
||||||
|
| string
|
||||||
|
| false
|
||||||
|
|
||||||
const normalizeProduct = (
|
const normalizeProduct = (
|
||||||
spreeSuccessResponse: JsonApiSingleResponse | JsonApiListResponse,
|
spreeSuccessResponse: JsonApiSingleResponse | JsonApiListResponse,
|
||||||
spreeProduct: ProductAttr
|
spreeProduct: ProductAttr
|
||||||
@ -44,11 +49,18 @@ const normalizeProduct = (
|
|||||||
'images'
|
'images'
|
||||||
)
|
)
|
||||||
|
|
||||||
const images = getMediaGallery(
|
const productImages = getMediaGallery(
|
||||||
spreeImageRecords,
|
spreeImageRecords,
|
||||||
createGetAbsoluteImageUrl(requireConfigValue('imageHost') as string)
|
createGetAbsoluteImageUrl(requireConfigValue('imageHost') as string)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const images: ProductImage[] =
|
||||||
|
productImages.length === 0
|
||||||
|
? placeholderImage === false
|
||||||
|
? []
|
||||||
|
: [{ url: placeholderImage }]
|
||||||
|
: productImages
|
||||||
|
|
||||||
const price: ProductPrice = {
|
const price: ProductPrice = {
|
||||||
value: parseFloat(spreeProduct.attributes.price),
|
value: parseFloat(spreeProduct.attributes.price),
|
||||||
currencyCode: spreeProduct.attributes.currency,
|
currencyCode: spreeProduct.attributes.currency,
|
||||||
|
15
framework/spree/utils/validate-placeholder-image-url.ts
Normal file
15
framework/spree/utils/validate-placeholder-image-url.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const validatePlaceholderImageUrl = (
|
||||||
|
placeholderUrlOrFalse: unknown
|
||||||
|
): string | false => {
|
||||||
|
if (!placeholderUrlOrFalse || placeholderUrlOrFalse === 'false') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof placeholderUrlOrFalse === 'string') {
|
||||||
|
return placeholderUrlOrFalse
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new TypeError('placeholderUrlOrFalse must be a string or falsy.')
|
||||||
|
}
|
||||||
|
|
||||||
|
export default validatePlaceholderImageUrl
|
Loading…
x
Reference in New Issue
Block a user