From 0c2855a323c628c8af51f0d9021611972774dea8 Mon Sep 17 00:00:00 2001 From: goncy Date: Thu, 12 Aug 2021 15:29:58 -0300 Subject: [PATCH] Add options and variants --- .../ordercloud/api/operations/get-product.ts | 29 +++++++++-- framework/ordercloud/types/product.ts | 27 +++++++++- framework/ordercloud/utils/product.ts | 51 ++++++++++--------- 3 files changed, 79 insertions(+), 28 deletions(-) diff --git a/framework/ordercloud/api/operations/get-product.ts b/framework/ordercloud/api/operations/get-product.ts index 975d9529a..636404770 100644 --- a/framework/ordercloud/api/operations/get-product.ts +++ b/framework/ordercloud/api/operations/get-product.ts @@ -1,7 +1,7 @@ import type { OperationContext } from '@commerce/api/operations' import type { GetProductOperation } from '@commerce/types/product' -import type { RawProduct } from '../../types/product' +import type { RawProduct, RawSpec, RawVariant } from '../../types/product' import type { OrdercloudConfig, Provider } from '../index' import { normalize as normalizeProduct } from '../../utils/product' @@ -22,14 +22,37 @@ export default function getProductOperation({ const { fetch } = commerce.getConfig(config) // Get a single product - const rawProduct: RawProduct = await fetch( + const productPromise = fetch( 'GET', `/me/products/${variables?.slug}` ) + // Get product specs + const specsPromise = fetch<{ Items: RawSpec[] }>( + 'GET', + `/me/products/${variables?.slug}/specs` + ).then((res) => res.Items) + + // Get product variants + const variantsPromise = fetch<{ Items: RawVariant[] }>( + 'GET', + `/me/products/${variables?.slug}/variants` + ).then((res) => res.Items) + + // Execute all promises in parallel + const [product, specs, variants] = await Promise.all([ + productPromise, + specsPromise, + variantsPromise, + ]) + + // Hydrate product + product.xp.Specs = specs + product.xp.Variants = variants + return { // Normalize product to commerce schema - product: normalizeProduct(rawProduct), + product: normalizeProduct(product), } } diff --git a/framework/ordercloud/types/product.ts b/framework/ordercloud/types/product.ts index 9c16f268c..3de95a9e1 100644 --- a/framework/ordercloud/types/product.ts +++ b/framework/ordercloud/types/product.ts @@ -1,3 +1,27 @@ +interface RawVariantSpec { + SpecID: string + Name: string + OptionID: string + Value: string +} + +export interface RawSpec { + ID: string + Name: string + Options: { + ID: string + Value: string + xp: { + hexColor?: string + } + }[] +} + +export interface RawVariant { + ID: string + Specs: RawVariantSpec[] +} + export interface RawProduct { OwnerID: string DefaultPriceScheduleID: string | null @@ -23,6 +47,7 @@ export interface RawProduct { Images: { url: string }[] - Facets: Record + Variants?: RawVariant[] + Specs?: RawSpec[] } } diff --git a/framework/ordercloud/utils/product.ts b/framework/ordercloud/utils/product.ts index ec214f236..1c3f2336c 100644 --- a/framework/ordercloud/utils/product.ts +++ b/framework/ordercloud/utils/product.ts @@ -13,30 +13,33 @@ export function normalize(product: RawProduct): Product { value: product.xp.Price, currencyCode: product.xp.PriceCurrency, }, - // Variants are not always present, in case they are not, return a single unique variant - variants: - product.VariantCount === 0 - ? [ - { - id: 'unique', - options: [ - { - id: 'unique', - displayName: 'Unique', - values: [{ label: 'Unique' }], - }, - ], - }, - ] - : [], - // Facets are not always present, just iterate them if they are - options: product.xp.Facets - ? Object.entries(product.xp.Facets).map(([key, values]) => ({ - id: key, - displayName: key, - __typename: 'MultipleChoiceOption', - values: values.map((value) => ({ - label: value, + variants: product.xp.Variants?.length + ? product.xp.Variants.map((variant) => ({ + id: variant.ID, + options: variant.Specs.map((spec) => ({ + id: spec.SpecID, + __typename: 'MultipleChoiceOption', + displayName: spec.Name, + values: [ + { + label: spec.Value, + }, + ], + })), + })) + : [ + { + id: product.ID, + options: [], + }, + ], + options: product.xp.Specs?.length + ? product.xp.Specs.map((spec) => ({ + id: spec.ID, + displayName: spec.Name, + values: spec.Options.map((option) => ({ + label: option.Value, + ...(option.xp?.hexColor && { hexColors: [option.xp.hexColor] }), })), })) : [],