commerce/lib/shopify/index.ts
2023-08-14 18:07:07 +02:00

322 lines
7.5 KiB
TypeScript

// @ts-ignore
import {
mockShopifyProduct,
mockCartItem,
mockShopifyCart,
winterCollection,
summerCollection,
europeCollection,
collections,
pages
} from './mock';
import {
Cart,
Collection,
Connection,
Image,
Menu,
Page,
Product,
ShopifyCart,
ShopifyCollection,
ShopifyCollectionsOperation,
ShopifyProduct
} from './types';
import { getCollectionsQuery } from './queries/collection';
import { TAGS } from '../constants';
import { shopifyFetch } from './index_old';
import { adventureProductNodes, getProductByHandle, getProductNodesByKeyword } from './adventures';
const HIDDEN_PRODUCT_TAG = 'hidden';
// Helper function to simulate a fetch response
// @ts-ignore
const mockFetchResponse = (data) => ({
body: {
data
}
});
// @ts-ignore
const removeEdgesAndNodes = (connection) => {
if (!connection?.edges) {
return connection;
}
return connection?.edges ? connection?.edges.map((edge: any) => edge.node) : [];
};
export const createCart = async (): Promise<Cart> => {
const res = mockFetchResponse({
cartCreate: {
cart: mockShopifyCart
}
});
return reshapeCart(res.body.data.cartCreate.cart);
};
export const addToCart = async (
cartId: string,
lines: { merchandiseId: string; quantity: number }[]
): Promise<Cart> => {
const res = mockFetchResponse({
cartLinesAdd: {
cart: mockShopifyCart
}
});
return reshapeCart(res.body.data.cartLinesAdd.cart);
};
export const removeFromCart = async (cartId: string, lineIds: string[]): Promise<Cart> => {
const res = mockFetchResponse({
cartLinesRemove: {
cart: mockShopifyCart
}
});
return reshapeCart(res.body.data.cartLinesRemove.cart);
};
export const updateCart = async (
cartId: string,
lines: { id: string; merchandiseId: string; quantity: number }[]
): Promise<Cart> => {
const res = mockFetchResponse({
cartLinesUpdate: {
cart: mockShopifyCart
}
});
return reshapeCart(res.body.data.cartLinesUpdate.cart);
};
export const getCart = async (cartId: string): Promise<Cart | undefined> => {
const res = mockFetchResponse({
cart: mockShopifyCart
});
return reshapeCart(res.body.data.cart);
};
export const getCollection = async (handle: string): Promise<Collection | undefined> => {
const res = mockFetchResponse({
collection: collections.find((collection) => collection.handle === handle)
});
return reshapeCollection(res.body.data.collection);
};
export const getCollectionProducts = async ({
collection,
reverse,
sortKey
}: {
collection: string;
reverse?: boolean;
sortKey?: string;
}): Promise<Product[]> => {
const res = mockFetchResponse({
collection: {
products: {
edges: getProductNodesByKeyword(collection)
}
}
});
return reshapeProducts(removeEdgesAndNodes(res.body.data.collection.products));
};
export async function getCollections(): Promise<Collection[]> {
// const res = await shopifyFetch<ShopifyCollectionsOperation>({
// query: getCollectionsQuery,
// tags: [TAGS.collections]
// });
const res = mockFetchResponse({
collections: {
edges: [{ node: winterCollection }, { node: summerCollection }, { node: europeCollection }]
}
});
const shopifyCollections = removeEdgesAndNodes(res.body?.data?.collections);
const collections = [
{
handle: '',
title: 'All',
description: 'All products',
seo: {
title: 'All',
description: 'All products'
},
path: '/search/',
updatedAt: new Date().toISOString()
},
// Filter out the `hidden` collections.
// Collections that start with `hidden-*` need to be hidden on the search page.
...reshapeCollections(shopifyCollections).filter(
(collection) => !collection.handle.startsWith('hidden')
)
];
return collections;
}
export const getMenu = async (handle: string): Promise<Menu[]> => {
const res = mockFetchResponse({
menu: {
items: [
{
title: 'Home',
path: '/'
},
{
title: 'About',
path: '/about'
},
{
title: 'Terms & Conditions',
path: '/tc'
},
{
title: 'Shipping & Return Policy',
path: '/sr'
},
{
title: 'Privacy Policy',
path: '/pp'
},
{
title: 'FAQ',
path: '/faq'
}
]
}
});
return res.body.data.menu.items;
};
export const getPage = async (handle: string): Promise<Page> => {
const res = mockFetchResponse({
pageByHandle: pages.find((page) => page.handle === handle)
});
return res.body.data.pageByHandle;
};
export const getPages = async (): Promise<Page[]> => {
return pages;
};
export const getProduct = async (handle: string): Promise<Product | undefined> => {
const res = mockFetchResponse({
product: getProductByHandle(handle)
});
return reshapeProduct(res.body.data.product, false);
};
export const getProductRecommendations = async (productId: string): Promise<Product[]> => {
const res = mockFetchResponse({
productRecommendations: [
getProductByHandle('climbing-new-zealand'),
getProductByHandle('ski-touring-mont-blanc'),
getProductByHandle('downhill-skiing-wyoming'),
getProductByHandle('cycling-tuscany')
]
});
return reshapeProducts(res.body.data.productRecommendations);
};
export const getProducts = async ({
query,
reverse,
sortKey
}: {
query?: string;
reverse?: boolean;
sortKey?: string;
}): Promise<Product[]> => {
const res = mockFetchResponse({
products: {
edges: getProductNodesByKeyword(query)
}
});
return reshapeProducts(removeEdgesAndNodes(res.body.data.products));
};
const reshapeCart = (cart: ShopifyCart): Cart => {
if (!cart.cost?.totalTaxAmount) {
cart.cost.totalTaxAmount = {
amount: '0.0',
currencyCode: 'USD'
};
}
return {
...cart,
lines: removeEdgesAndNodes(cart.lines)
};
};
const reshapeCollection = (collection: ShopifyCollection): Collection | undefined => {
if (!collection) {
return undefined;
}
return {
...collection,
path: `/search/${collection.handle}`
};
};
const reshapeCollections = (collections: ShopifyCollection[]) => {
const reshapedCollections = [];
for (const collection of collections) {
if (collection) {
const reshapedCollection = reshapeCollection(collection);
if (reshapedCollection) {
reshapedCollections.push(reshapedCollection);
}
}
}
return reshapedCollections;
};
const reshapeImages = (images: Connection<Image>, productTitle: string) => {
const flattened = removeEdgesAndNodes(images);
// @ts-ignore
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))) {
if (!product) {
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;
};