From 5cfa8241f66e6b952e3e6601e76a375c34a2257f Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Tue, 2 Feb 2021 20:16:47 -0500 Subject: [PATCH] Updated the useAddItem and useRemoveItem hooks --- framework/bigcommerce/api/cart/index.ts | 30 ++--------- framework/bigcommerce/cart/use-add-item.tsx | 19 ++++--- .../bigcommerce/cart/use-remove-item.tsx | 52 +++++++++++++------ framework/bigcommerce/types.ts | 10 ++++ framework/commerce/cart/use-add-item.tsx | 4 ++ framework/commerce/cart/use-remove-item.tsx | 5 ++ framework/commerce/types.ts | 29 ++++++++++- 7 files changed, 98 insertions(+), 51 deletions(-) diff --git a/framework/bigcommerce/api/cart/index.ts b/framework/bigcommerce/api/cart/index.ts index 7b5be31c3..4ee668895 100644 --- a/framework/bigcommerce/api/cart/index.ts +++ b/framework/bigcommerce/api/cart/index.ts @@ -11,42 +11,22 @@ import removeItem from './handlers/remove-item' import type { BigcommerceCart, GetCartHandlerBody, + AddCartItemHandlerBody, UpdateCartItemHandlerBody, + RemoveCartItemHandlerBody, } 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 = { getCart: BigcommerceHandler - addItem: BigcommerceHandler< - BigcommerceCart, - { cartId?: string } & Partial - > + addItem: BigcommerceHandler updateItem: BigcommerceHandler - removeItem: BigcommerceHandler< - BigcommerceCart, - { cartId?: string } & Partial - > + removeItem: BigcommerceHandler } const METHODS = ['GET', 'POST', 'PUT', 'DELETE'] // TODO: a complete implementation should have schema validation for `req.body` -const cartApi: BigcommerceApiHandler = async ( +const cartApi: BigcommerceApiHandler = async ( req, res, config, diff --git a/framework/bigcommerce/cart/use-add-item.tsx b/framework/bigcommerce/cart/use-add-item.tsx index 38ac69650..c66ee462a 100644 --- a/framework/bigcommerce/cart/use-add-item.tsx +++ b/framework/bigcommerce/cart/use-add-item.tsx @@ -1,13 +1,16 @@ import { useCallback } from 'react' import type { HookFetcher } from '@commerce/utils/types' 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 type { - ItemBody, - AddItemBody, - Cart as BigcommerceCart, -} from '../api/cart' + AddCartItemBody, + Cart, + BigcommerceCart, + CartItemBody, +} from '../types' import useCart from './use-cart' const defaultOpts = { @@ -15,9 +18,9 @@ const defaultOpts = { method: 'POST', } -export type AddItemInput = ItemBody +export type AddItemInput = UseAddItemInput -export const fetcher: HookFetcher = async ( +export const fetcher: HookFetcher = async ( options, { item }, fetch @@ -31,7 +34,7 @@ export const fetcher: HookFetcher = async ( }) } - const data = await fetch({ + const data = await fetch({ ...defaultOpts, ...options, body: { item }, diff --git a/framework/bigcommerce/cart/use-remove-item.tsx b/framework/bigcommerce/cart/use-remove-item.tsx index 6f25c0c9e..c8cdaeb0d 100644 --- a/framework/bigcommerce/cart/use-remove-item.tsx +++ b/framework/bigcommerce/cart/use-remove-item.tsx @@ -1,8 +1,16 @@ import { useCallback } from 'react' 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 type { RemoveItemBody, Cart as BigcommerceCart } from '../api/cart' +import type { + RemoveCartItemBody, + Cart, + BigcommerceCart, + LineItem, +} from '../types' import useCart from './use-cart' const defaultOpts = { @@ -10,11 +18,15 @@ const defaultOpts = { method: 'DELETE', } -export type RemoveItemInput = { - id: string -} +export type RemoveItemFn = T extends LineItem + ? (input?: RemoveItemInput) => Promise + : (input: RemoveItemInput) => Promise -export const fetcher: HookFetcher = async ( +export type RemoveItemInput = T extends LineItem + ? Partial + : UseRemoveItemInput + +export const fetcher: HookFetcher = async ( options, { itemId }, fetch @@ -28,21 +40,29 @@ export const fetcher: HookFetcher = async ( } export function extendHook(customFetcher: typeof fetcher) { - const useRemoveItem = (item?: any) => { + const useRemoveItem = ( + item?: T + ) => { const { mutate } = useCart() - const fn = useCartRemoveItem( + const fn = useCartRemoveItem( defaultOpts, customFetcher ) + const removeItem: RemoveItemFn = async (input) => { + const itemId = input?.id ?? item?.id - return useCallback( - async function removeItem(input: RemoveItemInput) { - const data = await fn({ itemId: input.id ?? item?.id }) - await mutate(data, false) - return data - }, - [fn, mutate] - ) + if (!itemId) { + throw new ValidationError({ + message: 'Invalid input used for this operation', + }) + } + + const data = await fn({ itemId }) + await mutate(data, false) + return data + } + + return useCallback(removeItem as RemoveItemFn, [fn, mutate]) } useRemoveItem.extend = extendHook diff --git a/framework/bigcommerce/types.ts b/framework/bigcommerce/types.ts index 26d093bfe..90afb425d 100644 --- a/framework/bigcommerce/types.ts +++ b/framework/bigcommerce/types.ts @@ -45,8 +45,18 @@ export interface CartItemBody extends Core.CartItemBody { export interface GetCartHandlerBody extends Core.GetCartHandlerBody {} +export interface AddCartItemBody extends Core.AddCartItemBody {} + +export interface AddCartItemHandlerBody + extends Core.AddCartItemHandlerBody {} + export interface UpdateCartItemBody extends Core.UpdateCartItemBody {} export interface UpdateCartItemHandlerBody extends Core.UpdateCartItemHandlerBody {} + +export interface RemoveCartItemBody extends Core.RemoveCartItemBody {} + +export interface RemoveCartItemHandlerBody + extends Core.RemoveCartItemHandlerBody {} diff --git a/framework/commerce/cart/use-add-item.tsx b/framework/commerce/cart/use-add-item.tsx index f6c069f2b..2f6422ab3 100644 --- a/framework/commerce/cart/use-add-item.tsx +++ b/framework/commerce/cart/use-add-item.tsx @@ -1,4 +1,8 @@ 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 const useAddItem = useAction diff --git a/framework/commerce/cart/use-remove-item.tsx b/framework/commerce/cart/use-remove-item.tsx index dfa60c363..8a63b1b73 100644 --- a/framework/commerce/cart/use-remove-item.tsx +++ b/framework/commerce/cart/use-remove-item.tsx @@ -1,5 +1,10 @@ import useAction from '../utils/use-action' +// Input expected by the action returned by the `useRemoveItem` hook +export interface RemoveItemInput { + id: string +} + const useRemoveItem = useAction export default useRemoveItem diff --git a/framework/commerce/types.ts b/framework/commerce/types.ts index 61bf0d5e7..cc04f52e1 100644 --- a/framework/commerce/types.ts +++ b/framework/commerce/types.ts @@ -87,6 +87,10 @@ export interface Cart { discounts?: Discount[] } +/** + * Cart mutations + */ + // Base cart item body used for cart mutations export interface CartItemBody { variantId: string @@ -99,14 +103,35 @@ export interface GetCartHandlerBody { cartId?: string } -// Body used by the update operation +// Body used by the add item to cart operation +export interface AddCartItemBody { + item: T +} + +// Body expected by the add item to cart operation handler +export interface AddCartItemHandlerBody + extends Partial> { + cartId?: string +} + +// Body used by the update cart item operation export interface UpdateCartItemBody { itemId: string item: T } -// Body expected by the update operation handler +// Body expected by the update cart item operation handler export interface UpdateCartItemHandlerBody extends Partial> { 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 { + cartId?: string +}