mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 15:36:58 +00:00
219 lines
4.9 KiB
TypeScript
219 lines
4.9 KiB
TypeScript
import { Product } from '@commerce/types'
|
|
|
|
import {
|
|
CatalogItem,
|
|
Cart as ReactionCart,
|
|
ProductPricingInfo,
|
|
CatalogProductVariant,
|
|
CartItemEdge,
|
|
} from '../schema'
|
|
|
|
import type { Cart, LineItem } from '../types'
|
|
|
|
const money = ({ displayPrice }: ProductPricingInfo) => {
|
|
return {
|
|
displayPrice,
|
|
}
|
|
}
|
|
|
|
const normalizeProductOption = ({
|
|
id,
|
|
name: displayName,
|
|
values,
|
|
}: ProductOption) => {
|
|
return {
|
|
__typename: 'MultipleChoiceOption',
|
|
id,
|
|
displayName,
|
|
values: values.map((value) => {
|
|
let output: any = {
|
|
label: value,
|
|
}
|
|
if (displayName === 'Color') {
|
|
output = {
|
|
...output,
|
|
hexColors: [value],
|
|
}
|
|
}
|
|
return output
|
|
}),
|
|
}
|
|
}
|
|
|
|
const normalizeProductVariants = (variants: [CatalogProductVariant]) => {
|
|
return variants?.map(
|
|
({
|
|
variantId,
|
|
attributeLabel,
|
|
optionTitle,
|
|
options,
|
|
sku,
|
|
title,
|
|
pricing,
|
|
}) => {
|
|
const variantPrice = pricing[0]?.price ?? pricing[0]?.minPrice
|
|
|
|
return {
|
|
id: variantId,
|
|
name: title,
|
|
sku: sku ?? variantId,
|
|
price: variantPrice,
|
|
listPrice: pricing[0]?.compareAtPrice?.amount ?? variantPrice,
|
|
requiresShipping: true,
|
|
// options: options?.map(({ attributeLabel, optionTitle }: CatalogProductVariant) =>
|
|
// normalizeProductOption({
|
|
// id: _id,
|
|
// name: attributeLabel,
|
|
// values: [optionTitle],
|
|
// })
|
|
// ) ?? [],
|
|
options: [
|
|
{
|
|
__typename: 'MultipleChoiceOption',
|
|
displayName: attributeLabel,
|
|
values: [{ label: optionTitle }],
|
|
},
|
|
],
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
export function groupProductOptionsByAttributeLabel(
|
|
options: [CatalogProductVariant]
|
|
) {
|
|
return options.reduce((groupedOptions, currentOption) => {
|
|
const attributeLabelIndex = groupedOptions.findIndex((option) => {
|
|
return (
|
|
option.displayName.toLowerCase() ===
|
|
currentOption.attributeLabel.toLowerCase()
|
|
)
|
|
})
|
|
|
|
if (attributeLabelIndex !== -1) {
|
|
groupedOptions[attributeLabelIndex].values = [
|
|
...groupedOptions[attributeLabelIndex].values,
|
|
{
|
|
label: currentOption.optionTitle,
|
|
hexColors: [currentOption.optionTitle],
|
|
},
|
|
]
|
|
} else {
|
|
groupedOptions = [
|
|
...groupedOptions,
|
|
normalizeProductOption({
|
|
id: currentOption.variantId,
|
|
name: currentOption.attributeLabel,
|
|
values: [currentOption.optionTitle],
|
|
}),
|
|
]
|
|
}
|
|
|
|
return groupedOptions
|
|
}, [])
|
|
}
|
|
|
|
export function normalizeProduct(productNode: CatalogItemEdge): CatalogItem {
|
|
const {
|
|
_id,
|
|
product: {
|
|
productId,
|
|
description,
|
|
title: name,
|
|
vendor,
|
|
pricing,
|
|
slug,
|
|
primaryImage,
|
|
variants,
|
|
},
|
|
...rest
|
|
} = productNode
|
|
|
|
const product = {
|
|
id: productId ?? _id,
|
|
name,
|
|
vendor,
|
|
description,
|
|
path: `/${slug}`,
|
|
slug: slug?.replace(/^\/+|\/+$/g, ''),
|
|
price: {
|
|
value: pricing[0].minPrice,
|
|
currencyCode: pricing[0].currency.code,
|
|
},
|
|
variants: variants ? normalizeProductVariants(variants) : [],
|
|
options: variants ? groupProductOptionsByAttributeLabel(variants) : [],
|
|
images: [],
|
|
...rest,
|
|
}
|
|
|
|
if (productNode.product.primaryImage) {
|
|
product.images = [
|
|
{
|
|
url: primaryImage?.URLs?.original,
|
|
alt: name,
|
|
},
|
|
]
|
|
}
|
|
|
|
return product
|
|
}
|
|
|
|
export function normalizeCart(cart: ReactionCart): Cart {
|
|
return {
|
|
id: cart._id,
|
|
customerId: '',
|
|
email: '',
|
|
createdAt: cart.createdAt,
|
|
currency: {
|
|
code: cart.checkout?.summary?.total?.currency.code,
|
|
},
|
|
taxesIncluded: false,
|
|
lineItems: cart.items?.edges?.map(normalizeLineItem),
|
|
lineItemsSubtotalPrice: +cart.checkout?.summary?.itemTotal?.amount,
|
|
subtotalPrice: +cart.checkout?.summary?.itemTotal?.amount,
|
|
totalPrice: cart.checkout?.summary?.total?.amount,
|
|
discounts: [],
|
|
}
|
|
}
|
|
|
|
function normalizeLineItem({
|
|
node: {
|
|
_id,
|
|
compareAtPrice,
|
|
imageURLs,
|
|
title,
|
|
productConfiguration,
|
|
priceWhenAdded,
|
|
optionTitle,
|
|
variantTitle,
|
|
quantity,
|
|
},
|
|
}: CartItemEdge): LineItem {
|
|
console.log('imageURLs', imageURLs)
|
|
return {
|
|
id: _id,
|
|
variantId: String(productConfiguration?.productVariantId),
|
|
productId: String(productConfiguration?.productId),
|
|
name: `${title}`,
|
|
quantity,
|
|
variant: {
|
|
id: String(productConfiguration?.productVariantId),
|
|
sku: String(productConfiguration?.productVariantId),
|
|
name: String(optionTitle || variantTitle),
|
|
image: {
|
|
url: imageURLs?.original ?? '/product-img-placeholder.svg',
|
|
},
|
|
requiresShipping: true,
|
|
price: priceWhenAdded?.amount,
|
|
listPrice: compareAtPrice?.amount,
|
|
},
|
|
path: '',
|
|
discounts: [],
|
|
options: [
|
|
{
|
|
value: String(optionTitle || variantTitle),
|
|
},
|
|
],
|
|
}
|
|
}
|