forked from crowetic/commerce
bug fixes for cart actions
This commit is contained in:
parent
80614a1df0
commit
3ac6805ebe
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user