mirror of
https://github.com/vercel/commerce.git
synced 2025-05-01 23:37:56 +00:00
Updated the useAddItem and useRemoveItem hooks
This commit is contained in:
parent
023058dc0c
commit
5cfa8241f6
@ -11,42 +11,22 @@ import removeItem from './handlers/remove-item'
|
|||||||
import type {
|
import type {
|
||||||
BigcommerceCart,
|
BigcommerceCart,
|
||||||
GetCartHandlerBody,
|
GetCartHandlerBody,
|
||||||
|
AddCartItemHandlerBody,
|
||||||
UpdateCartItemHandlerBody,
|
UpdateCartItemHandlerBody,
|
||||||
|
RemoveCartItemHandlerBody,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
|
|
||||||
type OptionSelections = {
|
|
||||||
option_id: Number
|
|
||||||
option_value: Number | String
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ItemBody = {
|
|
||||||
productId: number
|
|
||||||
variantId: number
|
|
||||||
quantity?: number
|
|
||||||
optionSelections?: OptionSelections
|
|
||||||
}
|
|
||||||
|
|
||||||
export type AddItemBody = { item: ItemBody }
|
|
||||||
|
|
||||||
export type RemoveItemBody = { itemId: string }
|
|
||||||
|
|
||||||
export type CartHandlers = {
|
export type CartHandlers = {
|
||||||
getCart: BigcommerceHandler<BigcommerceCart, GetCartHandlerBody>
|
getCart: BigcommerceHandler<BigcommerceCart, GetCartHandlerBody>
|
||||||
addItem: BigcommerceHandler<
|
addItem: BigcommerceHandler<BigcommerceCart, AddCartItemHandlerBody>
|
||||||
BigcommerceCart,
|
|
||||||
{ cartId?: string } & Partial<AddItemBody>
|
|
||||||
>
|
|
||||||
updateItem: BigcommerceHandler<BigcommerceCart, UpdateCartItemHandlerBody>
|
updateItem: BigcommerceHandler<BigcommerceCart, UpdateCartItemHandlerBody>
|
||||||
removeItem: BigcommerceHandler<
|
removeItem: BigcommerceHandler<BigcommerceCart, RemoveCartItemHandlerBody>
|
||||||
BigcommerceCart,
|
|
||||||
{ cartId?: string } & Partial<RemoveItemBody>
|
|
||||||
>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const METHODS = ['GET', 'POST', 'PUT', 'DELETE']
|
const METHODS = ['GET', 'POST', 'PUT', 'DELETE']
|
||||||
|
|
||||||
// TODO: a complete implementation should have schema validation for `req.body`
|
// TODO: a complete implementation should have schema validation for `req.body`
|
||||||
const cartApi: BigcommerceApiHandler<Cart, CartHandlers> = async (
|
const cartApi: BigcommerceApiHandler<BigcommerceCart, CartHandlers> = async (
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
config,
|
config,
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import type { HookFetcher } from '@commerce/utils/types'
|
import type { HookFetcher } from '@commerce/utils/types'
|
||||||
import { CommerceError } from '@commerce/utils/errors'
|
import { CommerceError } from '@commerce/utils/errors'
|
||||||
import useCartAddItem from '@commerce/cart/use-add-item'
|
import useCartAddItem, {
|
||||||
|
AddItemInput as UseAddItemInput,
|
||||||
|
} from '@commerce/cart/use-add-item'
|
||||||
import { normalizeCart } from '../lib/normalize'
|
import { normalizeCart } from '../lib/normalize'
|
||||||
import type {
|
import type {
|
||||||
ItemBody,
|
AddCartItemBody,
|
||||||
AddItemBody,
|
Cart,
|
||||||
Cart as BigcommerceCart,
|
BigcommerceCart,
|
||||||
} from '../api/cart'
|
CartItemBody,
|
||||||
|
} from '../types'
|
||||||
import useCart from './use-cart'
|
import useCart from './use-cart'
|
||||||
|
|
||||||
const defaultOpts = {
|
const defaultOpts = {
|
||||||
@ -15,9 +18,9 @@ const defaultOpts = {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AddItemInput = ItemBody
|
export type AddItemInput = UseAddItemInput<CartItemBody>
|
||||||
|
|
||||||
export const fetcher: HookFetcher<Cart, AddItemBody> = async (
|
export const fetcher: HookFetcher<Cart, AddCartItemBody> = async (
|
||||||
options,
|
options,
|
||||||
{ item },
|
{ item },
|
||||||
fetch
|
fetch
|
||||||
@ -31,7 +34,7 @@ export const fetcher: HookFetcher<Cart, AddItemBody> = async (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await fetch<BigcommerceCart>({
|
const data = await fetch<BigcommerceCart, AddCartItemBody>({
|
||||||
...defaultOpts,
|
...defaultOpts,
|
||||||
...options,
|
...options,
|
||||||
body: { item },
|
body: { item },
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import { HookFetcher } from '@commerce/utils/types'
|
import { HookFetcher } from '@commerce/utils/types'
|
||||||
import useCartRemoveItem from '@commerce/cart/use-remove-item'
|
import { ValidationError } from '@commerce/utils/errors'
|
||||||
|
import useCartRemoveItem, {
|
||||||
|
RemoveItemInput as UseRemoveItemInput,
|
||||||
|
} from '@commerce/cart/use-remove-item'
|
||||||
import { normalizeCart } from '../lib/normalize'
|
import { normalizeCart } from '../lib/normalize'
|
||||||
import type { RemoveItemBody, Cart as BigcommerceCart } from '../api/cart'
|
import type {
|
||||||
|
RemoveCartItemBody,
|
||||||
|
Cart,
|
||||||
|
BigcommerceCart,
|
||||||
|
LineItem,
|
||||||
|
} from '../types'
|
||||||
import useCart from './use-cart'
|
import useCart from './use-cart'
|
||||||
|
|
||||||
const defaultOpts = {
|
const defaultOpts = {
|
||||||
@ -10,11 +18,15 @@ const defaultOpts = {
|
|||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RemoveItemInput = {
|
export type RemoveItemFn<T = any> = T extends LineItem
|
||||||
id: string
|
? (input?: RemoveItemInput<T>) => Promise<Cart | null>
|
||||||
}
|
: (input: RemoveItemInput<T>) => Promise<Cart | null>
|
||||||
|
|
||||||
export const fetcher: HookFetcher<Cart | null, RemoveItemBody> = async (
|
export type RemoveItemInput<T = any> = T extends LineItem
|
||||||
|
? Partial<UseRemoveItemInput>
|
||||||
|
: UseRemoveItemInput
|
||||||
|
|
||||||
|
export const fetcher: HookFetcher<Cart | null, RemoveCartItemBody> = async (
|
||||||
options,
|
options,
|
||||||
{ itemId },
|
{ itemId },
|
||||||
fetch
|
fetch
|
||||||
@ -28,21 +40,29 @@ export const fetcher: HookFetcher<Cart | null, RemoveItemBody> = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function extendHook(customFetcher: typeof fetcher) {
|
export function extendHook(customFetcher: typeof fetcher) {
|
||||||
const useRemoveItem = (item?: any) => {
|
const useRemoveItem = <T extends LineItem | undefined = undefined>(
|
||||||
|
item?: T
|
||||||
|
) => {
|
||||||
const { mutate } = useCart()
|
const { mutate } = useCart()
|
||||||
const fn = useCartRemoveItem<Cart | null, RemoveItemBody>(
|
const fn = useCartRemoveItem<Cart | null, RemoveCartItemBody>(
|
||||||
defaultOpts,
|
defaultOpts,
|
||||||
customFetcher
|
customFetcher
|
||||||
)
|
)
|
||||||
|
const removeItem: RemoveItemFn<LineItem> = async (input) => {
|
||||||
|
const itemId = input?.id ?? item?.id
|
||||||
|
|
||||||
return useCallback(
|
if (!itemId) {
|
||||||
async function removeItem(input: RemoveItemInput) {
|
throw new ValidationError({
|
||||||
const data = await fn({ itemId: input.id ?? item?.id })
|
message: 'Invalid input used for this operation',
|
||||||
await mutate(data, false)
|
})
|
||||||
return data
|
}
|
||||||
},
|
|
||||||
[fn, mutate]
|
const data = await fn({ itemId })
|
||||||
)
|
await mutate(data, false)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
return useCallback(removeItem as RemoveItemFn<T>, [fn, mutate])
|
||||||
}
|
}
|
||||||
|
|
||||||
useRemoveItem.extend = extendHook
|
useRemoveItem.extend = extendHook
|
||||||
|
@ -45,8 +45,18 @@ export interface CartItemBody extends Core.CartItemBody {
|
|||||||
|
|
||||||
export interface GetCartHandlerBody extends Core.GetCartHandlerBody {}
|
export interface GetCartHandlerBody extends Core.GetCartHandlerBody {}
|
||||||
|
|
||||||
|
export interface AddCartItemBody extends Core.AddCartItemBody<CartItemBody> {}
|
||||||
|
|
||||||
|
export interface AddCartItemHandlerBody
|
||||||
|
extends Core.AddCartItemHandlerBody<CartItemBody> {}
|
||||||
|
|
||||||
export interface UpdateCartItemBody
|
export interface UpdateCartItemBody
|
||||||
extends Core.UpdateCartItemBody<CartItemBody> {}
|
extends Core.UpdateCartItemBody<CartItemBody> {}
|
||||||
|
|
||||||
export interface UpdateCartItemHandlerBody
|
export interface UpdateCartItemHandlerBody
|
||||||
extends Core.UpdateCartItemHandlerBody<CartItemBody> {}
|
extends Core.UpdateCartItemHandlerBody<CartItemBody> {}
|
||||||
|
|
||||||
|
export interface RemoveCartItemBody extends Core.RemoveCartItemBody {}
|
||||||
|
|
||||||
|
export interface RemoveCartItemHandlerBody
|
||||||
|
extends Core.RemoveCartItemHandlerBody {}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import useAction from '../utils/use-action'
|
import useAction from '../utils/use-action'
|
||||||
|
import type { CartItemBody } from '../types'
|
||||||
|
|
||||||
|
// Input expected by the action returned by the `useAddItem` hook
|
||||||
|
export type AddItemInput<T extends CartItemBody> = T
|
||||||
|
|
||||||
const useAddItem = useAction
|
const useAddItem = useAction
|
||||||
|
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import useAction from '../utils/use-action'
|
import useAction from '../utils/use-action'
|
||||||
|
|
||||||
|
// Input expected by the action returned by the `useRemoveItem` hook
|
||||||
|
export interface RemoveItemInput {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
const useRemoveItem = useAction
|
const useRemoveItem = useAction
|
||||||
|
|
||||||
export default useRemoveItem
|
export default useRemoveItem
|
||||||
|
@ -87,6 +87,10 @@ export interface Cart {
|
|||||||
discounts?: Discount[]
|
discounts?: Discount[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cart mutations
|
||||||
|
*/
|
||||||
|
|
||||||
// Base cart item body used for cart mutations
|
// Base cart item body used for cart mutations
|
||||||
export interface CartItemBody {
|
export interface CartItemBody {
|
||||||
variantId: string
|
variantId: string
|
||||||
@ -99,14 +103,35 @@ export interface GetCartHandlerBody {
|
|||||||
cartId?: string
|
cartId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Body used by the update operation
|
// Body used by the add item to cart operation
|
||||||
|
export interface AddCartItemBody<T extends CartItemBody> {
|
||||||
|
item: T
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body expected by the add item to cart operation handler
|
||||||
|
export interface AddCartItemHandlerBody<T extends CartItemBody>
|
||||||
|
extends Partial<AddCartItemBody<T>> {
|
||||||
|
cartId?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body used by the update cart item operation
|
||||||
export interface UpdateCartItemBody<T extends CartItemBody> {
|
export interface UpdateCartItemBody<T extends CartItemBody> {
|
||||||
itemId: string
|
itemId: string
|
||||||
item: T
|
item: T
|
||||||
}
|
}
|
||||||
|
|
||||||
// Body expected by the update operation handler
|
// Body expected by the update cart item operation handler
|
||||||
export interface UpdateCartItemHandlerBody<T extends CartItemBody>
|
export interface UpdateCartItemHandlerBody<T extends CartItemBody>
|
||||||
extends Partial<UpdateCartItemBody<T>> {
|
extends Partial<UpdateCartItemBody<T>> {
|
||||||
cartId?: string
|
cartId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Body used by the remove cart item operation
|
||||||
|
export interface RemoveCartItemBody {
|
||||||
|
itemId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body expected by the remove cart item operation handler
|
||||||
|
export interface RemoveCartItemHandlerBody extends Partial<RemoveCartItemBody> {
|
||||||
|
cartId?: string
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user