Trailing commas, null checks, formatting

Added trailing commas object literals in normalize util.
Added null checks for product and cart item normalization methods.
Formatted the code with prettier config.
Separated the nested functions in groupProductOptionsByAttributeLabel
This commit is contained in:
tedraykov 2021-05-25 12:57:11 +03:00
parent f933d66e38
commit 081a9a54a7
4 changed files with 151 additions and 98 deletions

View File

@ -127,4 +127,3 @@ a {
opacity: 1; opacity: 1;
} }
} }

View File

@ -111,8 +111,8 @@ export type CartItemBody = {
productId?: string productId?: string
quantity?: number quantity?: number
pricing?: { pricing?: {
amount: number, amount: number
currencyCode: string, currencyCode: string
} }
} }

View File

@ -1,4 +1,10 @@
import {Product, Customer, ProductVariant, ProductOption, ProductOptionValues} from '@commerce/types' import {
Product,
Customer,
ProductVariant,
ProductOption,
ProductOptionValues,
} from '@commerce/types'
import { import {
Account, Account,
@ -11,12 +17,12 @@ import {
CartItem, CartItem,
} from '../schema' } from '../schema'
import type {Cart, LineItem} from '../types' import type { Cart, LineItem } from '../types'
const normalizeProductImages = (images: ImageInfo[], name: string) => const normalizeProductImages = (images: ImageInfo[], name: string) =>
images.map((image) => ({ images.map((image) => ({
url: image?.URLs?.original || image?.URLs?.medium || '', url: image?.URLs?.original || image?.URLs?.medium || '',
alt: name alt: name,
})) }))
const normalizeProductOption = (variant: CatalogProductVariant) => { const normalizeProductOption = (variant: CatalogProductVariant) => {
@ -24,30 +30,36 @@ const normalizeProductOption = (variant: CatalogProductVariant) => {
__typename: 'MultipleChoiceOption', __typename: 'MultipleChoiceOption',
id: variant._id, id: variant._id,
displayName: variant.attributeLabel, displayName: variant.attributeLabel,
values: variant.optionTitle ? [{label: variant.optionTitle}] : [] values: variant.optionTitle ? [{ label: variant.optionTitle }] : [],
} }
option.values = option.values.map(value => colorizeProductOptionValue(value, option.displayName)) option.values = option.values.map((value) =>
colorizeProductOptionValue(value, option.displayName)
)
return option; return option
} }
function colorizeProductOptionValue(value: ProductOptionValues, displayName: string): ProductOptionValues { function colorizeProductOptionValue(
value: ProductOptionValues,
displayName: string
): ProductOptionValues {
if (displayName.toLowerCase() === 'color') { if (displayName.toLowerCase() === 'color') {
value.hexColors = [value.label] value.hexColors = [value.label]
} }
return value; return value
} }
const normalizeProductVariants = (variants: Array<CatalogProductVariant>): ProductVariant[] => { const normalizeProductVariants = (
console.log(variants); variants: Array<CatalogProductVariant>
return variants.reduce((productVariants: ProductVariant[], variant: CatalogProductVariant) => { ): ProductVariant[] => {
return variants.reduce(
(productVariants: ProductVariant[], variant: CatalogProductVariant) => {
if (variantHasOptions(variant)) { if (variantHasOptions(variant)) {
productVariants.push(...flatVariantOptions(variant)) productVariants.push(...flatVariantOptions(variant))
return productVariants return productVariants
} }
const {sku, title, pricing = [], variantId} = variant ?? {} const { sku, title, pricing = [], variantId } = variant ?? {}
const variantPrice = pricing[0]?.price ?? pricing[0]?.minPrice ?? 0 const variantPrice = pricing[0]?.price ?? pricing[0]?.minPrice ?? 0
productVariants.push(<ProductVariant>{ productVariants.push(<ProductVariant>{
@ -57,71 +69,100 @@ const normalizeProductVariants = (variants: Array<CatalogProductVariant>): Produ
price: variantPrice, price: variantPrice,
listPrice: pricing[0]?.compareAtPrice?.amount ?? variantPrice, listPrice: pricing[0]?.compareAtPrice?.amount ?? variantPrice,
requiresShipping: true, requiresShipping: true,
options: [normalizeProductOption(variant)] options: [normalizeProductOption(variant)],
}); })
return productVariants; return productVariants
}, []) },
[]
)
} }
function groupProductOptionsByAttributeLabel(variants: CatalogProductVariant[]): ProductOption[] { function groupProductOptionsByAttributeLabel(
return variants.reduce((groupedOptions: ProductOption[], currentVariant: CatalogProductVariant) => { variants: CatalogProductVariant[]
): ProductOption[] {
groupedOptions = mergeVariantOptionsWithExistingOptions(groupedOptions, currentVariant); return variants.reduce(
(
groupedOptions: ProductOption[],
currentVariant: CatalogProductVariant
) => {
groupedOptions = mergeVariantOptionsWithExistingOptions(
groupedOptions,
currentVariant
)
if (variantHasOptions(currentVariant)) { if (variantHasOptions(currentVariant)) {
(<CatalogProductVariant[]>currentVariant.options).forEach(variantOption => { (<CatalogProductVariant[]>currentVariant.options).forEach(
groupedOptions = mergeVariantOptionsWithExistingOptions(groupedOptions, variantOption) (variantOption) => {
}) groupedOptions = mergeVariantOptionsWithExistingOptions(
groupedOptions,
variantOption
)
}
)
} }
return groupedOptions return groupedOptions
}, []) },
[]
)
}
function mergeVariantOptionsWithExistingOptions( function mergeVariantOptionsWithExistingOptions(
groupedOptions: ProductOption[], groupedOptions: ProductOption[],
currentVariant: CatalogProductVariant): ProductOption[] { currentVariant: CatalogProductVariant
): ProductOption[] {
const matchingOptionIndex = findCurrentVariantOptionsInGroupedOptions(
groupedOptions,
currentVariant
)
const matchingOptionIndex = findCurrentVariantOptionsInGroupedOptions(groupedOptions, currentVariant) return matchingOptionIndex !== -1
? mergeWithExistingOptions(
groupedOptions,
currentVariant,
matchingOptionIndex
)
: addNewProductOption(groupedOptions, currentVariant)
}
return matchingOptionIndex !== -1 ? function findCurrentVariantOptionsInGroupedOptions(
mergeWithExistingOptions(groupedOptions, currentVariant, matchingOptionIndex) :
addNewProductOption(groupedOptions, currentVariant)
}
function findCurrentVariantOptionsInGroupedOptions(
groupedOptions: ProductOption[], groupedOptions: ProductOption[],
currentVariant: CatalogProductVariant): number { currentVariant: CatalogProductVariant
): number {
return groupedOptions.findIndex(
(option) =>
option.displayName.toLowerCase() ===
currentVariant.attributeLabel.toLowerCase()
)
}
return groupedOptions.findIndex(option => function mergeWithExistingOptions(
(option.displayName.toLowerCase() === currentVariant.attributeLabel.toLowerCase())
);
}
function mergeWithExistingOptions(
groupedOptions: ProductOption[], groupedOptions: ProductOption[],
currentVariant: CatalogProductVariant, currentVariant: CatalogProductVariant,
matchingOptionIndex: number) { matchingOptionIndex: number
) {
const currentVariantOption = normalizeProductOption(currentVariant); const currentVariantOption = normalizeProductOption(currentVariant)
groupedOptions[matchingOptionIndex].values = [ groupedOptions[matchingOptionIndex].values = [
...groupedOptions[matchingOptionIndex].values, ...groupedOptions[matchingOptionIndex].values,
...currentVariantOption.values ...currentVariantOption.values,
] ]
return groupedOptions; return groupedOptions
} }
function addNewProductOption(groupedOptions: ProductOption[], currentVariant: CatalogProductVariant) { function addNewProductOption(
return [ groupedOptions: ProductOption[],
...groupedOptions, currentVariant: CatalogProductVariant
normalizeProductOption(currentVariant), ) {
]; return [...groupedOptions, normalizeProductOption(currentVariant)]
}
} }
export function normalizeProduct(productNode: CatalogItemProduct): Product { export function normalizeProduct(productNode: CatalogItemProduct): Product {
const product = productNode.product as CatalogProduct const product = productNode.product
if (!product) {
return <Product>{}
}
const { const {
_id, _id,
@ -132,8 +173,8 @@ export function normalizeProduct(productNode: CatalogItemProduct): Product {
sku, sku,
media, media,
pricing, pricing,
variants variants,
} = product } = <CatalogProduct>product
return { return {
id: productId ?? _id, id: productId ?? _id,
@ -142,14 +183,20 @@ export function normalizeProduct(productNode: CatalogItemProduct): Product {
slug: slug?.replace(/^\/+|\/+$/g, '') ?? '', slug: slug?.replace(/^\/+|\/+$/g, '') ?? '',
path: slug ?? '', path: slug ?? '',
sku: sku ?? '', sku: sku ?? '',
images: media?.length ? normalizeProductImages(<ImageInfo[]>media, title ?? '') : [], images: media?.length
? normalizeProductImages(<ImageInfo[]>media, title ?? '')
: [],
vendor: product.vendor, vendor: product.vendor,
price: { price: {
value: pricing[0]?.minPrice ?? 0, value: pricing[0]?.minPrice ?? 0,
currencyCode: pricing[0]?.currency.code, currencyCode: pricing[0]?.currency.code,
}, },
variants: !!variants ? normalizeProductVariants(<CatalogProductVariant[]>variants) : [], variants: !!variants
options: !!variants ? groupProductOptionsByAttributeLabel(<CatalogProductVariant[]>variants) : [] ? normalizeProductVariants(<CatalogProductVariant[]>variants)
: [],
options: !!variants
? groupProductOptionsByAttributeLabel(<CatalogProductVariant[]>variants)
: [],
} }
} }
@ -163,7 +210,10 @@ export function normalizeCart(cart: ReactionCart): Cart {
code: cart.checkout?.summary?.total?.currency.code ?? '', code: cart.checkout?.summary?.total?.currency.code ?? '',
}, },
taxesIncluded: false, taxesIncluded: false,
lineItems: cart.items?.edges?.map(cartItem => normalizeLineItem(<CartItemEdge>cartItem)) ?? [], lineItems:
cart.items?.edges?.map((cartItem) =>
normalizeLineItem(<CartItemEdge>cartItem)
) ?? [],
lineItemsSubtotalPrice: +(cart.checkout?.summary?.itemTotal?.amount ?? 0), lineItemsSubtotalPrice: +(cart.checkout?.summary?.itemTotal?.amount ?? 0),
subtotalPrice: +(cart.checkout?.summary?.itemTotal?.amount ?? 0), subtotalPrice: +(cart.checkout?.summary?.itemTotal?.amount ?? 0),
totalPrice: cart.checkout?.summary?.total?.amount ?? 0, totalPrice: cart.checkout?.summary?.total?.amount ?? 0,
@ -171,7 +221,13 @@ export function normalizeCart(cart: ReactionCart): Cart {
} }
} }
function normalizeLineItem(cartItem: CartItemEdge): LineItem { function normalizeLineItem(cartItemEdge: CartItemEdge): LineItem {
const cartItem = cartItemEdge.node
if (!cartItem) {
return <LineItem>{}
}
const { const {
_id, _id,
compareAtPrice, compareAtPrice,
@ -181,10 +237,9 @@ function normalizeLineItem(cartItem: CartItemEdge): LineItem {
priceWhenAdded, priceWhenAdded,
optionTitle, optionTitle,
variantTitle, variantTitle,
quantity quantity,
} = <CartItem>cartItem.node } = <CartItem>cartItem
console.log('imageURLs', cartItem)
return { return {
id: _id, id: _id,
variantId: String(productConfiguration?.productVariantId), variantId: String(productConfiguration?.productVariantId),
@ -201,7 +256,7 @@ function normalizeLineItem(cartItem: CartItemEdge): LineItem {
requiresShipping: true, requiresShipping: true,
price: priceWhenAdded?.amount, price: priceWhenAdded?.amount,
listPrice: compareAtPrice?.amount ?? 0, listPrice: compareAtPrice?.amount ?? 0,
options: [] options: [],
}, },
path: '', path: '',
discounts: [], discounts: [],
@ -226,15 +281,14 @@ export function normalizeCustomer(viewer: Account): Customer {
} }
function flatVariantOptions(variant: CatalogProductVariant): ProductVariant[] { function flatVariantOptions(variant: CatalogProductVariant): ProductVariant[] {
const variantOptions = <CatalogProductVariant[]>variant.options; const variantOptions = <CatalogProductVariant[]>variant.options
return normalizeProductVariants(variantOptions) return normalizeProductVariants(variantOptions).map((variantOption) => {
.map(variantOption => {
variantOption.options.push(normalizeProductOption(variant)) variantOption.options.push(normalizeProductOption(variant))
return variantOption return variantOption
}); })
} }
function variantHasOptions(variant: CatalogProductVariant) { function variantHasOptions(variant: CatalogProductVariant) {
return !!variant.options && variant.options.length != 0; return !!variant.options && variant.options.length != 0
} }