diff --git a/packages/bigcommerce/src/api/fragments/product.ts b/packages/bigcommerce/src/api/fragments/product.ts index 734e0ab63..9435b0a7f 100644 --- a/packages/bigcommerce/src/api/fragments/product.ts +++ b/packages/bigcommerce/src/api/fragments/product.ts @@ -67,6 +67,9 @@ export const productInfoFragment = /* GraphQL */ ` altText isDefault } + prices { + ...productPrices + } } } } @@ -80,6 +83,15 @@ export const productInfoFragment = /* GraphQL */ ` } } } + customFields @include(if: $withCustomFields) { + edges { + node { + entityId + name + value + } + } + } localeMeta: metafields(namespace: $locale, keys: ["name", "description"]) @include(if: $hasLocale) { edges { diff --git a/packages/bigcommerce/src/api/operations/get-all-products.ts b/packages/bigcommerce/src/api/operations/get-all-products.ts index 2833ffcd7..b95e4c783 100644 --- a/packages/bigcommerce/src/api/operations/get-all-products.ts +++ b/packages/bigcommerce/src/api/operations/get-all-products.ts @@ -17,6 +17,7 @@ import { normalizeProduct } from '../../lib/normalize' export const getAllProductsQuery = /* GraphQL */ ` query getAllProducts( $hasLocale: Boolean = false + $withCustomFields: Boolean = false $locale: String = "null" $entityIds: [Int!] $first: Int = 10 diff --git a/packages/bigcommerce/src/api/operations/get-product.ts b/packages/bigcommerce/src/api/operations/get-product.ts index c7457de2a..0f736674a 100644 --- a/packages/bigcommerce/src/api/operations/get-product.ts +++ b/packages/bigcommerce/src/api/operations/get-product.ts @@ -12,6 +12,7 @@ import { normalizeProduct } from '../../lib/normalize' export const getProductQuery = /* GraphQL */ ` query getProduct( $hasLocale: Boolean = false + $withCustomFields: Boolean = false $locale: String = "null" $path: String! ) { @@ -98,6 +99,7 @@ export default function getAllProductPathsOperation({ const config = commerce.getConfig(cfg) const { locale } = config const variables: GetProductQueryVariables = { + ...vars, locale, hasLocale: !!locale, path: slug ? `/${slug}/` : vars.path!, diff --git a/packages/bigcommerce/src/commerce.config.json b/packages/bigcommerce/src/commerce.config.json index 89ce5625c..b7869f11d 100644 --- a/packages/bigcommerce/src/commerce.config.json +++ b/packages/bigcommerce/src/commerce.config.json @@ -2,6 +2,7 @@ "provider": "bigcommerce", "features": { "wishlist": true, - "customerAuth": true + "customerAuth": true, + "customFields": true } } diff --git a/packages/bigcommerce/src/lib/normalize.ts b/packages/bigcommerce/src/lib/normalize.ts index 059e3f871..9bd17c060 100644 --- a/packages/bigcommerce/src/lib/normalize.ts +++ b/packages/bigcommerce/src/lib/normalize.ts @@ -1,4 +1,4 @@ -import type { Product } from '../types/product' +import type { Product, ProductCustomField } from '../types/product' import type { Cart, BigcommerceCart, LineItem } from '../types/cart' import type { Page } from '../types/page' import type { BCCategory, Category } from '../types/site' @@ -18,10 +18,23 @@ function normalizeProductOption(productOption: any) { } } +function normalizeCustomFieldsValue(field: any): ProductCustomField { + const { + node: { entityId, name, value }, + } = field + + return { + key: String(entityId), + name, + value, + } +} + export function normalizeProduct(productNode: any): Product { const { entityId: id, productOptions, + customFields, prices, path, id: _, @@ -31,28 +44,63 @@ export function normalizeProduct(productNode: any): Product { return update(productNode, { id: { $set: String(id) }, images: { - $apply: ({ edges }: any) => - edges?.map(({ node: { urlOriginal, altText, ...rest } }: any) => ({ + $apply: ({ edges }: any) => [ + ...edges?.map(({ node: { urlOriginal, altText, ...rest } }: any) => ({ url: urlOriginal, alt: altText, ...rest, })), + + ...productNode.variants?.edges + ?.map(({ node: { defaultImage } }: any) => + defaultImage + ? { url: defaultImage.urlOriginal, alt: defaultImage.altText } + : null + ) + .filter(Boolean), + ], }, + variants: { $apply: ({ edges }: any) => - edges?.map(({ node: { entityId, productOptions, ...rest } }: any) => ({ - id: entityId, - options: productOptions?.edges - ? productOptions.edges.map(normalizeProductOption) - : [], - ...rest, - })), + edges?.map( + ({ + node: { entityId, productOptions, prices, defaultImage, ...rest }, + }: any) => ({ + id: entityId, + ...(defaultImage && { + image: { + url: defaultImage.urlOriginal, + alt: defaultImage.altText, + }, + }), + price: { + value: prices?.price.value, + currencyCode: prices?.price.currencyCode, + ...(prices?.salePrice?.value && { + salePrice: prices?.salePrice.value, + }), + ...(prices?.retailPrice?.value && { + retailPrice: prices?.retailPrice.value, + }), + }, + options: productOptions?.edges + ? productOptions.edges.map(normalizeProductOption) + : [], + ...rest, + }) + ), }, options: { - $set: productOptions.edges + $set: productOptions?.edges ? productOptions?.edges.map(normalizeProductOption) : [], }, + customFields: { + $set: customFields?.edges + ? customFields?.edges.map(normalizeCustomFieldsValue) + : [], + }, brand: { $apply: (brand: any) => (brand?.entityId ? brand?.entityId : null), }, @@ -63,6 +111,10 @@ export function normalizeProduct(productNode: any): Product { $set: { value: prices?.price.value, currencyCode: prices?.price.currencyCode, + ...(prices?.salePrice?.value && { salePrice: prices?.salePrice.value }), + ...(prices?.retailPrice?.value && { + retailPrice: prices?.retailPrice.value, + }), }, }, $unset: ['entityId'], diff --git a/packages/commerce/src/types/product.ts b/packages/commerce/src/types/product.ts index 9676a3a07..490d57201 100644 --- a/packages/commerce/src/types/product.ts +++ b/packages/commerce/src/types/product.ts @@ -35,11 +35,14 @@ export type ProductVariant = { image?: ProductImage } -export type ProductMetafield = { +export type ProductCustomField = { key: string + name: string value: string - description?: string + type?: string + htmlValue?: string + description?: string } export type Product = { @@ -56,7 +59,7 @@ export type Product = { options: ProductOption[] vendor?: string seo?: SEO - metafields?: ProductMetafield[] + customFields?: ProductCustomField[] } export type SearchProductsBody = { @@ -108,5 +111,5 @@ export type GetAllProductsOperation = { export type GetProductOperation = { data: { product?: T['product'] } - variables: { slug?: string; path?: string; withMetafields?: boolean } + variables: { slug?: string; path?: string; withCustomFields?: boolean } } diff --git a/packages/shopify/package.json b/packages/shopify/package.json index 8f7d11cd2..ba14ea1f7 100644 --- a/packages/shopify/package.json +++ b/packages/shopify/package.json @@ -51,6 +51,7 @@ "dependencies": { "@vercel/commerce": "^0.0.1", "@vercel/fetch": "^6.1.1", + "humanize-string": "^3.0.0", "lodash.debounce": "^4.0.8" }, "peerDependencies": { diff --git a/packages/shopify/schema.d.ts b/packages/shopify/schema.d.ts index b13927934..a89d1db00 100644 --- a/packages/shopify/schema.d.ts +++ b/packages/shopify/schema.d.ts @@ -1283,6 +1283,8 @@ export enum CheckoutErrorCode { GiftCardUnusable = 'GIFT_CARD_UNUSABLE', /** The input value should be greater than or equal to the minimum value allowed. */ GreaterThanOrEqualTo = 'GREATER_THAN_OR_EQUAL_TO', + /** Higher value discount applied. */ + HigherValueDiscountApplied = 'HIGHER_VALUE_DISCOUNT_APPLIED', /** The input value is invalid. */ Invalid = 'INVALID', /** Cannot specify country and presentment currency code. */ @@ -6867,47 +6869,6 @@ export type CustomerAccessTokenFragment = { expiresAt: any } -type Media_ExternalVideo_Fragment = { - __typename?: 'ExternalVideo' - mediaContentType: MediaContentType - alt?: string | null - previewImage?: { __typename?: 'Image'; url: any } | null -} - -type Media_MediaImage_Fragment = { - __typename?: 'MediaImage' - id: string - mediaContentType: MediaContentType - alt?: string | null - image?: { - __typename?: 'Image' - url: any - width?: number | null - height?: number | null - } | null - previewImage?: { __typename?: 'Image'; url: any } | null -} - -type Media_Model3d_Fragment = { - __typename?: 'Model3d' - mediaContentType: MediaContentType - alt?: string | null - previewImage?: { __typename?: 'Image'; url: any } | null -} - -type Media_Video_Fragment = { - __typename?: 'Video' - mediaContentType: MediaContentType - alt?: string | null - previewImage?: { __typename?: 'Image'; url: any } | null -} - -export type MediaFragment = - | Media_ExternalVideo_Fragment - | Media_MediaImage_Fragment - | Media_Model3d_Fragment - | Media_Video_Fragment - export type ProductCardFragment = { __typename?: 'Product' id: string @@ -7849,7 +7810,7 @@ export type GetPageQuery = { export type GetProductBySlugQueryVariables = Exact<{ slug: Scalars['String'] - withMetafields?: InputMaybe + withCustomFields?: InputMaybe }> export type GetProductBySlugQuery = { diff --git a/packages/shopify/schema.graphql b/packages/shopify/schema.graphql index 527032ea1..468f469c8 100644 --- a/packages/shopify/schema.graphql +++ b/packages/shopify/schema.graphql @@ -2175,6 +2175,11 @@ enum CheckoutErrorCode { """ GREATER_THAN_OR_EQUAL_TO + """ + Higher value discount applied. + """ + HIGHER_VALUE_DISCOUNT_APPLIED + """ The input value is invalid. """ diff --git a/packages/shopify/src/api/operations/get-all-products.ts b/packages/shopify/src/api/operations/get-all-products.ts index 22d4449c0..75e363816 100644 --- a/packages/shopify/src/api/operations/get-all-products.ts +++ b/packages/shopify/src/api/operations/get-all-products.ts @@ -2,13 +2,17 @@ import type { OperationContext, OperationOptions, } from '@vercel/commerce/api/operations' -import { GetAllProductsOperation } from '../../types/product' + +import type { GetAllProductsOperation } from '../../types/product' + import { GetAllProductsQuery, GetAllProductsQueryVariables, Product as ShopifyProduct, } from '../../../schema' + import type { ShopifyConfig, Provider } from '..' + import { normalizeProduct, getAllProductsQuery } from '../../utils' export default function getAllProductsOperation({ diff --git a/packages/shopify/src/api/operations/get-product.ts b/packages/shopify/src/api/operations/get-product.ts index 8a9ce35b5..8a239a2df 100644 --- a/packages/shopify/src/api/operations/get-product.ts +++ b/packages/shopify/src/api/operations/get-product.ts @@ -61,7 +61,7 @@ export default function getProductOperation({ return { ...(productByHandle && { - product: normalizeProduct(productByHandle as ShopifyProduct), + product: normalizeProduct(productByHandle as ShopifyProduct, locale), }), } } diff --git a/packages/shopify/src/commerce.config.json b/packages/shopify/src/commerce.config.json index 29fdd8fc6..43342ac09 100644 --- a/packages/shopify/src/commerce.config.json +++ b/packages/shopify/src/commerce.config.json @@ -3,6 +3,6 @@ "features": { "wishlist": false, "customerAuth": true, - "metafields": true + "customFields": true } } diff --git a/packages/shopify/src/types/product.ts b/packages/shopify/src/types/product.ts index 731225dfa..244c16c01 100644 --- a/packages/shopify/src/types/product.ts +++ b/packages/shopify/src/types/product.ts @@ -42,10 +42,10 @@ export type MetaieldTypes = export type MetafieldType = LiteralUnion -export type ProductMetafield = Core.ProductMetafield & { +export type ProductCustomField = Core.ProductCustomField & { type?: MetafieldType } export type Product = Core.Product & { - metafields?: ProductMetafield[] + metafields?: ProductCustomField[] } diff --git a/packages/shopify/src/utils/fragments/media-fragment.ts b/packages/shopify/src/utils/fragments/media-fragment.ts deleted file mode 100644 index ad5c96439..000000000 --- a/packages/shopify/src/utils/fragments/media-fragment.ts +++ /dev/null @@ -1,36 +0,0 @@ -export const mediaFragment = /* GraphQL */ ` - fragment Media on Media { - mediaContentType - alt - previewImage { - url - } - ... on MediaImage { - id - image { - url - width - height - } - } - # ... on Video { - # id - # sources { - # mimeType - # url - # } - # } - # ... on Model3d { - # id - # sources { - # mimeType - # url - # } - # } - # ... on ExternalVideo { - # id - # embedUrl - # host - # } - } -` diff --git a/packages/shopify/src/utils/helpers.ts b/packages/shopify/src/utils/helpers.ts index 30267a8f6..ab0f810da 100644 --- a/packages/shopify/src/utils/helpers.ts +++ b/packages/shopify/src/utils/helpers.ts @@ -1,5 +1,18 @@ import Cookies, { CookieAttributes } from 'js-cookie' -import { SearchProductsBody } from '../types/product' + +import type { + CartLineInput, + CollectionEdge, + CartCreateMutation, + CartDetailsFragment, + CartCreateMutationVariables, + GetAllProductVendorsQuery, + GetAllProductVendorsQueryVariables, +} from '../../schema' + +import type { Category } from '../types/site' +import type { MetafieldType, SearchProductsBody } from '../types/product' +import type { FetcherOptions } from '@vercel/commerce/utils/types' import { SHOPIFY_CART_URL_COOKIE, @@ -8,6 +21,109 @@ import { SHOPIFY_CUSTOMER_TOKEN_COOKIE, } from '../const' +import { ShopifyConfig } from '../api' +import { normalizeCategory } from './normalize' +import { throwUserErrors } from './throw-user-errors' +import { cartCreateMutation } from './mutations/cart-mutations' +import { getAllProductVendors, getSiteCollectionsQuery } from './queries' + +export const cartCreate = async ( + fetch: (options: FetcherOptions) => Promise, + lines?: Array | CartLineInput +): Promise => { + const { cartCreate } = await fetch< + CartCreateMutation, + CartCreateMutationVariables + >({ + query: cartCreateMutation, + variables: { + input: { + lines, + }, + }, + }) + + const cart = cartCreate?.cart + + throwUserErrors(cartCreate?.userErrors) + + if (cart?.id) { + const options = { + expires: SHOPIFY_COOKIE_EXPIRE, + } + Cookies.set(SHOPIFY_CART_ID_COOKIE, cart.id, options) + } + + setCartUrlCookie(cart?.checkoutUrl) + + return cart +} + +export const getCategories = async ({ + fetch, + locale, +}: ShopifyConfig): Promise => { + const { data } = await fetch( + getSiteCollectionsQuery, + { + variables: { + first: 250, + }, + }, + { + ...(locale && { + headers: { + 'Accept-Language': locale, + }, + }), + } + ) + + return ( + data.collections?.edges?.map(({ node }: CollectionEdge) => + normalizeCategory(node) + ) ?? [] + ) +} + +export type Brand = { + entityId: string + name: string + path: string +} + +export type BrandEdge = { + node: Brand +} + +export type Brands = BrandEdge[] + +export const getBrands = async ( + config: ShopifyConfig +): Promise => { + const { data } = await config.fetch< + GetAllProductVendorsQuery, + GetAllProductVendorsQueryVariables + >(getAllProductVendors, { + variables: { + first: 250, + }, + }) + + let vendorsStrings = data.products.edges.map(({ node: { vendor } }) => vendor) + + return [...new Set(vendorsStrings)].map((v) => { + const id = v.replace(/\s+/g, '-').toLowerCase() + return { + node: { + entityId: id, + name: v, + path: `brands/${id}`, + }, + } + }) +} + export const setCartUrlCookie = (cartUrl: string) => { if (cartUrl) { const oldCookie = Cookies.get(SHOPIFY_CART_URL_COOKIE) @@ -27,34 +143,28 @@ export const getSortVariables = ( sort?: string, isCategory: boolean = false ) => { - let output = {} switch (sort) { case 'price-asc': - output = { + return { sortKey: 'PRICE', reverse: false, } - break case 'price-desc': - output = { + return { sortKey: 'PRICE', reverse: true, } - break case 'trending-desc': - output = { + return { sortKey: 'BEST_SELLING', reverse: false, } - break case 'latest-desc': - output = { + return { sortKey: isCategory ? 'CREATED' : 'CREATED_AT', reverse: true, } - break } - return output } export const getSearchVariables = ({ @@ -102,3 +212,92 @@ export const setCustomerToken = ( ) } } + +export const parseJson = (value: string): any => { + try { + return JSON.parse(value) + } catch (e) { + return value + } +} + +const unitConversion: Record = { + MILLIMETERS: 'millimeter', + CENTIMETERS: 'centimeter', + METERS: 'meter', + + MILLILITERS: 'milliliter', + LITERS: 'liter', + FLUID_OUNCES: 'fluid-ounce', + IMPERIAL_FLUID_OUNCES: 'fluid-ounce', + GALLONS: 'gallon', + + KILOGRAMS: 'kilogram', + GRAMS: 'gram', + OUNCES: 'ounce', + POUNDS: 'pound', +} + +export const getMeasurment = (input: string, locale: string = 'en-US') => { + try { + let { unit, value } = JSON.parse(input) + + return new Intl.NumberFormat(locale, { + unit: unitConversion[unit], + style: 'unit', + }).format(parseFloat(value)) + } catch (e) { + console.error(e) + return input + } +} + +export const getMetafieldValue = ( + type: MetafieldType, + value: string, + locale: string = 'en-US' +) => { + switch (type) { + case 'boolean': + return value === 'true' ? '✓' : 'No' + case 'number_integer': + return parseInt(value).toLocaleString(locale) + case 'number_decimal': + return parseFloat(value).toLocaleString(locale) + case 'date': + return Intl.DateTimeFormat(locale, { + dateStyle: 'medium', + }).format(new Date(value)) + case 'date_time': + return Intl.DateTimeFormat(locale, { + dateStyle: 'medium', + timeStyle: 'long', + }).format(new Date(value)) + case 'dimension': + case 'volume': + case 'weight': + return getMeasurment(value, locale) + case 'rating': + const { scale_max, value: val } = JSON.parse(value) + return Array.from({ length: scale_max }, (_, i) => + i <= val - 1 ? '★' : '☆' + ).join('') + case 'color': + return `
` + case 'url': + return `${value}` + case 'multi_line_text_field': + return value + .split('\n') + .map((line) => `

${line}

`) + .join('') + case 'json': + case 'single_line_text_field': + case 'product_reference': + case 'page_reference': + case 'variant_reference': + case 'file_reference': + default: + return value + } +} diff --git a/packages/shopify/src/utils/index.ts b/packages/shopify/src/utils/index.ts index ef373053d..bd0a927b3 100644 --- a/packages/shopify/src/utils/index.ts +++ b/packages/shopify/src/utils/index.ts @@ -1,10 +1,11 @@ export { throwUserErrors } from './throw-user-errors' export { handleFetchResponse } from './handle-fetch-response' -export { cartCreate } from './cart-create' -export { handleLogin, handleAutomaticLogin } from './handle-login' -export { handleAccountActivation } from './handle-account-activation' -export { getCategories } from './get-categories' -export { getBrands } from './get-brands' + +export { + handleLogin, + handleAutomaticLogin, + handleAccountActivation, +} from './handle-login' export * from './helpers' export * from './queries' diff --git a/packages/shopify/src/utils/normalize.ts b/packages/shopify/src/utils/normalize.ts index 5782d2f34..038529371 100644 --- a/packages/shopify/src/utils/normalize.ts +++ b/packages/shopify/src/utils/normalize.ts @@ -1,9 +1,9 @@ import type { Page } from '../types/page' -import type { Product, ProductPrice } from '../types/product' +import type { MetafieldType, Product, ProductPrice } from '../types/product' import type { Cart, LineItem } from '../types/cart' import type { Category } from '../types/site' -import { +import type { Product as ShopifyProduct, SelectedOption, ImageConnection, @@ -14,12 +14,15 @@ import { PageEdge, Collection, CartDetailsFragment, - MetafieldConnection, } from '../../schema' -import { colorMap } from './colors' + +import humanizeString from 'humanize-string' import { CommerceError } from '@vercel/commerce/utils/errors' -type MoneyProps = MoneyV2 & { retailPrice?: string } +import { colorMap } from './colors' +import { getMetafieldValue, parseJson } from './helpers' + +type MoneyProps = MoneyV2 & { retailPrice?: string | number } const money = (money: MoneyProps): ProductPrice => { const { amount, currencyCode, retailPrice } = money || { currencyCode: 'USD' } @@ -101,20 +104,24 @@ const normalizeProductVariants = (variants: ProductVariantConnection) => { ) } -export function normalizeProduct({ - id, - title: name, - vendor, - images, - variants, - description, - descriptionHtml, - handle, - options, - metafields, - ...rest -}: ShopifyProduct): Product { +export function normalizeProduct( + { + id, + title: name, + vendor, + images, + variants, + description, + descriptionHtml, + handle, + options, + metafields, + ...rest + }: ShopifyProduct, + locale?: string +): Product { const variant = variants?.nodes?.[0] + return { id, name, @@ -132,7 +139,14 @@ export function normalizeProduct({ .filter((o) => o.name !== 'Title') // By default Shopify adds a 'Title' name when there's only one option. We don't need it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095 .map((o) => normalizeProductOption(o)) : [], - metafields: metafields?.nodes?.map((m) => m) || [], + customFields: + metafields?.nodes?.map(({ key, type, value }) => ({ + key, + name: humanizeString(key), + type, + value, + htmlValue: normalizeMetafieldValue(type, value, locale), + })) || [], ...(description && { description }), ...(descriptionHtml && { descriptionHtml }), ...rest, @@ -212,3 +226,18 @@ export const normalizeCategory = ({ slug: handle, path: `/${handle}`, }) +export const normalizeMetafieldValue = ( + type: MetafieldType, + value: string, + locale?: string +) => { + if (type.startsWith('list.')) { + const arr = parseJson(value) + return Array.isArray(arr) + ? arr + .map((v) => getMetafieldValue(type.split('.')[1], v, locale)) + .join(' • ') + : value + } + return getMetafieldValue(type, value, locale) +} diff --git a/packages/shopify/src/utils/queries/get-product-query.ts b/packages/shopify/src/utils/queries/get-product-query.ts index a91f3ab9e..d6976f065 100644 --- a/packages/shopify/src/utils/queries/get-product-query.ts +++ b/packages/shopify/src/utils/queries/get-product-query.ts @@ -1,5 +1,5 @@ export const getProductQuery = /* GraphQL */ ` - query getProductBySlug($slug: String!, $withMetafields: Boolean = false) { + query getProductBySlug($slug: String!, $withCustomFields: Boolean = false) { productByHandle(handle: $slug) { id handle @@ -46,7 +46,7 @@ export const getProductQuery = /* GraphQL */ ` } } } - metafields(first: 25) @include(if: $withMetafields) { + metafields(first: 25) @include(if: $withCustomFields) { nodes { key value diff --git a/site/components/product/ProductCustomFields/ProductCustomFields.tsx b/site/components/product/ProductCustomFields/ProductCustomFields.tsx new file mode 100644 index 000000000..496bcf5e4 --- /dev/null +++ b/site/components/product/ProductCustomFields/ProductCustomFields.tsx @@ -0,0 +1,30 @@ +import type { ProductCustomField } from '@framework/types/product' + +const ProductCustomFields = ({ fields }: { fields: ProductCustomField[] }) => { + return ( +
    + {fields.map((m) => ( +
  • + + {m.name} + + : + {m.htmlValue ? ( +
    + ) : ( + {m.value} + )} +
  • + ))} +
+ ) +} + +export default ProductCustomFields diff --git a/site/components/product/ProductCustomFields/index.ts b/site/components/product/ProductCustomFields/index.ts new file mode 100644 index 000000000..b0d6f0bba --- /dev/null +++ b/site/components/product/ProductCustomFields/index.ts @@ -0,0 +1 @@ +export { default } from './ProductCustomFields' diff --git a/site/components/product/ProductSidebar/ProductSidebar.tsx b/site/components/product/ProductSidebar/ProductSidebar.tsx index 93e08d823..5c61037c1 100644 --- a/site/components/product/ProductSidebar/ProductSidebar.tsx +++ b/site/components/product/ProductSidebar/ProductSidebar.tsx @@ -5,6 +5,7 @@ import { ProductOptions } from '@components/product' import { Button, Text, Rating, Collapse, useUI } from '@components/ui' import { useProduct } from '../context' +import ProductCustomFields from '../ProductCustomFields' interface ProductSidebarProps { className?: string } @@ -59,23 +60,6 @@ const ProductSidebar: FC = ({ className }) => { )}
- {process.env.COMMERCE_METAFIELDS_ENABLED && - product.metafields && - product.metafields?.length > 0 && ( - -
    - {product.metafields.map((m) => ( -
  • - {m.key}: - {m.value} -
  • - ))} -
-
- )} This is a limited edition production run. Printing starts when the drop ends. @@ -85,6 +69,13 @@ const ProductSidebar: FC = ({ className }) => { drop ends. Reminder: Bad Boys For Life. Shipping may take 10+ days due to COVID-19. + {process.env.COMMERCE_CUSTOMFIELDS_ENABLED && + product.customFields && + product.customFields.length > 0 && ( + + + + )}
) diff --git a/site/pages/product/[slug].tsx b/site/pages/product/[slug].tsx index c3fd70678..ff734bbcf 100644 --- a/site/pages/product/[slug].tsx +++ b/site/pages/product/[slug].tsx @@ -20,7 +20,7 @@ export async function getStaticProps({ const productPromise = commerce.getProduct({ variables: { slug: params!.slug, - withMetafields: Boolean(process.env.COMMERCE_METAFIELDS_ENABLED), + withCustomFields: Boolean(process.env.COMMERCE_CUSTOMFIELDS_ENABLED), }, config, preview, diff --git a/yarn.lock b/yarn.lock index 1dd65d651..f460cd4e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2853,6 +2853,11 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== +decamelize@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-6.0.0.tgz#8cad4d916fde5c41a264a43d0ecc56fe3d31749e" + integrity sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -3986,6 +3991,13 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +humanize-string@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/humanize-string/-/humanize-string-3.0.0.tgz#4ea0ef1daf1d23fd8d8c7864adf0117f74939455" + integrity sha512-jhWD2GAZRMELz0IEIfqpEdi0M4CMQF1GpJpBYIopFN6wT+78STiujfQTKcKqZzOJgUkIgJSo2xFeHdsg922JZQ== + dependencies: + decamelize "^6.0.0" + husky@^7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535"