@scayle/storefront-core
Version:
Collection of essential utilities to work with the Storefront API
152 lines (151 loc) • 5.55 kB
JavaScript
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);
};