From 45c3a5345daabe4be98057e73ec76309ec2aa8d1 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Mon, 5 Oct 2020 12:25:03 -0500 Subject: [PATCH] Updated types and added remove item from cart api --- lib/bigcommerce/api/cart.ts | 50 ++++++++++++++++++++---- lib/bigcommerce/cart/use-add-item.tsx | 8 ++-- lib/bigcommerce/cart/use-update-item.tsx | 13 ++---- 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/lib/bigcommerce/api/cart.ts b/lib/bigcommerce/api/cart.ts index 7c71eb35f..d6666369c 100644 --- a/lib/bigcommerce/api/cart.ts +++ b/lib/bigcommerce/api/cart.ts @@ -5,12 +5,20 @@ import createApiHandler, { } from './utils/create-api-handler' import { BigcommerceApiError } from './utils/errors' -export type Item = { +type Body = Partial | undefined + +export type ItemBody = { productId: number variantId: number quantity?: number } +export type AddItemBody = { item: ItemBody } + +export type UpdateItemBody = { itemId: string; item: ItemBody } + +export type RemoveItemBody = { itemId: string } + // TODO: this type should match: // https://developer.bigcommerce.com/api-reference/cart-checkout/server-server-cart-api/cart/getacart#responses export type Cart = { @@ -34,6 +42,7 @@ export type Cart = { const METHODS = ['GET', 'POST', 'PUT', 'DELETE'] +// TODO: a complete implementation should have schema validation for `req.body` const cartApi: BigcommerceApiHandler = async (req, res, config) => { if (!isAllowedMethod(req, res, METHODS)) return @@ -63,7 +72,7 @@ const cartApi: BigcommerceApiHandler = async (req, res, config) => { // Create or add an item to the cart if (req.method === 'POST') { - const item: Item | undefined = req.body?.item + const { item } = (req.body as Body) ?? {} if (!item) { return res.status(400).json({ @@ -71,6 +80,7 @@ const cartApi: BigcommerceApiHandler = async (req, res, config) => { errors: [{ message: 'Missing item' }], }) } + if (!item.quantity) item.quantity = 1 const options = { method: 'POST', @@ -93,10 +103,7 @@ const cartApi: BigcommerceApiHandler = async (req, res, config) => { // Update item in cart if (req.method === 'PUT') { - const { itemId, item } = (req.body ?? {}) as { - itemId?: string - item?: Item - } + const { itemId, item } = (req.body as Body) ?? {} if (!cartId || !itemId || !item) { return res.status(400).json({ @@ -123,6 +130,33 @@ const cartApi: BigcommerceApiHandler = async (req, res, config) => { return res.status(200).json({ data }) } + + // Remove an item from the cart + if (req.method === 'DELETE') { + const { itemId } = (req.body as Body) ?? {} + + if (!cartId || !itemId) { + return res.status(400).json({ + data: null, + errors: [{ message: 'Invalid request' }], + }) + } + + const { data } = await config.storeApiFetch( + `/v3/carts/${cartId}/items/${itemId}`, + { + method: 'DELETE', + } + ) + + // Update the cart cookie + res.setHeader( + 'Set-Cookie', + getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge) + ) + + return res.status(200).json({ data }) + } } catch (error) { console.error(error) @@ -150,8 +184,8 @@ function getCartCookie(name: string, cartId?: string, maxAge?: number) { return serialize(name, cartId || '', options) } -const parseItem = (item: Item) => ({ - quantity: item.quantity || 1, +const parseItem = (item: ItemBody) => ({ + quantity: item.quantity, product_id: item.productId, variant_id: item.variantId, }) diff --git a/lib/bigcommerce/cart/use-add-item.tsx b/lib/bigcommerce/cart/use-add-item.tsx index 3b5d5541a..b648d5ca6 100644 --- a/lib/bigcommerce/cart/use-add-item.tsx +++ b/lib/bigcommerce/cart/use-add-item.tsx @@ -1,11 +1,11 @@ import type { Fetcher } from '@lib/commerce' import { default as useCartAddItem } from '@lib/commerce/cart/use-add-item' -import type { Item } from '../api/cart' +import type { ItemBody, AddItemBody } from '../api/cart' import { Cart, useCart } from '.' -export type { Item } +export type { ItemBody, AddItemBody } -function fetcher(fetch: Fetcher, { item }: { item: Item }) { +function fetcher(fetch: Fetcher, { item }: AddItemBody) { if ( item.quantity && (!Number.isInteger(item.quantity) || item.quantity! < 1) @@ -20,7 +20,7 @@ function fetcher(fetch: Fetcher, { item }: { item: Item }) { export default function useAddItem() { const { mutate } = useCart() - const fn = useCartAddItem(fetcher) + const fn = useCartAddItem(fetcher) const addItem: typeof fn = async (input) => { const data = await fn(input) mutate(data) diff --git a/lib/bigcommerce/cart/use-update-item.tsx b/lib/bigcommerce/cart/use-update-item.tsx index f82bca5a3..be9d30ff7 100644 --- a/lib/bigcommerce/cart/use-update-item.tsx +++ b/lib/bigcommerce/cart/use-update-item.tsx @@ -1,16 +1,11 @@ import type { Fetcher } from '@lib/commerce' import { default as useCartUpdateItem } from '@lib/commerce/cart/use-update-item' -import type { Item } from '../api/cart' +import type { ItemBody, UpdateItemBody } from '../api/cart' import { Cart, useCart } from '.' -export type { Item } +export type { ItemBody, UpdateItemBody } -export type UpdateItemInput = { - itemId: string - item: Item -} - -function fetcher(fetch: Fetcher, { itemId, item }: UpdateItemInput) { +function fetcher(fetch: Fetcher, { itemId, item }: UpdateItemBody) { if ( item.quantity && (!Number.isInteger(item.quantity) || item.quantity! < 1) @@ -29,7 +24,7 @@ function fetcher(fetch: Fetcher, { itemId, item }: UpdateItemInput) { export default function useUpdateItem() { const { mutate } = useCart() - const fn = useCartUpdateItem(fetcher) + const fn = useCartUpdateItem(fetcher) const updateItem: typeof fn = async (input) => { const data = await fn(input) mutate(data)