import { Product } from '@commerce/types/product' import { Product as SaleorProduct, Checkout, CheckoutLine, Money, ProductVariant } from '../schema' import type { Cart, LineItem } from '../types' // TODO: Check nextjs-commerce bug if no images are added for a product const placeholderImg = '/product-img-placeholder.svg' const money = ({ amount, currency }: Money) => { return { value: +amount, currencyCode: currency || 'USD', } } const normalizeProductOptions = (options: ProductVariant[]) => { return options ?.map((option) => option?.attributes) .flat(1) .reduce((acc, x) => { if (acc.find(({ displayName }: any) => displayName === x.attribute.name)) { return acc.map((opt: any) => { return opt.displayName === x.attribute.name ? { ...opt, values: [ ...opt.values, ...x.values.map((value: any) => ({ label: value?.name, })), ], } : opt }) } return acc.concat({ __typename: 'MultipleChoiceOption', displayName: x.attribute.name, variant: 'size', values: x.values.map((value: any) => ({ label: value?.name, })), }) }, []) } const normalizeProductVariants = (variants: ProductVariant[]) => { return variants?.map((variant) => { const { id, sku, name, pricing } = variant const price = pricing?.price?.net && money(pricing.price.net)?.value return { id, name, sku: sku ?? id, price, listPrice: price, requiresShipping: true, options: normalizeProductOptions([variant]), } }) } export function normalizeProduct(productNode: SaleorProduct): Product { const { id, name, media = [], variants, description, slug, pricing, ...rest } = productNode const product = { id, name, vendor: '', description: description ? JSON.parse(description)?.blocks[0]?.data.text : '', path: `/${slug}`, slug: slug?.replace(/^\/+|\/+$/g, ''), price: (pricing?.priceRange?.start?.net && money(pricing.priceRange.start.net)) || { value: 0, currencyCode: 'USD', }, // TODO: Check nextjs-commerce bug if no images are added for a product images: media?.length ? media : [{ url: placeholderImg }], variants: variants && variants.length > 0 ? normalizeProductVariants(variants as ProductVariant[]) : [], options: variants && variants.length > 0 ? normalizeProductOptions(variants as ProductVariant[]) : [], ...rest, } return product as Product } export function normalizeCart(checkout: Checkout): Cart { const lines = checkout.lines as CheckoutLine[] const lineItems: LineItem[] = lines.length > 0 ? lines?.map(normalizeLineItem) : [] return { id: checkout.id, customerId: '', email: '', createdAt: checkout.created, currency: { code: checkout.totalPrice?.currency!, }, taxesIncluded: false, lineItems, lineItemsSubtotalPrice: checkout.subtotalPrice?.gross?.amount!, subtotalPrice: checkout.subtotalPrice?.gross?.amount!, totalPrice: checkout.totalPrice?.gross.amount!, discounts: [], } } function normalizeLineItem({ id, variant, quantity }: CheckoutLine): LineItem { return { id, variantId: String(variant?.id), productId: String(variant?.id), name: `${variant.product.name}`, quantity, variant: { id: String(variant?.id), sku: variant?.sku ?? '', name: variant?.name!, image: { url: variant?.media![0] ? variant?.media![0].url : placeholderImg, }, requiresShipping: false, price: variant?.pricing?.price?.gross.amount!, listPrice: 0, }, path: String(variant?.product?.slug), discounts: [], options: [], } }