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;
}
}

View File

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