import { useCallback } from 'react' import debounce from 'lodash.debounce' import type { HookFetcherContext, MutationHook, MutationHookContext, } from '@commerce/utils/types' import { ValidationError } from '@commerce/utils/errors' // import useUpdateItem, { // UpdateItemInput as UpdateItemInputBase, // UseUpdateItem, // } from '@commerce/cart/use-update-item' import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item' import useCart from './use-cart' import { handler as removeItemHandler } from './use-remove-item' import { CartItemBody, LineItem } from '@commerce/types/cart' import { checkoutToCart } from './utils' import { UpdateItemHook } from '../types/cart' // export type UpdateItemInput = T extends LineItem // ? Partial> // : UpdateItemInputBase export default useUpdateItem as UseUpdateItem export type UpdateItemActionInput = T extends LineItem ? Partial : UpdateItemHook['actionInput'] export const handler = { fetchOptions: { query: 'cart', method: 'updateItem', }, async fetcher({ input: { itemId, item }, options, fetch, }: HookFetcherContext) { 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 removeItemHandler.fetcher({ options: removeItemHandler.fetchOptions, input: { itemId }, fetch, }) } } else if (item.quantity) { throw new ValidationError({ message: 'The item quantity has to be a valid integer', }) } const response = await fetch({ ...options, variables: [itemId, { quantity: item.quantity }], }) return checkoutToCart(response) }, useHook: ({ fetch }: MutationHookContext) => ( ctx: { item?: T wait?: number } = {} ) => { const { item } = ctx const { mutate, data: cartData } = useCart() as any return useCallback( debounce(async (input: UpdateItemActionInput) => { const firstLineItem = cartData.lineItems[0] const itemId = item?.id || firstLineItem.id const productId = item?.productId || firstLineItem.productId const variantId = item?.variant.id || firstLineItem.variant.id if (!itemId || !productId) { throw new ValidationError({ message: 'Invalid input used for this operation', }) } const data = await fetch({ input: { item: { productId, variantId, quantity: input.quantity, }, itemId, }, }) await mutate(data, false) return data }, ctx.wait ?? 500), [fetch, mutate] ) }, }