diff --git a/framework/bigcommerce/customer/use-customer.tsx b/framework/bigcommerce/customer/use-customer.tsx index f44f16c1f..95adb6fb3 100644 --- a/framework/bigcommerce/customer/use-customer.tsx +++ b/framework/bigcommerce/customer/use-customer.tsx @@ -1,38 +1,4 @@ -import type { HookFetcher } from '@commerce/utils/types' -import type { SwrOptions } from '@commerce/utils/use-data' -import useCommerceCustomer from '@commerce/use-customer' -import type { Customer, CustomerData } from '../api/customers' +import useCustomer, { UseCustomer } from '@commerce/customer/use-customer' +import type { BigcommerceProvider } from '..' -const defaultOpts = { - url: '/api/bigcommerce/customers', - method: 'GET', -} - -export type { Customer } - -export const fetcher: HookFetcher = async ( - options, - _, - fetch -) => { - const data = await fetch({ ...defaultOpts, ...options }) - return data?.customer ?? null -} - -export function extendHook( - customFetcher: typeof fetcher, - swrOptions?: SwrOptions -) { - const useCustomer = () => { - return useCommerceCustomer(defaultOpts, [], customFetcher, { - revalidateOnFocus: false, - ...swrOptions, - }) - } - - useCustomer.extend = extendHook - - return useCustomer -} - -export default extendHook(fetcher) +export default useCustomer as UseCustomer diff --git a/framework/bigcommerce/provider.tsx b/framework/bigcommerce/provider.tsx index 60106f7f8..d3ae4d171 100644 --- a/framework/bigcommerce/provider.tsx +++ b/framework/bigcommerce/provider.tsx @@ -4,6 +4,7 @@ import type { Fetcher, HookHandler } from '@commerce/utils/types' import type { FetchCartInput } from '@commerce/cart/use-cart' import { normalizeCart } from './lib/normalize' import type { Wishlist } from './api/wishlist' +import type { Customer, CustomerData } from './api/customers' import useCustomer from './customer/use-customer' import type { Cart } from './types' @@ -130,6 +131,28 @@ const useWishlist: HookHandler< }, } +const useCustomerHandler: HookHandler< + Customer | null, + {}, + {}, + CustomerData | null, + any +> = { + fetchOptions: { + url: '/api/bigcommerce/customers', + method: 'GET', + }, + normalizer: (data) => data.customer, + useHook({ input, useData }) { + return useData({ + swrOptions: { + revalidateOnFocus: false, + ...input.swrOptions, + }, + }) + }, +} + export const bigcommerceProvider = { locale: 'en-us', cartCookie: 'bc_cartId', @@ -137,6 +160,7 @@ export const bigcommerceProvider = { cartNormalizer: normalizeCart, cart: { useCart }, wishlist: { useWishlist }, + customer: { useCustomer: useCustomerHandler }, } export type BigcommerceProvider = typeof bigcommerceProvider diff --git a/framework/commerce/customer/use-customer.tsx b/framework/commerce/customer/use-customer.tsx new file mode 100644 index 000000000..f1675a544 --- /dev/null +++ b/framework/commerce/customer/use-customer.tsx @@ -0,0 +1,62 @@ +import type { Customer } from '../types' +import type { + Prop, + HookFetcherFn, + UseHookInput, + UseHookResponse, +} from '../utils/types' +import useData from '../utils/use-data-2' +import { Provider, useCommerce } from '..' + +export type UseCustomerHandler

= Prop< + Prop, + 'useCustomer' +> + +export type UseCustomerInput

= UseHookInput< + UseCustomerHandler

+> + +export type CustomerResponse

= UseHookResponse< + UseCustomerHandler

+> + +export type UseCustomer

= Partial< + UseCustomerInput

+> extends UseCustomerInput

+ ? (input?: UseCustomerInput

) => CustomerResponse

+ : (input: UseCustomerInput

) => CustomerResponse

+ +export const fetcher: HookFetcherFn = async ({ + options, + fetch, + normalize, +}) => { + const data = await fetch({ ...options }) + return data && normalize ? normalize(data) : data +} + +export default function useCustomer

( + input: UseCustomerInput

= {} +) { + const { providerRef, fetcherRef } = useCommerce

() + + const provider = providerRef.current + const opts = provider.customer?.useCustomer + + const fetcherFn = opts?.fetcher ?? fetcher + const useHook = opts?.useHook ?? ((ctx) => ctx.useData()) + + return useHook({ + input, + useData(ctx) { + const response = useData( + { ...opts!, fetcher: fetcherFn }, + ctx?.input ?? [], + provider.fetcher ?? fetcherRef.current, + ctx?.swrOptions ?? input.swrOptions + ) + return response + }, + }) +} diff --git a/framework/commerce/index.tsx b/framework/commerce/index.tsx index cb4136e3b..ccfc07e66 100644 --- a/framework/commerce/index.tsx +++ b/framework/commerce/index.tsx @@ -6,10 +6,9 @@ import { useMemo, useRef, } from 'react' -import * as React from 'react' import { Fetcher, HookHandler } from './utils/types' import type { FetchCartInput } from './cart/use-cart' -import type { Cart, Wishlist } from './types' +import type { Cart, Wishlist, Customer } from './types' const Commerce = createContext | {}>({}) @@ -21,6 +20,9 @@ export type Provider = CommerceConfig & { wishlist?: { useWishlist?: HookHandler } + customer: { + useCustomer?: HookHandler + } } export type CommerceProps

= { diff --git a/framework/commerce/types.ts b/framework/commerce/types.ts index 743a93e4e..31aaa6fd7 100644 --- a/framework/commerce/types.ts +++ b/framework/commerce/types.ts @@ -1,4 +1,5 @@ import type { Wishlist as BCWishlist } from '@framework/api/wishlist' +import type { Customer as BCCustomer } from '@framework/api/customers' export interface Discount { // The value of the discount, can be an amount or percentage @@ -92,6 +93,9 @@ export interface Cart { // TODO: Properly define this type export interface Wishlist extends BCWishlist {} +// TODO: Properly define this type +export interface Customer extends BCCustomer {} + /** * Cart mutations */ diff --git a/framework/commerce/use-customer.tsx b/framework/commerce/use-customer.tsx deleted file mode 100644 index 8e2ff3ec2..000000000 --- a/framework/commerce/use-customer.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import useData from './utils/use-data' - -const useCustomer = useData - -export default useCustomer diff --git a/framework/commerce/utils/types.ts b/framework/commerce/utils/types.ts index dbde3e7ec..47da81a7f 100644 --- a/framework/commerce/utils/types.ts +++ b/framework/commerce/utils/types.ts @@ -79,7 +79,7 @@ export type HookHandler< }): ResponseState & State fetchOptions: HookFetcherOptions fetcher?: HookFetcherFn - normalizer?(data: Result): Data + normalizer?(data: NonNullable): Data } export type SwrOptions = ConfigInterface< diff --git a/framework/commerce/wishlist/use-wishlist.tsx b/framework/commerce/wishlist/use-wishlist.tsx index c2e0d2dc1..64bb5a1c1 100644 --- a/framework/commerce/wishlist/use-wishlist.tsx +++ b/framework/commerce/wishlist/use-wishlist.tsx @@ -22,10 +22,10 @@ export type WishlistResponse

= UseHookResponse< > export type UseWishlist

= Partial< - WishlistResponse

-> extends WishlistResponse

- ? (input?: WishlistResponse

) => WishlistResponse

- : (input: WishlistResponse

) => WishlistResponse

+ UseWishlistInput

+> extends UseWishlistInput

+ ? (input?: UseWishlistInput

) => WishlistResponse

+ : (input: UseWishlistInput

) => WishlistResponse

export const fetcher: HookFetcherFn = async ({ options,