4
0
forked from crowetic/commerce

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

@ -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<HTMLInputElement>) => {
const val = Number(e.target.value)

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,
})

View File

@ -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,
}
}