Move useCustomer to the new hook

This commit is contained in:
Luis Alvarez 2021-02-11 13:26:09 -05:00
parent 8966f0b583
commit d8de84bed1
8 changed files with 102 additions and 49 deletions

View File

@ -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<Customer | null> = async (
options,
_,
fetch
) => {
const data = await fetch<CustomerData | null>({ ...defaultOpts, ...options })
return data?.customer ?? null
}
export function extendHook(
customFetcher: typeof fetcher,
swrOptions?: SwrOptions<Customer | null>
) {
const useCustomer = () => {
return useCommerceCustomer(defaultOpts, [], customFetcher, {
revalidateOnFocus: false,
...swrOptions,
})
}
useCustomer.extend = extendHook
return useCustomer
}
export default extendHook(fetcher)
export default useCustomer as UseCustomer<BigcommerceProvider>

View File

@ -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

View File

@ -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<P extends Provider> = Prop<
Prop<P, 'customer'>,
'useCustomer'
>
export type UseCustomerInput<P extends Provider> = UseHookInput<
UseCustomerHandler<P>
>
export type CustomerResponse<P extends Provider> = UseHookResponse<
UseCustomerHandler<P>
>
export type UseCustomer<P extends Provider> = Partial<
UseCustomerInput<P>
> extends UseCustomerInput<P>
? (input?: UseCustomerInput<P>) => CustomerResponse<P>
: (input: UseCustomerInput<P>) => CustomerResponse<P>
export const fetcher: HookFetcherFn<Customer | null> = async ({
options,
fetch,
normalize,
}) => {
const data = await fetch({ ...options })
return data && normalize ? normalize(data) : data
}
export default function useCustomer<P extends Provider>(
input: UseCustomerInput<P> = {}
) {
const { providerRef, fetcherRef } = useCommerce<P>()
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
},
})
}

View File

@ -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<CommerceContextValue<any> | {}>({})
@ -21,6 +20,9 @@ export type Provider = CommerceConfig & {
wishlist?: {
useWishlist?: HookHandler<Wishlist | null, any, any>
}
customer: {
useCustomer?: HookHandler<Customer | null, any, any>
}
}
export type CommerceProps<P extends Provider> = {

View File

@ -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
*/

View File

@ -1,5 +0,0 @@
import useData from './utils/use-data'
const useCustomer = useData
export default useCustomer

View File

@ -79,7 +79,7 @@ export type HookHandler<
}): ResponseState<Data> & State
fetchOptions: HookFetcherOptions
fetcher?: HookFetcherFn<Data, FetchInput, Result, Body>
normalizer?(data: Result): Data
normalizer?(data: NonNullable<Result>): Data
}
export type SwrOptions<Data, Input = null, Result = any> = ConfigInterface<

View File

@ -22,10 +22,10 @@ export type WishlistResponse<P extends Provider> = UseHookResponse<
>
export type UseWishlist<P extends Provider> = Partial<
WishlistResponse<P>
> extends WishlistResponse<P>
? (input?: WishlistResponse<P>) => WishlistResponse<P>
: (input: WishlistResponse<P>) => WishlistResponse<P>
UseWishlistInput<P>
> extends UseWishlistInput<P>
? (input?: UseWishlistInput<P>) => WishlistResponse<P>
: (input: UseWishlistInput<P>) => WishlistResponse<P>
export const fetcher: HookFetcherFn<Wishlist | null> = async ({
options,