From 8b1218fc352a58e5e3ff1a527bb798c73b962fa4 Mon Sep 17 00:00:00 2001 From: Kristian Duda Date: Fri, 28 Jun 2024 08:16:08 +0200 Subject: [PATCH] wip --- lib/shopify/index.ts | 160 +++++++++++++---------------------------- lib/shopify/payload.ts | 5 ++ lib/shopify/types.ts | 4 +- next.config.js | 6 +- 4 files changed, 60 insertions(+), 115 deletions(-) diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts index d1793d651..4ab6802e5 100644 --- a/lib/shopify/index.ts +++ b/lib/shopify/index.ts @@ -1,6 +1,6 @@ -import { HIDDEN_PRODUCT_TAG, SHOPIFY_GRAPHQL_API_ENDPOINT, TAGS } from 'lib/constants'; -import { find } from 'lib/shopify/payload'; -import { Media, Option, Product } from 'lib/shopify/payload-types'; +import { SHOPIFY_GRAPHQL_API_ENDPOINT, TAGS } from 'lib/constants'; +import { find, findByID } from 'lib/shopify/payload'; +import { Media, Option, Product, Tag } from 'lib/shopify/payload-types'; import { isShopifyError } from 'lib/type-guards'; import { ensureStartsWith } from 'lib/utils'; import { revalidateTag } from 'next/cache'; @@ -15,11 +15,6 @@ import { import { getCartQuery } from './queries/cart'; import { getCollectionQuery, getCollectionsQuery } from './queries/collection'; import { getPageQuery, getPagesQuery } from './queries/page'; -import { - getProductQuery, - getProductRecommendationsQuery, - getProductsQuery -} from './queries/product'; import { Cart, Collection, @@ -30,6 +25,7 @@ import { Money, Page, ProductOption, + ProductVariant, ShopifyAddToCartOperation, ShopifyCart, ShopifyCartOperation, @@ -39,10 +35,6 @@ import { ShopifyCreateCartOperation, ShopifyPageOperation, ShopifyPagesOperation, - ShopifyProduct, - ShopifyProductOperation, - ShopifyProductRecommendationsOperation, - ShopifyProductsOperation, ShopifyRemoveFromCartOperation, ShopifyUpdateCartOperation } from './types'; @@ -156,48 +148,6 @@ const reshapeCollections = (collections: ShopifyCollection[]) => { return reshapedCollections; }; -const reshapeImages = (images: Connection, productTitle: string) => { - const flattened = removeEdgesAndNodes(images); - - return flattened.map((image) => { - const filename = image.url.match(/.*\/(.*)\..*/)[1]; - return { - ...image, - altText: image.altText || `${productTitle} - ${filename}` - }; - }); -}; - -const reshapeProduct = (product: ShopifyProduct, filterHiddenProducts: boolean = true) => { - if (!product || (filterHiddenProducts && product.tags.includes(HIDDEN_PRODUCT_TAG))) { - return undefined; - } - - const { images, variants, ...rest } = product; - - return { - ...rest, - images: reshapeImages(images, product.title), - variants: removeEdgesAndNodes(variants) - }; -}; - -const reshapeProducts = (products: ShopifyProduct[]) => { - const reshapedProducts = []; - - for (const product of products) { - if (product) { - const reshapedProduct = reshapeProduct(product); - - if (reshapedProduct) { - reshapedProducts.push(reshapedProduct); - } - } - } - - return reshapedProducts; -}; - export async function createCart(): Promise { const res = await shopifyFetch({ query: createCartMutation, @@ -282,7 +232,9 @@ export async function getCollection(handle: string): Promise { return { url: media.url!, - altText: media.alt + altText: media.alt, + width: media.width, + height: media.height }; }; @@ -293,24 +245,49 @@ type Price = { const reshapePrice = (price: Price): Money => { return { - amount: (price.amount / 100).toString(), + amount: price.amount.toString(), currencyCode: price.currencyCode }; }; -const reshapeP = (product: Product): ExProduct => { - const options: ProductOption[] = []; - const map = new Map(); +const reshapeOptions = (variants: Product['variants']): ProductOption[] => { + const options = new Map(); - product.variants.forEach((variant) => { + variants.forEach((variant) => { variant.selectedOptions?.forEach((selectedOption) => { const option = selectedOption.option as Option; - map.set(option.id, option.values); + options.set(option.id, option); }); }); - // console.log(map); + return Array.from(options, ([id, option]) => ({ + id, + name: option.name, + values: option.values.map((value) => value.label) + })); +}; +const reshapeVariants = (variants: Product['variants']): ProductVariant[] => { + return variants.map((variant) => ({ + id: variant.id!, + title: `${variant.price.amount} ${variant.price.currencyCode}`, + availableForSale: true, + selectedOptions: (variant.selectedOptions ?? []).map((selectedOption) => { + const option = selectedOption.option as Option; + return { + name: option.name, + value: option.values.find(({ value }) => value === selectedOption.value)?.label! + }; + }), + price: reshapePrice(variant.price) + })); +}; + +const reshapeTags = (tags: Tag[]): string[] => { + return tags.map((tag) => tag.name); +}; + +const reshapeProduct = (product: Product): ExProduct => { return { id: product.id, handle: product.id, @@ -318,20 +295,20 @@ const reshapeP = (product: Product): ExProduct => { title: product.title, description: product.description, descriptionHtml: product.description, - options, + options: reshapeOptions(product.variants), priceRange: { maxVariantPrice: reshapePrice(product.variants[0]?.price!), minVariantPrice: reshapePrice(product.variants[0]?.price!) }, - featuredImage: {} as any, + featuredImage: reshapeImage(product.media as Media), images: [], seo: { title: product.title, description: product.description }, - // tags: product.tags ?? [], - updatedAt: product.updatedAt, - createdAt: product.createdAt + tags: reshapeTags(product.tags as Tag[]), + variants: reshapeVariants(product.variants), + updatedAt: product.updatedAt }; }; @@ -344,19 +321,8 @@ export async function getCollectionProducts({ reverse?: boolean; sortKey?: string; }): Promise { - const m = await find('products', { - where: { - title: { - equals: 'test' - } - } - }); - - const products: ExProduct[] = m.docs.map(reshapeP); - - console.log(products); - - return products; + const products = await find('products', {}); + return products.docs.map(reshapeProduct); } export async function getCollections(): Promise { @@ -425,27 +391,12 @@ export async function getPages(): Promise { } export async function getProduct(handle: string): Promise { - const res = await shopifyFetch({ - query: getProductQuery, - tags: [TAGS.products], - variables: { - handle - } - }); - - return reshapeProduct(res.body.data.product, false); + const product = await findByID('products', handle); + return reshapeProduct(product); } export async function getProductRecommendations(productId: string): Promise { - const res = await shopifyFetch({ - query: getProductRecommendationsQuery, - tags: [TAGS.products], - variables: { - productId - } - }); - - return reshapeProducts(res.body.data.productRecommendations); + return []; } export async function getProducts({ @@ -457,17 +408,8 @@ export async function getProducts({ reverse?: boolean; sortKey?: string; }): Promise { - const res = await shopifyFetch({ - query: getProductsQuery, - tags: [TAGS.products], - variables: { - query, - reverse, - sortKey - } - }); - - return reshapeProducts(removeEdgesAndNodes(res.body.data.products)); + const products = await find('products', {}); + return products.docs.map(reshapeProduct); } // This is called from `app/api/revalidate.ts` so providers can control revalidation logic. diff --git a/lib/shopify/payload.ts b/lib/shopify/payload.ts index 4c2f5cca2..f7176d687 100644 --- a/lib/shopify/payload.ts +++ b/lib/shopify/payload.ts @@ -59,3 +59,8 @@ export const find = (collection: string, params: FindParams) => { const url = `${process.env.CMS_URL}/api/${collection}${query}`; return ajax>('GET', url); }; + +export const findByID = (collection: string, id: string) => { + const url = `${process.env.CMS_URL}/api/${collection}/${id}`; + return ajax('GET', url); +}; diff --git a/lib/shopify/types.ts b/lib/shopify/types.ts index ce753bbf7..e78721510 100644 --- a/lib/shopify/types.ts +++ b/lib/shopify/types.ts @@ -36,8 +36,8 @@ export type Collection = ShopifyCollection & { export type Image = { url: string; altText: string; - width?: number; - height?: number; + width?: number | null; + height?: number | null; }; export type Menu = { diff --git a/next.config.js b/next.config.js index 8bab35c40..9f02de99b 100644 --- a/next.config.js +++ b/next.config.js @@ -5,12 +5,10 @@ module.exports = { ignoreDuringBuilds: true }, images: { - formats: ['image/avif', 'image/webp'], remotePatterns: [ { - protocol: 'https', - hostname: 'cdn.shopify.com', - pathname: '/s/files/**' + protocol: 'http', + hostname: 'localhost' } ] },