diff --git a/app/layout.tsx b/app/layout.tsx index 3b09ab7e4..b793efe04 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -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'; diff --git a/components/cart/actions.ts b/components/cart/actions.ts index a2c592557..4b619dd2a 100644 --- a/components/cart/actions.ts +++ b/components/cart/actions.ts @@ -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'; diff --git a/lib/fourthwall/index.ts b/lib/fourthwall/index.ts index 0b48af9a6..1b5c71bf7 100644 --- a/lib/fourthwall/index.ts +++ b/lib/fourthwall/index.ts @@ -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(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 { + if (!cartId) { + return undefined; + } + + const res = await fourthwallGet(`${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 { return []; diff --git a/lib/fourthwall/reshape.ts b/lib/fourthwall/reshape.ts index 283bcd005..2d9e99215 100644 --- a/lib/fourthwall/reshape.ts +++ b/lib/fourthwall/reshape.ts @@ -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) + }; +}; diff --git a/lib/fourthwall/types.ts b/lib/fourthwall/types.ts index 8c8bfbd35..50afc8cfc 100644 --- a/lib/fourthwall/types.ts +++ b/lib/fourthwall/types.ts @@ -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; +}; diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts index 38f80514c..887e11988 100644 --- a/lib/shopify/index.ts +++ b/lib/shopify/index.ts @@ -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 { - if (!cartId) { - return undefined; - } - - const res = await shopifyFetch({ - 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 { const res = await shopifyFetch({ query: getCollectionQuery,