forked from crowetic/commerce
Match product options with variants
This commit is contained in:
parent
8a8ef7dbba
commit
dd40b8c604
@ -1,5 +1,4 @@
|
||||
import { getConfig, SwellConfig } from '../api'
|
||||
import getPageQuery from '../utils/queries/get-page-query'
|
||||
import { Page } from './get-all-pages'
|
||||
|
||||
type Variables = {
|
||||
|
197
framework/swell/schema.d.ts
vendored
197
framework/swell/schema.d.ts
vendored
@ -321,96 +321,113 @@ export enum CardBrand {
|
||||
}
|
||||
|
||||
/** A container for all the information required to checkout items and pay. */
|
||||
export type Checkout = Node & {
|
||||
__typename?: 'Checkout'
|
||||
/** The gift cards used on the checkout. */
|
||||
appliedGiftCards: Array<AppliedGiftCard>
|
||||
/**
|
||||
* The available shipping rates for this Checkout.
|
||||
* Should only be used when checkout `requiresShipping` is `true` and
|
||||
* the shipping address is valid.
|
||||
*/
|
||||
availableShippingRates?: Maybe<AvailableShippingRates>
|
||||
/** The date and time when the checkout was completed. */
|
||||
completedAt?: Maybe<Scalars['DateTime']>
|
||||
/** The date and time when the checkout was created. */
|
||||
createdAt: Scalars['DateTime']
|
||||
/** The currency code for the Checkout. */
|
||||
currencyCode: CurrencyCode
|
||||
/** A list of extra information that is added to the checkout. */
|
||||
customAttributes: Array<Attribute>
|
||||
/**
|
||||
* The customer associated with the checkout.
|
||||
* @deprecated This field will always return null. If you have an authentication token for the customer, you can use the `customer` field on the query root to retrieve it.
|
||||
*/
|
||||
customer?: Maybe<Customer>
|
||||
/** Discounts that have been applied on the checkout. */
|
||||
discountApplications: DiscountApplicationConnection
|
||||
/** The email attached to this checkout. */
|
||||
email?: Maybe<Scalars['String']>
|
||||
/** Globally unique identifier. */
|
||||
id: Scalars['ID']
|
||||
/** A list of line item objects, each one containing information about an item in the checkout. */
|
||||
lineItems: CheckoutLineItemConnection
|
||||
/** The sum of all the prices of all the items in the checkout. Duties, taxes, shipping and discounts excluded. */
|
||||
lineItemsSubtotalPrice: MoneyV2
|
||||
/** The note associated with the checkout. */
|
||||
note?: Maybe<Scalars['String']>
|
||||
/** The resulting order from a paid checkout. */
|
||||
order?: Maybe<Order>
|
||||
/** The Order Status Page for this Checkout, null when checkout is not completed. */
|
||||
orderStatusUrl?: Maybe<Scalars['URL']>
|
||||
/**
|
||||
* The amount left to be paid. This is equal to the cost of the line items, taxes and shipping minus discounts and gift cards.
|
||||
* @deprecated Use `paymentDueV2` instead
|
||||
*/
|
||||
paymentDue: Scalars['Money']
|
||||
/** The amount left to be paid. This is equal to the cost of the line items, duties, taxes and shipping minus discounts and gift cards. */
|
||||
paymentDueV2: MoneyV2
|
||||
/**
|
||||
* Whether or not the Checkout is ready and can be completed. Checkouts may
|
||||
* have asynchronous operations that can take time to finish. If you want
|
||||
* to complete a checkout or ensure all the fields are populated and up to
|
||||
* date, polling is required until the value is true.
|
||||
*/
|
||||
ready: Scalars['Boolean']
|
||||
/** States whether or not the fulfillment requires shipping. */
|
||||
requiresShipping: Scalars['Boolean']
|
||||
/** The shipping address to where the line items will be shipped. */
|
||||
shippingAddress?: Maybe<MailingAddress>
|
||||
/** The discounts that have been allocated onto the shipping line by discount applications. */
|
||||
shippingDiscountAllocations: Array<DiscountAllocation>
|
||||
/** Once a shipping rate is selected by the customer it is transitioned to a `shipping_line` object. */
|
||||
shippingLine?: Maybe<ShippingRate>
|
||||
/**
|
||||
* Price of the checkout before shipping and taxes.
|
||||
* @deprecated Use `subtotalPriceV2` instead
|
||||
*/
|
||||
subtotalPrice: Scalars['Money']
|
||||
/** Price of the checkout before duties, shipping and taxes. */
|
||||
subtotalPriceV2: MoneyV2
|
||||
/** Specifies if the Checkout is tax exempt. */
|
||||
taxExempt: Scalars['Boolean']
|
||||
/** Specifies if taxes are included in the line item and shipping line prices. */
|
||||
taxesIncluded: Scalars['Boolean']
|
||||
/**
|
||||
* The sum of all the prices of all the items in the checkout, taxes and discounts included.
|
||||
* @deprecated Use `totalPriceV2` instead
|
||||
*/
|
||||
totalPrice: Scalars['Money']
|
||||
/** The sum of all the prices of all the items in the checkout, duties, taxes and discounts included. */
|
||||
totalPriceV2: MoneyV2
|
||||
/**
|
||||
* The sum of all the taxes applied to the line items and shipping lines in the checkout.
|
||||
* @deprecated Use `totalTaxV2` instead
|
||||
*/
|
||||
totalTax: Scalars['Money']
|
||||
/** The sum of all the taxes applied to the line items and shipping lines in the checkout. */
|
||||
totalTaxV2: MoneyV2
|
||||
/** The date and time when the checkout was last updated. */
|
||||
updatedAt: Scalars['DateTime']
|
||||
/** The url pointing to the checkout accessible from the web. */
|
||||
webUrl: Scalars['URL']
|
||||
export type Checkout = {
|
||||
name: string
|
||||
currency: string
|
||||
support_email: string
|
||||
fields: any[]
|
||||
scripts: any[]
|
||||
accounts: string
|
||||
email_optin: boolean
|
||||
terms_policy?: string
|
||||
refund_policy?: string
|
||||
privacy_policy?: string
|
||||
theme?: stirng
|
||||
countries: any[]
|
||||
currencies: any[]
|
||||
payment_methods: any[]
|
||||
coupons: boolean
|
||||
giftcards: boolean
|
||||
|
||||
// __typename?: 'Checkout'
|
||||
// /** The gift cards used on the checkout. */
|
||||
// appliedGiftCards: Array<AppliedGiftCard>
|
||||
// /**
|
||||
// * The available shipping rates for this Checkout.
|
||||
// * Should only be used when checkout `requiresShipping` is `true` and
|
||||
// * the shipping address is valid.
|
||||
// */
|
||||
// availableShippingRates?: Maybe<AvailableShippingRates>
|
||||
// /** The date and time when the checkout was completed. */
|
||||
// completedAt?: Maybe<Scalars['DateTime']>
|
||||
// /** The date and time when the checkout was created. */
|
||||
// createdAt: Scalars['DateTime']
|
||||
// /** The currency code for the Checkout. */
|
||||
// currencyCode: CurrencyCode
|
||||
// /** A list of extra information that is added to the checkout. */
|
||||
// customAttributes: Array<Attribute>
|
||||
// /**
|
||||
// * The customer associated with the checkout.
|
||||
// * @deprecated This field will always return null. If you have an authentication token for the customer, you can use the `customer` field on the query root to retrieve it.
|
||||
// */
|
||||
// customer?: Maybe<Customer>
|
||||
// /** Discounts that have been applied on the checkout. */
|
||||
// discountApplications: DiscountApplicationConnection
|
||||
// /** The email attached to this checkout. */
|
||||
// email?: Maybe<Scalars['String']>
|
||||
// /** Globally unique identifier. */
|
||||
// id: Scalars['ID']
|
||||
// /** A list of line item objects, each one containing information about an item in the checkout. */
|
||||
// lineItems: CheckoutLineItemConnection
|
||||
// /** The sum of all the prices of all the items in the checkout. Duties, taxes, shipping and discounts excluded. */
|
||||
// lineItemsSubtotalPrice: MoneyV2
|
||||
// /** The note associated with the checkout. */
|
||||
// note?: Maybe<Scalars['String']>
|
||||
// /** The resulting order from a paid checkout. */
|
||||
// order?: Maybe<Order>
|
||||
// /** The Order Status Page for this Checkout, null when checkout is not completed. */
|
||||
// orderStatusUrl?: Maybe<Scalars['URL']>
|
||||
// /**
|
||||
// * The amount left to be paid. This is equal to the cost of the line items, taxes and shipping minus discounts and gift cards.
|
||||
// * @deprecated Use `paymentDueV2` instead
|
||||
// */
|
||||
// paymentDue: Scalars['Money']
|
||||
// /** The amount left to be paid. This is equal to the cost of the line items, duties, taxes and shipping minus discounts and gift cards. */
|
||||
// paymentDueV2: MoneyV2
|
||||
// /**
|
||||
// * Whether or not the Checkout is ready and can be completed. Checkouts may
|
||||
// * have asynchronous operations that can take time to finish. If you want
|
||||
// * to complete a checkout or ensure all the fields are populated and up to
|
||||
// * date, polling is required until the value is true.
|
||||
// */
|
||||
// ready: Scalars['Boolean']
|
||||
// /** States whether or not the fulfillment requires shipping. */
|
||||
// requiresShipping: Scalars['Boolean']
|
||||
// /** The shipping address to where the line items will be shipped. */
|
||||
// shippingAddress?: Maybe<MailingAddress>
|
||||
// /** The discounts that have been allocated onto the shipping line by discount applications. */
|
||||
// shippingDiscountAllocations: Array<DiscountAllocation>
|
||||
// /** Once a shipping rate is selected by the customer it is transitioned to a `shipping_line` object. */
|
||||
// shippingLine?: Maybe<ShippingRate>
|
||||
// /**
|
||||
// * Price of the checkout before shipping and taxes.
|
||||
// * @deprecated Use `subtotalPriceV2` instead
|
||||
// */
|
||||
// subtotalPrice: Scalars['Money']
|
||||
// /** Price of the checkout before duties, shipping and taxes. */
|
||||
// subtotalPriceV2: MoneyV2
|
||||
// /** Specifies if the Checkout is tax exempt. */
|
||||
// taxExempt: Scalars['Boolean']
|
||||
// /** Specifies if taxes are included in the line item and shipping line prices. */
|
||||
// taxesIncluded: Scalars['Boolean']
|
||||
// /**
|
||||
// * The sum of all the prices of all the items in the checkout, taxes and discounts included.
|
||||
// * @deprecated Use `totalPriceV2` instead
|
||||
// */
|
||||
// totalPrice: Scalars['Money']
|
||||
// /** The sum of all the prices of all the items in the checkout, duties, taxes and discounts included. */
|
||||
// totalPriceV2: MoneyV2
|
||||
// /**
|
||||
// * The sum of all the taxes applied to the line items and shipping lines in the checkout.
|
||||
// * @deprecated Use `totalTaxV2` instead
|
||||
// */
|
||||
// totalTax: Scalars['Money']
|
||||
// /** The sum of all the taxes applied to the line items and shipping lines in the checkout. */
|
||||
// totalTaxV2: MoneyV2
|
||||
// /** The date and time when the checkout was last updated. */
|
||||
// updatedAt: Scalars['DateTime']
|
||||
// /** The url pointing to the checkout accessible from the web. */
|
||||
// webUrl: Scalars['URL']
|
||||
}
|
||||
|
||||
/** A container for all the information required to checkout items and pay. */
|
||||
|
@ -1,6 +1,15 @@
|
||||
import * as Core from '@commerce/types'
|
||||
import { CheckoutLineItem } from './schema'
|
||||
|
||||
export type SwellImage = {
|
||||
file: {
|
||||
url: String
|
||||
height: Number
|
||||
width: Number
|
||||
}
|
||||
id: string
|
||||
}
|
||||
|
||||
export type SwellCart = {
|
||||
id: string
|
||||
account_id: number
|
||||
@ -21,9 +30,28 @@ export type SwellCart = {
|
||||
// TODO: add missing fields
|
||||
}
|
||||
|
||||
export type VariantResult = {
|
||||
export type SwellVariant = {
|
||||
id: string
|
||||
option_value_ids: string[]
|
||||
name: string
|
||||
price?: number
|
||||
stock_status?: string
|
||||
}
|
||||
|
||||
export interface ProductOptionValue {
|
||||
label: string
|
||||
hexColors?: string[]
|
||||
id: string
|
||||
}
|
||||
|
||||
export type ProductOptions = {
|
||||
id: string
|
||||
name: string
|
||||
variant: boolean
|
||||
values: ProductOptionValue[]
|
||||
required: boolean
|
||||
active: boolean
|
||||
attribute_id: string
|
||||
}
|
||||
|
||||
export interface SwellProduct {
|
||||
|
@ -1,19 +1,22 @@
|
||||
import { Product } from '@commerce/types'
|
||||
import { Customer } from '@commerce/types'
|
||||
import { Product, Customer } from '@commerce/types'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import {
|
||||
Product as ShopifyProduct,
|
||||
Checkout,
|
||||
CheckoutLineItemEdge,
|
||||
SelectedOption,
|
||||
ImageConnection,
|
||||
ProductVariantConnection,
|
||||
MoneyV2,
|
||||
ProductOption,
|
||||
} from '../schema'
|
||||
|
||||
import type { Cart, LineItem, SwellCustomer, SwellProduct } from '../types'
|
||||
import type {
|
||||
Cart,
|
||||
LineItem,
|
||||
SwellCustomer,
|
||||
SwellProduct,
|
||||
SwellImage,
|
||||
SwellVariant,
|
||||
ProductOptionValue,
|
||||
} from '../types'
|
||||
|
||||
const money = ({ amount, currencyCode }: MoneyV2) => {
|
||||
return {
|
||||
@ -22,15 +25,22 @@ const money = ({ amount, currencyCode }: MoneyV2) => {
|
||||
}
|
||||
}
|
||||
|
||||
type normalizedProductOption = {
|
||||
__typename?: string
|
||||
id: string
|
||||
displayName: string
|
||||
values: ProductOptionValue[]
|
||||
}
|
||||
|
||||
const normalizeProductOption = ({
|
||||
id,
|
||||
name: displayName,
|
||||
name: displayName = '',
|
||||
values,
|
||||
}: ProductOption) => {
|
||||
let returnValues = values.map((value) => {
|
||||
let output: any = {
|
||||
displayName,
|
||||
label: value.name,
|
||||
id: value?.id || id,
|
||||
}
|
||||
if (displayName === 'Color') {
|
||||
output = {
|
||||
@ -48,50 +58,52 @@ const normalizeProductOption = ({
|
||||
}
|
||||
}
|
||||
|
||||
type SwellImage = {
|
||||
file: {
|
||||
url: String
|
||||
height: Number
|
||||
width: Number
|
||||
}
|
||||
id: string
|
||||
}
|
||||
const normalizeProductImages = (images) => {
|
||||
const normalizeProductImages = (images: SwellImage[]) => {
|
||||
if (!images) {
|
||||
return [{ url: '/' }]
|
||||
}
|
||||
return images?.map(({ file, ...rest }: SwellImage) => ({
|
||||
url: file?.url,
|
||||
height: file?.height,
|
||||
width: file?.width,
|
||||
url: file?.url + '',
|
||||
height: Number(file?.height),
|
||||
width: Number(file?.width),
|
||||
...rest,
|
||||
}))
|
||||
}
|
||||
|
||||
const normalizeProductVariants = (variants) => {
|
||||
return variants?.map(({ id, name, price, sku }) => {
|
||||
const values = name
|
||||
.split(',')
|
||||
.map((i) => ({ name: i.trim(), label: i.trim() }))
|
||||
const normalizeProductVariants = (
|
||||
variants: SwellVariant[],
|
||||
productOptions: normalizedProductOption[]
|
||||
) => {
|
||||
return variants?.map(
|
||||
({ id, name, price, option_value_ids: optionValueIds }) => {
|
||||
const values = name
|
||||
.split(',')
|
||||
.map((i) => ({ name: i.trim(), label: i.trim() }))
|
||||
|
||||
const options = values.map((value) => {
|
||||
return normalizeProductOption({
|
||||
const options = optionValueIds.map((id) => {
|
||||
const matchingOption = productOptions.find((option) => {
|
||||
return option.values.find(
|
||||
(value: ProductOptionValue) => value.id == id
|
||||
)
|
||||
})
|
||||
return normalizeProductOption({
|
||||
id,
|
||||
name: matchingOption?.displayName ?? '',
|
||||
values,
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
values: [value],
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
sku: sku ?? id,
|
||||
price: price ?? null,
|
||||
listPrice: price ?? null,
|
||||
// requiresShipping: true,
|
||||
options,
|
||||
// sku: sku ?? id,
|
||||
price: price ?? null,
|
||||
listPrice: price ?? null,
|
||||
// requiresShipping: true,
|
||||
options,
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export function normalizeProduct(swellProduct: SwellProduct): Product {
|
||||
@ -108,10 +120,10 @@ export function normalizeProduct(swellProduct: SwellProduct): Product {
|
||||
const productOptions = options
|
||||
? options.map((o) => normalizeProductOption(o))
|
||||
: []
|
||||
const productVariants = variants ? normalizeProductVariants(variants) : []
|
||||
const productVariants = variants
|
||||
? normalizeProductVariants(variants, productOptions)
|
||||
: []
|
||||
|
||||
// ProductView.tsx assumes the existence of at least one product variant
|
||||
const emptyVariants = [{ options: [{ id: 123 }] }]
|
||||
const productImages = normalizeProductImages(images)
|
||||
const product = {
|
||||
...swellProduct,
|
||||
@ -120,10 +132,7 @@ export function normalizeProduct(swellProduct: SwellProduct): Product {
|
||||
vendor: '',
|
||||
path: `/${slug}`,
|
||||
images: productImages,
|
||||
variants:
|
||||
productVariants && productVariants.length
|
||||
? productVariants
|
||||
: emptyVariants,
|
||||
variants: productVariants,
|
||||
options: productOptions,
|
||||
price: {
|
||||
value,
|
||||
@ -167,12 +176,12 @@ function normalizeLineItem({
|
||||
}: CheckoutLineItemEdge): LineItem {
|
||||
const item = {
|
||||
id,
|
||||
variantId: String(variant?.id),
|
||||
productId: String(product?.id),
|
||||
variantId: variant?.id ?? '',
|
||||
productId: product?.id ?? '',
|
||||
name: product?.name ?? '',
|
||||
quantity,
|
||||
variant: {
|
||||
id: String(variant?.id),
|
||||
id: variant?.id ?? '',
|
||||
sku: variant?.sku ?? '',
|
||||
name: variant?.name!,
|
||||
image: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user