moved use-remove-item

This commit is contained in:
Luis Alvarez 2021-02-18 16:06:19 -05:00
parent ff5b1e9414
commit 6dc7e0b632
6 changed files with 81 additions and 59 deletions

View File

@ -1,8 +1,9 @@
import { useCallback } from 'react'
import { HookFetcher } from '@commerce/utils/types'
import { HookContext, HookFetcherContext } from '@commerce/utils/types'
import { ValidationError } from '@commerce/utils/errors'
import useCartRemoveItem, {
RemoveItemInput as UseRemoveItemInput,
import useRemoveItem, {
RemoveItemInput as RemoveItemInputBase,
UseRemoveItem,
} from '@commerce/cart/use-remove-item'
import { normalizeCart } from '../lib/normalize'
import type {
@ -13,41 +14,39 @@ import type {
} from '../types'
import useCart from './use-cart'
const defaultOpts = {
url: '/api/bigcommerce/cart',
method: 'DELETE',
}
export type RemoveItemFn<T = any> = T extends LineItem
? (input?: RemoveItemInput<T>) => Promise<Cart | null>
: (input: RemoveItemInput<T>) => Promise<Cart | null>
export type RemoveItemInput<T = any> = T extends LineItem
? Partial<UseRemoveItemInput>
: UseRemoveItemInput
? Partial<RemoveItemInputBase>
: RemoveItemInputBase
export const fetcher: HookFetcher<Cart | null, RemoveCartItemBody> = async (
options,
{ itemId },
fetch
) => {
const data = await fetch<BigcommerceCart>({
...defaultOpts,
...options,
body: { itemId },
})
return normalizeCart(data)
}
export default useRemoveItem as UseRemoveItem<typeof handler>
export function extendHook(customFetcher: typeof fetcher) {
const useRemoveItem = <T extends LineItem | undefined = undefined>(
item?: T
export const handler = {
fetchOptions: {
url: '/api/bigcommerce/cart',
method: 'DELETE',
},
async fetcher({
input: { itemId },
options,
fetch,
}: HookFetcherContext<RemoveCartItemBody>) {
const data = await fetch<BigcommerceCart>({
...options,
body: { itemId },
})
return normalizeCart(data)
},
useHook: ({ fetch }: HookContext<Cart | null, RemoveCartItemBody>) => <
T extends LineItem | undefined = undefined
>(
ctx: { item?: T } = {}
) => {
const { mutate } = useCart()
const fn = useCartRemoveItem<Cart | null, RemoveCartItemBody>(
defaultOpts,
customFetcher
)
const { item } = ctx
const { mutate } = useCart() as any
const removeItem: RemoveItemFn<LineItem> = async (input) => {
const itemId = input?.id ?? item?.id
@ -57,17 +56,11 @@ export function extendHook(customFetcher: typeof fetcher) {
})
}
const data = await fn({ itemId })
const data = await fetch({ input: { itemId } })
await mutate(data, false)
return data
}
return useCallback(removeItem as RemoveItemFn<T>, [fn, mutate])
}
useRemoveItem.extend = extendHook
return useRemoveItem
return useCallback(removeItem as RemoveItemFn<T>, [fetch, mutate])
},
}
export default extendHook(fetcher)

View File

@ -13,7 +13,7 @@ import type {
BigcommerceCart,
LineItem,
} from '../types'
import { fetcher as removeFetcher } from './use-remove-item'
import { handler as removeItemHandler } from './use-remove-item'
import useCart from './use-cart'
export type UpdateItemInput<T = any> = T extends LineItem
@ -35,7 +35,11 @@ export const handler = {
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 removeFetcher(null, { itemId }, fetch)
return removeItemHandler.fetcher({
options: removeItemHandler.fetchOptions,
input: { itemId },
fetch,
})
}
} else if (item.quantity) {
throw new ValidationError({

View File

@ -1,6 +1,7 @@
import { handler as useCart } from './cart/use-cart'
import { handler as useAddItem } from './cart/use-add-item'
import { handler as useUpdateItem } from './cart/use-update-item'
import { handler as useRemoveItem } from './cart/use-remove-item'
import { handler as useWishlist } from './wishlist/use-wishlist'
import { handler as useCustomer } from './customer/use-customer'
import { handler as useSearch } from './product/use-search'
@ -10,7 +11,7 @@ export const bigcommerceProvider = {
locale: 'en-us',
cartCookie: 'bc_cartId',
fetcher,
cart: { useCart, useAddItem, useUpdateItem },
cart: { useCart, useAddItem, useUpdateItem, useRemoveItem },
wishlist: { useWishlist },
customer: { useCustomer },
products: { useSearch },

View File

@ -1,10 +1,32 @@
import useAction from '../utils/use-action'
import useHook, { useHookHandler } from '../utils/use-hook'
import { mutationFetcher } from '../utils/default-fetcher'
import type { MutationHook } from '../utils/types'
import type { Cart, LineItem, RemoveCartItemBody } from '../types'
import type { Provider } from '..'
// Input expected by the action returned by the `useRemoveItem` hook
export interface RemoveItemInput {
/**
* Input expected by the action returned by the `useRemoveItem` hook
*/
export type RemoveItemInput = {
id: string
}
const useRemoveItem = useAction
export type UseRemoveItem<
H extends MutationHook<any, any, any> = MutationHook<
Cart | null,
{ item?: LineItem },
RemoveItemInput,
RemoveCartItemBody
>
> = ReturnType<H['useHook']>
export const fetcher = mutationFetcher
const fn = (provider: Provider) => provider.cart?.useRemoveItem!
const useRemoveItem: UseRemoveItem = (input) => {
const handler = useHookHandler(fn, fetcher)
return handler(useHook(fn, fetcher))(input)
}
export default useRemoveItem

View File

@ -1,17 +1,19 @@
import useHook, { useHookHandler } from '../utils/use-hook'
import type { MutationHook, HookFetcherFn } from '../utils/types'
import { mutationFetcher } from '../utils/default-fetcher'
import type { MutationHook } from '../utils/types'
import type { Cart, CartItemBody, LineItem, UpdateCartItemBody } from '../types'
import type { Provider } from '..'
import debounce from 'lodash.debounce'
// Input expected by the action returned by the `useUpdateItem` hook
/**
* Input expected by the action returned by the `useUpdateItem` hook
*/
export type UpdateItemInput<T extends CartItemBody> = T & {
id: string
}
export type UseUpdateItem<
H extends MutationHook<any, any, any> = MutationHook<
Cart,
Cart | null,
{
item?: LineItem
wait?: number
@ -21,19 +23,13 @@ export type UseUpdateItem<
>
> = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn<any> = async ({
options,
input,
fetch,
}) => {
return fetch({ ...options, body: input })
}
export const fetcher = mutationFetcher
const fn = (provider: Provider) => provider.cart?.useUpdateItem!
const useUpdateItem: UseUpdateItem = (input = {}) => {
const useUpdateItem: UseUpdateItem = (input) => {
const handler = useHookHandler(fn, fetcher)
return debounce(handler(useHook(fn, fetcher))(input), input.wait ?? 500)
return handler(useHook(fn, fetcher))(input)
}
export default useUpdateItem

View File

@ -3,4 +3,10 @@ import type { HookFetcherFn } from './types'
const defaultFetcher: HookFetcherFn<any> = ({ options, fetch }) =>
fetch(options)
export const mutationFetcher: HookFetcherFn<any> = ({
input,
options,
fetch,
}) => fetch({ ...options, body: input })
export default defaultFetcher