commerce/framework/vendure/cart/use-add-item.tsx
2021-01-25 21:24:26 +01:00

81 lines
2.1 KiB
TypeScript

import { CommerceError } from '@commerce/utils/errors'
import { HookFetcher } from '@commerce/utils/types'
import fetchGraphqlApi from '@framework/api/utils/fetch-graphql-api'
import useCartAddItem from '@commerce/cart/use-add-item'
import useCart from './use-cart'
import { useCallback } from 'react'
import { cartFragment } from '../api/fragments/cart'
import {
AddItemToOrderMutation,
AddItemToOrderMutationVariables,
ErrorResult,
} from '@framework/schema'
export const addItemToOrderMutation = /* GraphQL */ `
mutation addItemToOrder($variantId: ID!, $quantity: Int!) {
addItemToOrder(productVariantId: $variantId, quantity: $quantity) {
__typename
...Cart
... on ErrorResult {
errorCode
message
}
}
}
${cartFragment}
`
export type AddItemInput = {
productId?: number
variantId: number
quantity?: number
}
export const fetcher: HookFetcher<
AddItemToOrderMutation,
AddItemToOrderMutationVariables
> = (options, { variantId, quantity }, fetch) => {
if (quantity && (!Number.isInteger(quantity) || quantity! < 1)) {
throw new CommerceError({
message: 'The item quantity has to be a valid integer greater than 0',
})
}
return fetch({
...options,
query: addItemToOrderMutation,
variables: { variantId, quantity: quantity || 1 },
})
}
export function extendHook(customFetcher: typeof fetcher) {
const useAddItem = () => {
const { mutate } = useCart()
const fn = useCartAddItem({}, customFetcher)
return useCallback(
async function addItem(input: AddItemInput) {
const { addItemToOrder } = await fn({
quantity: input.quantity || 1,
variantId: input.variantId,
})
if (addItemToOrder.__typename === 'Order') {
await mutate({ addItemToOrder }, false)
} else {
throw new CommerceError({
message: (addItemToOrder as ErrorResult).message,
})
}
return { addItemToOrder }
},
[fn, mutate]
)
}
useAddItem.extend = extendHook
return useAddItem
}
export default extendHook(fetcher)