feat: first step of adding core charge functionality

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe
2024-04-24 16:38:08 +07:00
parent 649a54891c
commit e3f564ca77
12 changed files with 412 additions and 28 deletions

View File

@@ -44,6 +44,12 @@ const productFragment = /* GraphQL */ `
amount
currencyCode
}
coreCharge: metafield(namespace: "custom", key: "core_charge") {
value
}
waiverAvailable: metafield(namespace: "custom", key: "waiver_available") {
value
}
}
}
}

View File

@@ -1,6 +1,6 @@
import { HIDDEN_PRODUCT_TAG, SHOPIFY_GRAPHQL_API_ENDPOINT, TAGS } from 'lib/constants';
import { isShopifyError } from 'lib/type-guards';
import { ensureStartsWith, normalizeUrl } from 'lib/utils';
import { ensureStartsWith, normalizeUrl, parseMetaFieldValue } from 'lib/utils';
import { revalidateTag } from 'next/cache';
import { headers } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';
@@ -29,8 +29,10 @@ import {
Connection,
Image,
Menu,
Money,
Page,
Product,
ProductVariant,
ShopifyAddToCartOperation,
ShopifyCart,
ShopifyCartOperation,
@@ -45,6 +47,7 @@ import {
ShopifyProduct,
ShopifyProductOperation,
ShopifyProductRecommendationsOperation,
ShopifyProductVariant,
ShopifyProductsOperation,
ShopifyRemoveFromCartOperation,
ShopifyUpdateCartOperation
@@ -128,7 +131,13 @@ const reshapeCart = (cart: ShopifyCart): Cart => {
return {
...cart,
lines: removeEdgesAndNodes(cart.lines)
lines: removeEdgesAndNodes(cart.lines).map((lineItem) => ({
...lineItem,
merchandise: {
...lineItem.merchandise,
product: reshapeProduct(lineItem.merchandise.product)
}
}))
};
};
@@ -171,6 +180,14 @@ const reshapeImages = (images: Connection<Image>, productTitle: string) => {
});
};
const reshapeVariants = (variants: ShopifyProductVariant[]): ProductVariant[] => {
return variants.map((variant) => ({
...variant,
coreCharge: parseMetaFieldValue<Money>(variant.coreCharge),
waiverAvailable: parseMetaFieldValue<boolean>(variant.waiverAvailable)
}));
};
const reshapeProduct = (product: ShopifyProduct, filterHiddenProducts: boolean = true) => {
if (!product || (filterHiddenProducts && product.tags.includes(HIDDEN_PRODUCT_TAG))) {
return undefined;
@@ -181,7 +198,7 @@ const reshapeProduct = (product: ShopifyProduct, filterHiddenProducts: boolean =
return {
...rest,
images: reshapeImages(images, product.title),
variants: removeEdgesAndNodes(variants)
variants: reshapeVariants(removeEdgesAndNodes(variants))
};
};

View File

@@ -82,6 +82,13 @@ export type ProductVariant = {
value: string;
}[];
price: Money;
coreCharge: Money | null;
waiverAvailable: boolean | null;
};
export type ShopifyProductVariant = Omit<ProductVariant, 'coreCharge' | 'waiverAvailable'> & {
coreCharge: { value: string } | null;
waiverAvailable: { value: string };
};
export type SEO = {
@@ -121,7 +128,7 @@ export type ShopifyProduct = {
maxVariantPrice: Money;
minVariantPrice: Money;
};
variants: Connection<ProductVariant>;
variants: Connection<ShopifyProductVariant>;
featuredImage: Image;
images: Connection<Image>;
seo: SEO;

View File

@@ -47,3 +47,11 @@ export function cn(...inputs: ClassValue[]) {
export function normalizeUrl(domain: string, url: string) {
return url.replace(domain, '').replace('/collections', '/search').replace('/pages', '');
}
export const parseMetaFieldValue = <T>(field: { value: string } | null): T | null => {
try {
return JSON.parse(field?.value || '{}');
} catch (error) {
return null;
}
};