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 export type UpdateItemActionInput = T extends LineItem ? Partial : UpdateItemHook['actionInput'] export const handler = { fetchOptions: { query: 'cart', method: 'update', }, async fetcher({ input, options, fetch }: HookFetcherContext) { 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) => ( 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) => { 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] ) }, }