commerce/packages/commercejs/cart/use-update-item.tsx
2022-01-13 20:58:26 -05:00

77 lines
2.3 KiB
TypeScript

import type { UpdateItemHook, LineItem } from '@commerce/types/cart'
import type {
HookFetcherContext,
MutationHookContext,
} from '@commerce/utils/types'
import { ValidationError } from '@commerce/utils/errors'
import debounce from 'lodash.debounce'
import { useCallback } from 'react'
import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item'
import type { CommercejsCart } from '../types/cart'
import { normalizeCart } from '../utils/normalize-cart'
import useCart from './use-cart'
export default useUpdateItem as UseUpdateItem<typeof handler>
export type UpdateItemActionInput<T = any> = T extends LineItem
? Partial<UpdateItemHook['actionInput']>
: UpdateItemHook['actionInput']
export const handler = {
fetchOptions: {
query: 'cart',
method: 'update',
},
async fetcher({ input, options, fetch }: HookFetcherContext<UpdateItemHook>) {
const variables = [input.itemId, { quantity: input.item.quantity }]
const { cart } = await fetch<{ cart: CommercejsCart }>({
query: options.query,
method: options.method,
variables,
})
return normalizeCart(cart)
},
useHook:
({ fetch }: MutationHookContext<UpdateItemHook>) =>
<T extends LineItem | undefined = undefined>(
ctx: {
item?: T
wait?: number
} = {}
) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const { mutate } = useCart() as any
const { item } = ctx
// eslint-disable-next-line react-hooks/rules-of-hooks
return useCallback(
debounce(async (input: UpdateItemActionInput<T>) => {
const itemId = input.id ?? item?.id
const productId = input.productId ?? item?.productId
const variantId = input.productId ?? item?.variantId
const quantity = input?.quantity ?? item?.quantity
if (!itemId || !productId || !variantId) {
throw new ValidationError({
message: 'Invalid input for updating cart item',
})
}
const cart = await fetch({
input: {
itemId,
item: {
quantity,
productId,
variantId,
},
},
})
await mutate(cart, false)
return cart
}, ctx.wait ?? 500),
[mutate, item]
)
},
}