clean reshape get cart

This commit is contained in:
Jieren Chen 2024-09-08 12:10:13 -04:00
parent 2c6e46b4d9
commit e2b30b8bb6
No known key found for this signature in database
GPG Key ID: 2FF322D21B5DB10B
6 changed files with 112 additions and 36 deletions

View File

@ -2,7 +2,7 @@ import { CartProvider } from 'components/cart/cart-context';
import { Navbar } from 'components/layout/navbar';
import { WelcomeToast } from 'components/welcome-toast';
import { GeistSans } from 'geist/font/sans';
import { getCart } from 'lib/shopify';
import { getCart } from 'lib/fourthwall';
import { ensureStartsWith } from 'lib/utils';
import { cookies } from 'next/headers';
import { ReactNode } from 'react';

View File

@ -1,7 +1,8 @@
'use server';
import { TAGS } from 'lib/constants';
import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/shopify';
import { getCart } from 'lib/fourthwall';
import { addToCart, createCart, removeFromCart, updateCart } from 'lib/shopify';
import { revalidateTag } from 'next/cache';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

View File

@ -1,5 +1,6 @@
import { Menu, Product } from "lib/shopify/types";
import { reshapeProducts } from "./reshape";
import { Cart, Menu, Product } from "lib/shopify/types";
import { reshapeCart, reshapeProducts } from "./reshape";
import { FourthwallCart } from "./types";
/**
* Helpers
@ -60,9 +61,8 @@ async function fourthwallPost<T>(url: string, data: any, options: RequestInit =
}
/**
* Calls
* Collection operations
*/
export async function getCollectionProducts({
collection,
reverse,
@ -87,9 +87,24 @@ export async function getCollectionProducts({
return reshapeProducts(res.body.results);
}
/**
* Cart operations
*/
export async function getCart(cartId: string | undefined): Promise<Cart | undefined> {
if (!cartId) {
return undefined;
}
const res = await fourthwallGet<FourthwallCart>(`${process.env.FW_URL}/api/public/v1.0/carts/${cartId}?secret=${process.env.FW_SECRET}`, {
cache: 'no-store'
});
return reshapeCart(res.body);
}
/**
* Stubbed out
* TODO: Stubbed out
*/
export async function getMenu(handle: string): Promise<Menu[]> {
return [];

View File

@ -1,6 +1,9 @@
import { Image, Money, Product, ProductVariant } from "lib/shopify/types";
import { FourthwallMoney, FourthwallProduct, FourthwallProductImage, FourthwallProductVariant } from "./types";
import { Cart, CartItem, Image, Money, Product, ProductVariant } from "lib/shopify/types";
import { FourthwallCart, FourthwallCartItem, FourthwallMoney, FourthwallProduct, FourthwallProductImage, FourthwallProductVariant } from "./types";
/**
* Utils
*/
const DEFAULT_IMAGE: Image = {
url: '',
altText: '',
@ -8,6 +11,17 @@ const DEFAULT_IMAGE: Image = {
height: 0
}
const reshapeMoney = (money: FourthwallMoney): Money => {
return {
amount: money.value.toString(),
currencyCode: money.currencyCode
};
}
/**
* Products
*/
export const reshapeProducts = (products: FourthwallProduct[]) => {
const reshapedProducts = [];
@ -44,8 +58,6 @@ const reshapeProduct = (product: FourthwallProduct): Product | undefined => {
description: product.description,
images: reshapeImages(images, product.name),
variants: reshapeVariants(variants),
// stubbed out
availableForSale: true,
priceRange: {
minVariantPrice: {
amount: minPrice.toString(),
@ -56,8 +68,10 @@ const reshapeProduct = (product: FourthwallProduct): Product | undefined => {
currencyCode,
}
},
options: [],
featuredImage: reshapeImages(images, product.name)[0] || DEFAULT_IMAGE,
// TODO: stubbed out
availableForSale: true,
options: [],
seo: {
title: product.name,
description: product.description,
@ -87,9 +101,59 @@ const reshapeVariants = (variants: FourthwallProductVariant[]): ProductVariant[]
}))
}
const reshapeMoney = (money: FourthwallMoney): Money => {
/**
* Cart
*/
const reshapeCartItem = (item: FourthwallCartItem): CartItem => {
return {
amount: money.value.toString(),
currencyCode: money.currencyCode
id: item.variant.id,
quantity: item.quantity,
cost: {
totalAmount: reshapeMoney(item.variant.unitPrice)
},
merchandise: {
id: item.variant.id,
title: item.variant.name,
// TODO: Stubbed out
selectedOptions: [],
product: {
id: 'TT',
handle: 'TT',
title: 'TT',
featuredImage: {
url: item.variant.images[0]?.url || 'TT',
altText: 'TT',
width: item.variant.images[0]?.width || 100,
height: item.variant.images[0]?.height || 100
}
}
}
};
}
export const reshapeCart = (cart: FourthwallCart): Cart => {
const totalValue = cart.items.map((item) => item.quantity * item.variant.unitPrice.value).reduce((a, b) => a + b, 0);
const currencyCode = cart.items[0]?.variant.unitPrice.currencyCode || 'USD';
return {
...cart,
cost: {
totalAmount: {
amount: totalValue.toString(),
currencyCode,
},
subtotalAmount: {
amount: totalValue.toString(),
currencyCode,
},
totalTaxAmount: {
amount: '0.0',
currencyCode,
}
},
lines: cart.items.map(reshapeCartItem),
// TODO: Stubbed out
checkoutUrl: 'TT',
totalQuantity: cart.items.map((item) => item.quantity).reduce((a, b) => a + b, 0)
};
};

View File

@ -30,3 +30,20 @@ export type FourthwallProductVariant = {
// other attr
};
export type FourthwallCart = {
id: string | undefined;
// checkoutUrl: string;
// cost: {
// subtotalAmount: Money;
// totalAmount: Money;
// totalTaxAmount: Money;
// };
items: FourthwallCartItem[];
};
export type FourthwallCartItem = {
variant: FourthwallProductVariant;
quantity: number;
};

View File

@ -10,7 +10,6 @@ import {
editCartItemsMutation,
removeFromCartMutation
} from './mutations/cart';
import { getCartQuery } from './queries/cart';
import {
getCollectionQuery,
getCollectionsQuery
@ -30,7 +29,6 @@ import {
Product,
ShopifyAddToCartOperation,
ShopifyCart,
ShopifyCartOperation,
ShopifyCollection,
ShopifyCollectionOperation,
ShopifyCollectionsOperation,
@ -249,25 +247,6 @@ export async function updateCart(
return reshapeCart(res.body.data.cartLinesUpdate.cart);
}
export async function getCart(cartId: string | undefined): Promise<Cart | undefined> {
if (!cartId) {
return undefined;
}
const res = await shopifyFetch<ShopifyCartOperation>({
query: getCartQuery,
variables: { cartId },
tags: [TAGS.cart]
});
// Old carts becomes `null` when you checkout.
if (!res.body.data.cart) {
return undefined;
}
return reshapeCart(res.body.data.cart);
}
export async function getCollection(handle: string): Promise<Collection | undefined> {
const res = await shopifyFetch<ShopifyCollectionOperation>({
query: getCollectionQuery,