mirror of
https://github.com/vercel/commerce.git
synced 2025-07-04 12:11:22 +00:00
Add options and variants
This commit is contained in:
parent
4151865fa2
commit
0c2855a323
@ -1,7 +1,7 @@
|
|||||||
import type { OperationContext } from '@commerce/api/operations'
|
import type { OperationContext } from '@commerce/api/operations'
|
||||||
import type { GetProductOperation } from '@commerce/types/product'
|
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 type { OrdercloudConfig, Provider } from '../index'
|
||||||
|
|
||||||
import { normalize as normalizeProduct } from '../../utils/product'
|
import { normalize as normalizeProduct } from '../../utils/product'
|
||||||
@ -22,14 +22,37 @@ export default function getProductOperation({
|
|||||||
const { fetch } = commerce.getConfig(config)
|
const { fetch } = commerce.getConfig(config)
|
||||||
|
|
||||||
// Get a single product
|
// Get a single product
|
||||||
const rawProduct: RawProduct = await fetch<RawProduct>(
|
const productPromise = fetch<RawProduct>(
|
||||||
'GET',
|
'GET',
|
||||||
`/me/products/${variables?.slug}`
|
`/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 {
|
return {
|
||||||
// Normalize product to commerce schema
|
// Normalize product to commerce schema
|
||||||
product: normalizeProduct(rawProduct),
|
product: normalizeProduct(product),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
export interface RawProduct {
|
||||||
OwnerID: string
|
OwnerID: string
|
||||||
DefaultPriceScheduleID: string | null
|
DefaultPriceScheduleID: string | null
|
||||||
@ -23,6 +47,7 @@ export interface RawProduct {
|
|||||||
Images: {
|
Images: {
|
||||||
url: string
|
url: string
|
||||||
}[]
|
}[]
|
||||||
Facets: Record<string, string[]>
|
Variants?: RawVariant[]
|
||||||
|
Specs?: RawSpec[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,30 +13,33 @@ export function normalize(product: RawProduct): Product {
|
|||||||
value: product.xp.Price,
|
value: product.xp.Price,
|
||||||
currencyCode: product.xp.PriceCurrency,
|
currencyCode: product.xp.PriceCurrency,
|
||||||
},
|
},
|
||||||
// Variants are not always present, in case they are not, return a single unique variant
|
variants: product.xp.Variants?.length
|
||||||
variants:
|
? product.xp.Variants.map((variant) => ({
|
||||||
product.VariantCount === 0
|
id: variant.ID,
|
||||||
? [
|
options: variant.Specs.map((spec) => ({
|
||||||
|
id: spec.SpecID,
|
||||||
|
__typename: 'MultipleChoiceOption',
|
||||||
|
displayName: spec.Name,
|
||||||
|
values: [
|
||||||
{
|
{
|
||||||
id: 'unique',
|
label: spec.Value,
|
||||||
options: [
|
|
||||||
{
|
|
||||||
id: 'unique',
|
|
||||||
displayName: 'Unique',
|
|
||||||
values: [{ label: 'Unique' }],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
})),
|
||||||
|
}))
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
id: product.ID,
|
||||||
|
options: [],
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
: [],
|
options: product.xp.Specs?.length
|
||||||
// Facets are not always present, just iterate them if they are
|
? product.xp.Specs.map((spec) => ({
|
||||||
options: product.xp.Facets
|
id: spec.ID,
|
||||||
? Object.entries(product.xp.Facets).map(([key, values]) => ({
|
displayName: spec.Name,
|
||||||
id: key,
|
values: spec.Options.map((option) => ({
|
||||||
displayName: key,
|
label: option.Value,
|
||||||
__typename: 'MultipleChoiceOption',
|
...(option.xp?.hexColor && { hexColors: [option.xp.hexColor] }),
|
||||||
values: values.map((value) => ({
|
|
||||||
label: value,
|
|
||||||
})),
|
})),
|
||||||
}))
|
}))
|
||||||
: [],
|
: [],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user