bug fixes for cart actions

This commit is contained in:
Luis Alvarez
2020-10-07 15:08:17 -05:00
parent 80614a1df0
commit 3ac6805ebe
8 changed files with 47 additions and 34 deletions

View File

@@ -146,14 +146,18 @@ const cartApi: BigcommerceApiHandler<Cart> = 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)

View File

@@ -16,7 +16,7 @@ export const CartProvider: FC = ({ children }) => {
}
export function useCart() {
const cart = useCommerceCart<Cart>()
const cart = useCommerceCart<Cart | null>()
// 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

View File

@@ -23,7 +23,7 @@ export default function useAddItem() {
const fn = useCartAddItem<Cart, AddItemBody>(fetcher)
const addItem: typeof fn = async (input) => {
const data = await fn(input)
mutate(data)
await mutate(data, false)
return data
}

View File

@@ -5,7 +5,10 @@ import { Cart, useCart } from '.'
export type { ItemBody, RemoveItemBody }
function fetcher(fetch: Fetcher<Cart>, { itemId }: RemoveItemBody) {
export function fetcher(
fetch: Fetcher<Cart | null>,
{ itemId }: RemoveItemBody
) {
return fetch({
url: '/api/bigcommerce/cart',
method: 'DELETE',
@@ -15,10 +18,10 @@ function fetcher(fetch: Fetcher<Cart>, { itemId }: RemoveItemBody) {
export default function useRemoveItem() {
const { mutate } = useCart()
const fn = useCartRemoveItem<Cart, RemoveItemBody>(fetcher)
const fn = useCartRemoveItem<Cart | null, RemoveItemBody>(fetcher)
const removeItem: typeof fn = async (input) => {
const data = await fn(input)
mutate(data)
await mutate(data, false)
return data
}

View File

@@ -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<Cart>, { 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<Cart | null>,
{ 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<Cart>, { itemId, item }: UpdateItemBody) {
})
}
export default function useUpdateItem() {
export default function useUpdateItem(item: any = {}) {
const { mutate } = useCart()
const fn = useCartUpdateItem<Cart, UpdateItemBody>(fetcher)
const updateItem: typeof fn = async (input) => {
const data = await fn(input)
const fn = useCartUpdateItem<Cart | null, UpdateItemBody>(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
}

View File

@@ -20,10 +20,11 @@ const CartProvider: FC<CartProviderProps> = ({ children, query, url }) => {
function useCart<C>() {
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,
})