diff --git a/components/cart/CartItem/CartItem.tsx b/components/cart/CartItem/CartItem.tsx index 1a6ac276d..652f5a624 100644 --- a/components/cart/CartItem/CartItem.tsx +++ b/components/cart/CartItem/CartItem.tsx @@ -14,7 +14,7 @@ const CartItem = ({ currencyCode: string }) => { const { locale } = useCommerce() - const updateItem = useUpdateItem() + const updateItem = useUpdateItem(item) const removeItem = useRemoveItem() const [quantity, setQuantity] = useState(item.quantity) const { price } = formatVariantPrice({ @@ -24,14 +24,7 @@ const CartItem = ({ locale, }) const updateQuantity = async (val: number) => { - const data = await updateItem({ - itemId: item.id, - item: { - productId: item.product_id, - variantId: item.variant_id, - quantity: val, - }, - }) + const data = await updateItem({ quantity: val }) } const handleQuantity = (e: ChangeEvent) => { const val = Number(e.target.value) diff --git a/lib/bigcommerce/api/cart.ts b/lib/bigcommerce/api/cart.ts index 3f917cabc..b7fd155e0 100644 --- a/lib/bigcommerce/api/cart.ts +++ b/lib/bigcommerce/api/cart.ts @@ -146,14 +146,18 @@ const cartApi: BigcommerceApiHandler = async (req, res, config) => { `/v3/carts/${cartId}/items/${itemId}`, { method: 'DELETE' } ) + const data = result?.data ?? null - // Update the cart cookie res.setHeader( 'Set-Cookie', - getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge) + data + ? // Update the cart cookie + getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge) + : // Remove the cart cookie if the cart was removed (empty items) + getCartCookie(config.cartCookie) ) - return res.status(200).json({ data: result?.data }) + return res.status(200).json({ data }) } } catch (error) { console.error(error) diff --git a/lib/bigcommerce/cart/index.tsx b/lib/bigcommerce/cart/index.tsx index 1c7a9e5ed..6152695bf 100644 --- a/lib/bigcommerce/cart/index.tsx +++ b/lib/bigcommerce/cart/index.tsx @@ -16,7 +16,7 @@ export const CartProvider: FC = ({ children }) => { } export function useCart() { - const cart = useCommerceCart() + const cart = useCommerceCart() // Uses a getter to only calculate the prop when required // cart.data is also a getter and it's better to not trigger it early diff --git a/lib/bigcommerce/cart/use-add-item.tsx b/lib/bigcommerce/cart/use-add-item.tsx index b648d5ca6..1a6e144f3 100644 --- a/lib/bigcommerce/cart/use-add-item.tsx +++ b/lib/bigcommerce/cart/use-add-item.tsx @@ -23,7 +23,7 @@ export default function useAddItem() { const fn = useCartAddItem(fetcher) const addItem: typeof fn = async (input) => { const data = await fn(input) - mutate(data) + await mutate(data, false) return data } diff --git a/lib/bigcommerce/cart/use-remove-item.tsx b/lib/bigcommerce/cart/use-remove-item.tsx index d8433f9fe..62a4f28d8 100644 --- a/lib/bigcommerce/cart/use-remove-item.tsx +++ b/lib/bigcommerce/cart/use-remove-item.tsx @@ -5,7 +5,10 @@ import { Cart, useCart } from '.' export type { ItemBody, RemoveItemBody } -function fetcher(fetch: Fetcher, { itemId }: RemoveItemBody) { +export function fetcher( + fetch: Fetcher, + { itemId }: RemoveItemBody +) { return fetch({ url: '/api/bigcommerce/cart', method: 'DELETE', @@ -15,10 +18,10 @@ function fetcher(fetch: Fetcher, { itemId }: RemoveItemBody) { export default function useRemoveItem() { const { mutate } = useCart() - const fn = useCartRemoveItem(fetcher) + const fn = useCartRemoveItem(fetcher) const removeItem: typeof fn = async (input) => { const data = await fn(input) - mutate(data) + await mutate(data, false) return data } diff --git a/lib/bigcommerce/cart/use-update-item.tsx b/lib/bigcommerce/cart/use-update-item.tsx index 6de709c74..55446d74d 100644 --- a/lib/bigcommerce/cart/use-update-item.tsx +++ b/lib/bigcommerce/cart/use-update-item.tsx @@ -1,18 +1,22 @@ import type { Fetcher } from '@lib/commerce' import { default as useCartUpdateItem } from '@lib/commerce/cart/use-update-item' import type { ItemBody, UpdateItemBody } from '../api/cart' +import { fetcher as removeFetcher } from './use-remove-item' import { Cart, useCart } from '.' -export type { ItemBody, UpdateItemBody } +export type UpdateItemInput = Partial<{ id: string } & ItemBody> -function fetcher(fetch: Fetcher, { itemId, item }: UpdateItemBody) { - if ( - item.quantity && - (!Number.isInteger(item.quantity) || item.quantity! < 1) - ) { - throw new Error( - 'The item quantity has to be a valid integer greater than 0' - ) +function fetcher( + fetch: Fetcher, + { itemId, item }: UpdateItemBody +) { + if (Number.isInteger(item.quantity)) { + // Also allow the update hook to remove an item if the quantity is lower than 1 + if (item.quantity! < 1) { + return removeFetcher(fetch, { itemId }) + } + } else if (item.quantity) { + throw new Error('The item quantity has to be a valid integer') } return fetch({ @@ -22,11 +26,18 @@ function fetcher(fetch: Fetcher, { itemId, item }: UpdateItemBody) { }) } -export default function useUpdateItem() { +export default function useUpdateItem(item: any = {}) { const { mutate } = useCart() - const fn = useCartUpdateItem(fetcher) - const updateItem: typeof fn = async (input) => { - const data = await fn(input) + const fn = useCartUpdateItem(fetcher) + const updateItem = async (input: UpdateItemInput) => { + const data = await fn({ + itemId: input.id ?? item.id, + item: { + productId: input.productId ?? item.product_id, + variantId: input.productId ?? item.variant_id, + quantity: input.quantity, + }, + }) await mutate(data, false) return data } diff --git a/lib/commerce/cart/index.tsx b/lib/commerce/cart/index.tsx index 1ca04d871..b18324090 100644 --- a/lib/commerce/cart/index.tsx +++ b/lib/commerce/cart/index.tsx @@ -20,10 +20,11 @@ const CartProvider: FC = ({ children, query, url }) => { function useCart() { const { fetcher: fetch, cartCookie } = useCommerce() - const fetcher = (url?: string, query?: string) => fetch({ url, query }) - const cartId = Cookies.get(cartCookie) + const fetcher = (url?: string, query?: string) => { + return Cookies.get(cartCookie) ? fetch({ url, query }) : null + } const { url, query } = useContext(CartContext) - const response = useSWR(() => (cartId ? [url, query] : null), fetcher, { + const response = useSWR([url, query], fetcher, { revalidateOnFocus: false, }) diff --git a/pages/product/[slug].tsx b/pages/product/[slug].tsx index 2b408b49f..eda376f83 100644 --- a/pages/product/[slug].tsx +++ b/pages/product/[slug].tsx @@ -8,6 +8,7 @@ import getAllProductPaths from '@lib/bigcommerce/api/operations/get-all-product- export async function getStaticProps({ params, }: GetStaticPropsContext<{ slug: string }>) { + console.log('SLUG', params!.slug) const { product } = await getProduct({ variables: { slug: params!.slug } }) if (!product) { @@ -43,7 +44,7 @@ export async function getStaticPaths() { return { paths: products.map((product) => `/product${product!.node.path}`), - fallback: 'unstable_blocking', + fallback: false, } }