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 currencyCode: string
}) => { }) => {
const { locale } = useCommerce() const { locale } = useCommerce()
const updateItem = useUpdateItem() const updateItem = useUpdateItem(item)
const removeItem = useRemoveItem() const removeItem = useRemoveItem()
const [quantity, setQuantity] = useState(item.quantity) const [quantity, setQuantity] = useState(item.quantity)
const { price } = formatVariantPrice({ const { price } = formatVariantPrice({
@ -24,14 +24,7 @@ const CartItem = ({
locale, locale,
}) })
const updateQuantity = async (val: number) => { const updateQuantity = async (val: number) => {
const data = await updateItem({ const data = await updateItem({ quantity: val })
itemId: item.id,
item: {
productId: item.product_id,
variantId: item.variant_id,
quantity: val,
},
})
} }
const handleQuantity = (e: ChangeEvent<HTMLInputElement>) => { const handleQuantity = (e: ChangeEvent<HTMLInputElement>) => {
const val = Number(e.target.value) 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}`, `/v3/carts/${cartId}/items/${itemId}`,
{ method: 'DELETE' } { method: 'DELETE' }
) )
const data = result?.data ?? null
// Update the cart cookie
res.setHeader( res.setHeader(
'Set-Cookie', '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) { } catch (error) {
console.error(error) console.error(error)

View File

@ -16,7 +16,7 @@ export const CartProvider: FC = ({ children }) => {
} }
export function useCart() { export function useCart() {
const cart = useCommerceCart<Cart>() const cart = useCommerceCart<Cart | null>()
// Uses a getter to only calculate the prop when required // 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 // 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 fn = useCartAddItem<Cart, AddItemBody>(fetcher)
const addItem: typeof fn = async (input) => { const addItem: typeof fn = async (input) => {
const data = await fn(input) const data = await fn(input)
mutate(data) await mutate(data, false)
return data return data
} }

View File

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

View File

@ -1,18 +1,22 @@
import type { Fetcher } from '@lib/commerce' import type { Fetcher } from '@lib/commerce'
import { default as useCartUpdateItem } from '@lib/commerce/cart/use-update-item' import { default as useCartUpdateItem } from '@lib/commerce/cart/use-update-item'
import type { ItemBody, UpdateItemBody } from '../api/cart' import type { ItemBody, UpdateItemBody } from '../api/cart'
import { fetcher as removeFetcher } from './use-remove-item'
import { Cart, useCart } from '.' import { Cart, useCart } from '.'
export type { ItemBody, UpdateItemBody } export type UpdateItemInput = Partial<{ id: string } & ItemBody>
function fetcher(fetch: Fetcher<Cart>, { itemId, item }: UpdateItemBody) { function fetcher(
if ( fetch: Fetcher<Cart | null>,
item.quantity && { itemId, item }: UpdateItemBody
(!Number.isInteger(item.quantity) || item.quantity! < 1) ) {
) { if (Number.isInteger(item.quantity)) {
throw new Error( // Also allow the update hook to remove an item if the quantity is lower than 1
'The item quantity has to be a valid integer greater than 0' 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({ 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 { mutate } = useCart()
const fn = useCartUpdateItem<Cart, UpdateItemBody>(fetcher) const fn = useCartUpdateItem<Cart | null, UpdateItemBody>(fetcher)
const updateItem: typeof fn = async (input) => { const updateItem = async (input: UpdateItemInput) => {
const data = await fn(input) 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) await mutate(data, false)
return data return data
} }

View File

@ -20,10 +20,11 @@ const CartProvider: FC<CartProviderProps> = ({ children, query, url }) => {
function useCart<C>() { function useCart<C>() {
const { fetcher: fetch, cartCookie } = useCommerce() const { fetcher: fetch, cartCookie } = useCommerce()
const fetcher = (url?: string, query?: string) => fetch({ url, query }) const fetcher = (url?: string, query?: string) => {
const cartId = Cookies.get(cartCookie) return Cookies.get(cartCookie) ? fetch({ url, query }) : null
}
const { url, query } = useContext(CartContext) const { url, query } = useContext(CartContext)
const response = useSWR(() => (cartId ? [url, query] : null), fetcher, { const response = useSWR([url, query], fetcher, {
revalidateOnFocus: false, revalidateOnFocus: false,
}) })

View File

@ -8,6 +8,7 @@ import getAllProductPaths from '@lib/bigcommerce/api/operations/get-all-product-
export async function getStaticProps({ export async function getStaticProps({
params, params,
}: GetStaticPropsContext<{ slug: string }>) { }: GetStaticPropsContext<{ slug: string }>) {
console.log('SLUG', params!.slug)
const { product } = await getProduct({ variables: { slug: params!.slug } }) const { product } = await getProduct({ variables: { slug: params!.slug } })
if (!product) { if (!product) {
@ -43,7 +44,7 @@ export async function getStaticPaths() {
return { return {
paths: products.map((product) => `/product${product!.node.path}`), paths: products.map((product) => `/product${product!.node.path}`),
fallback: 'unstable_blocking', fallback: false,
} }
} }