UNPKG

@scayle/storefront-core

Version:

Collection of essential utilities to work with the Storefront API

152 lines (151 loc) 5.55 kB
import { getFirstAttributeValue } from "@scayle/storefront-api"; import * as slugifyPackage from "slugify"; import { ProductImageType } from "../constants/product.mjs"; import { getAttributeValue, getAttributeValueTuples } from "./attributeHelpers.mjs"; import { getImageFromList } from "./imageHelpers.mjs"; import { flattenDeep } from "./arrayHelpers.mjs"; const baseSlugify = slugifyPackage.default || slugifyPackage; export const slugify = (url) => { return baseSlugify(url ?? "", { lower: true, remove: /[*+~.()'"!:@/#?]/g }); }; export const getPrice = (variant) => variant.price; export const getOriginalPrice = (price) => { return price.appliedReductions.length > 0 ? price.appliedReductions[0].amount.absoluteWithTax + price.withTax : price.withTax; }; export const getTotalAppliedReductions = (price) => { const total = { absoluteWithTax: 0, relative: 0 }; if (price) { price.appliedReductions.forEach((reduction) => { total.absoluteWithTax += reduction.amount.absoluteWithTax; total.relative += reduction.amount.relative; }); } return total; }; export const getLowestPrice = (variants) => { return variants.reduce( (m, x) => m.price.withoutTax < x.price.withoutTax ? m : x ).price; }; export const getAppliedReductionsByCategory = (price, category) => { return price.appliedReductions.filter((reduction) => { return reduction.category === category; }); }; export const getSizeFromVariant = (variant, attributeName = "shopSize") => getFirstAttributeValue(variant.attributes, attributeName); export const getSizeFromSpecificVariant = (product, variantId) => { if (!product.variants) { return null; } const variant = product.variants?.find((item) => item.id === variantId); return getSizeFromVariant(variant || product.variants[0]); }; export const getVariant = (variants, id) => { return variants?.find((variant) => variant.id === id); }; export const getAllSizesFromVariants = (variantsAttributes, attributeName = "shopSize") => { const array = variantsAttributes.map( (variant) => getFirstAttributeValue(variant.attributes, attributeName) ).filter(Boolean); return [...new Map(array.map((item) => [item?.id ?? item, item])).values()]; }; export const getProductSiblings = (product, colorAttributeName = "colorDetail") => { if (!product) { return []; } const items = [product]; product.siblings?.forEach((item) => { if (!item.isActive) { return; } items.push(item); }); return items.map((item) => ({ id: item.id, image: getImageFromList(item.images, ProductImageType.BUST, "front"), colors: getAttributeValueTuples(item.attributes, colorAttributeName) })); }; export const getProductColors = (product, colorAttributeName = "colorDetail") => { return getAttributeValueTuples(product.attributes, colorAttributeName).map( (color) => color.label ); }; export const getVariantBySize = (variants, size, sizeAttributeName = "shopSize") => { return variants?.find( (variant) => getAttributeValue(variant.attributes, sizeAttributeName) === size.value ); }; export const isInStock = (variant) => { return variant.stock.quantity > 0 || variant.stock.isSellableWithoutStock === true; }; export const isVariantInStock = (variants, size, sizeAttributeName = "shopSize") => { const variant = variants?.find( (variant2) => getSizeFromVariant(variant2, sizeAttributeName)?.value === size.value ); if (!variant) { return false; } return isInStock(variant); }; export const getAttribute = (product, key) => { const values = product.attributes?.[key]?.values; if (!values) { return; } if (Array.isArray(values)) { return values[0]?.value ?? values[0]?.label; } return values?.value ?? values?.label; }; export const getProductPath = (product) => { const name = getAttributeValue(product.attributes, "name"); return `/product/${slugify(name)}-${product.id}`; }; export const getCategoriesByRoute = (product, route) => { if (!product) { return []; } const item = product?.categories?.find((categories) => { return categories.some((entry) => entry.categoryUrl === route?.path); }); if (item) { return item; } return product.categories?.[product.categories?.length - 1] || []; }; export const getLatestCategory = (categories) => { if (!categories || categories.length === 0) { return; } const categoriesLength = categories.length; const latestSubset = categories[categoriesLength - 1]; return latestSubset[latestSubset.length - 1]; }; export const getProductAndSiblingsColors = (product, colorAttributeName = "colorDetail") => { const productColor = getFirstAttributeValue( product.attributes, colorAttributeName ); const siblingsColors = (product.siblings ?? []).filter((sibling) => sibling.isActive).map( (sibling) => getFirstAttributeValue(sibling.attributes, colorAttributeName) ); return [productColor, ...siblingsColors].filter( (color) => !!color ); }; export const getVariantCrosssellingValues = (variants) => { if (!variants?.length) { return []; } const crossSellings = variants.map((variant) => variant.advancedAttributes?.variantCrosssellings).filter(Boolean); const uniqueCrossSellings = [ ...new Map(crossSellings.map((item) => [item?.id ?? item, item])).values() ]; const values = uniqueCrossSellings.map((r) => r?.values); const fieldSets = flattenDeep(values).map((r) => r?.fieldSet); return flattenDeep(fieldSets).map((r) => r?.value).filter((it) => !!it); };