forked from crowetic/commerce
Moved useWishlist to use new handler
This commit is contained in:
parent
271ed01631
commit
8966f0b583
@ -1,4 +1,4 @@
|
|||||||
import useCommerceCart, { UseCart } from '@commerce/cart/use-cart'
|
import useCart, { UseCart } from '@commerce/cart/use-cart'
|
||||||
import type { BigcommerceProvider } from '..'
|
import type { BigcommerceProvider } from '..'
|
||||||
|
|
||||||
export default useCommerceCart as UseCart<BigcommerceProvider>
|
export default useCart as UseCart<BigcommerceProvider>
|
||||||
|
@ -3,6 +3,8 @@ import { FetcherError } from '@commerce/utils/errors'
|
|||||||
import type { Fetcher, HookHandler } from '@commerce/utils/types'
|
import type { Fetcher, HookHandler } from '@commerce/utils/types'
|
||||||
import type { FetchCartInput } from '@commerce/cart/use-cart'
|
import type { FetchCartInput } from '@commerce/cart/use-cart'
|
||||||
import { normalizeCart } from './lib/normalize'
|
import { normalizeCart } from './lib/normalize'
|
||||||
|
import type { Wishlist } from './api/wishlist'
|
||||||
|
import useCustomer from './customer/use-customer'
|
||||||
import type { Cart } from './types'
|
import type { Cart } from './types'
|
||||||
|
|
||||||
async function getText(res: Response) {
|
async function getText(res: Response) {
|
||||||
@ -76,9 +78,9 @@ const useCart: HookHandler<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const useWishlist: HookHandler<
|
const useWishlist: HookHandler<
|
||||||
Cart | null,
|
Wishlist | null,
|
||||||
{},
|
{ includeProducts?: boolean },
|
||||||
FetchCartInput,
|
{ customerId?: number; includeProducts: boolean },
|
||||||
any,
|
any,
|
||||||
any,
|
any,
|
||||||
{ isEmpty?: boolean }
|
{ isEmpty?: boolean }
|
||||||
@ -87,6 +89,45 @@ const useWishlist: HookHandler<
|
|||||||
url: '/api/bigcommerce/wishlist',
|
url: '/api/bigcommerce/wishlist',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
},
|
},
|
||||||
|
fetcher({ input: { customerId, includeProducts }, options, fetch }) {
|
||||||
|
if (!customerId) return null
|
||||||
|
|
||||||
|
// Use a dummy base as we only care about the relative path
|
||||||
|
const url = new URL(options.url!, 'http://a')
|
||||||
|
|
||||||
|
if (includeProducts) url.searchParams.set('products', '1')
|
||||||
|
|
||||||
|
return fetch({
|
||||||
|
url: url.pathname + url.search,
|
||||||
|
method: options.method,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
useHook({ input, useData }) {
|
||||||
|
const { data: customer } = useCustomer()
|
||||||
|
const response = useData({
|
||||||
|
input: [
|
||||||
|
['customerId', customer?.id],
|
||||||
|
['includeProducts', input.includeProducts],
|
||||||
|
],
|
||||||
|
swrOptions: {
|
||||||
|
revalidateOnFocus: false,
|
||||||
|
...input.swrOptions,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
Object.create(response, {
|
||||||
|
isEmpty: {
|
||||||
|
get() {
|
||||||
|
return (response.data?.items?.length || 0) <= 0
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[response]
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const bigcommerceProvider = {
|
export const bigcommerceProvider = {
|
||||||
|
@ -1,78 +1,4 @@
|
|||||||
import { HookFetcher } from '@commerce/utils/types'
|
import useWishlist, { UseWishlist } from '@commerce/wishlist/use-wishlist'
|
||||||
import { SwrOptions } from '@commerce/utils/use-data'
|
import type { BigcommerceProvider } from '..'
|
||||||
import useResponse from '@commerce/utils/use-response'
|
|
||||||
import useCommerceWishlist from '@commerce/wishlist/use-wishlist'
|
|
||||||
import type { Wishlist } from '../api/wishlist'
|
|
||||||
import useCustomer from '../customer/use-customer'
|
|
||||||
|
|
||||||
const defaultOpts = {
|
export default useWishlist as UseWishlist<BigcommerceProvider>
|
||||||
url: '/api/bigcommerce/wishlist',
|
|
||||||
method: 'GET',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type { Wishlist }
|
|
||||||
|
|
||||||
export interface UseWishlistOptions {
|
|
||||||
includeProducts?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UseWishlistInput extends UseWishlistOptions {
|
|
||||||
customerId?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetcher: HookFetcher<Wishlist | null, UseWishlistInput> = (
|
|
||||||
options,
|
|
||||||
{ customerId, includeProducts },
|
|
||||||
fetch
|
|
||||||
) => {
|
|
||||||
if (!customerId) return null
|
|
||||||
|
|
||||||
// Use a dummy base as we only care about the relative path
|
|
||||||
const url = new URL(options?.url ?? defaultOpts.url, 'http://a')
|
|
||||||
|
|
||||||
if (includeProducts) url.searchParams.set('products', '1')
|
|
||||||
|
|
||||||
return fetch({
|
|
||||||
url: url.pathname + url.search,
|
|
||||||
method: options?.method ?? defaultOpts.method,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function extendHook(
|
|
||||||
customFetcher: typeof fetcher,
|
|
||||||
swrOptions?: SwrOptions<Wishlist | null, UseWishlistInput>
|
|
||||||
) {
|
|
||||||
const useWishlist = ({ includeProducts }: UseWishlistOptions = {}) => {
|
|
||||||
const { data: customer } = useCustomer()
|
|
||||||
const response = useCommerceWishlist(
|
|
||||||
defaultOpts,
|
|
||||||
[
|
|
||||||
['customerId', customer?.id],
|
|
||||||
['includeProducts', includeProducts],
|
|
||||||
],
|
|
||||||
customFetcher,
|
|
||||||
{
|
|
||||||
revalidateOnFocus: false,
|
|
||||||
...swrOptions,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const res = useResponse(response, {
|
|
||||||
descriptors: {
|
|
||||||
isEmpty: {
|
|
||||||
get() {
|
|
||||||
return (response.data?.items?.length || 0) <= 0
|
|
||||||
},
|
|
||||||
set: (x) => x,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
useWishlist.extend = extendHook
|
|
||||||
|
|
||||||
return useWishlist
|
|
||||||
}
|
|
||||||
|
|
||||||
export default extendHook(fetcher)
|
|
||||||
|
@ -60,7 +60,7 @@ export default function useCart<P extends Provider>(
|
|||||||
input,
|
input,
|
||||||
useData(ctx) {
|
useData(ctx) {
|
||||||
const response = useData(
|
const response = useData(
|
||||||
{ ...opts, fetcher: wrapper },
|
{ ...opts!, fetcher: wrapper },
|
||||||
ctx?.input ?? [],
|
ctx?.input ?? [],
|
||||||
provider.fetcher ?? fetcherRef.current,
|
provider.fetcher ?? fetcherRef.current,
|
||||||
ctx?.swrOptions ?? input.swrOptions
|
ctx?.swrOptions ?? input.swrOptions
|
||||||
|
@ -8,18 +8,18 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { Fetcher, HookHandler } from './utils/types'
|
import { Fetcher, HookHandler } from './utils/types'
|
||||||
import { Cart } from './types'
|
|
||||||
import type { FetchCartInput } from './cart/use-cart'
|
import type { FetchCartInput } from './cart/use-cart'
|
||||||
|
import type { Cart, Wishlist } from './types'
|
||||||
|
|
||||||
const Commerce = createContext<CommerceContextValue<any> | {}>({})
|
const Commerce = createContext<CommerceContextValue<any> | {}>({})
|
||||||
|
|
||||||
export type Provider = CommerceConfig & {
|
export type Provider = CommerceConfig & {
|
||||||
fetcher: Fetcher
|
fetcher: Fetcher
|
||||||
cart?: {
|
cart?: {
|
||||||
useCart?: HookHandler<Cart | null, {}, FetchCartInput>
|
useCart?: HookHandler<Cart | null, any, FetchCartInput>
|
||||||
}
|
}
|
||||||
wishlist?: {
|
wishlist?: {
|
||||||
useWishlist?: HookHandler<Cart | null, {}, FetchCartInput>
|
useWishlist?: HookHandler<Wishlist | null, any, any>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import type { Wishlist as BCWishlist } from '@framework/api/wishlist'
|
||||||
|
|
||||||
export interface Discount {
|
export interface Discount {
|
||||||
// The value of the discount, can be an amount or percentage
|
// The value of the discount, can be an amount or percentage
|
||||||
value: number
|
value: number
|
||||||
@ -87,6 +89,9 @@ export interface Cart {
|
|||||||
discounts?: Discount[]
|
discounts?: Discount[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Properly define this type
|
||||||
|
export interface Wishlist extends BCWishlist {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cart mutations
|
* Cart mutations
|
||||||
*/
|
*/
|
||||||
|
@ -33,21 +33,20 @@ export type HookFetcher<Data, Input = null, Result = any> = (
|
|||||||
|
|
||||||
export type HookFetcherFn<
|
export type HookFetcherFn<
|
||||||
Data,
|
Data,
|
||||||
Input = unknown,
|
Input = never,
|
||||||
Result = any,
|
Result = any,
|
||||||
Body = any
|
Body = any
|
||||||
> = (context: {
|
> = (context: {
|
||||||
options: HookFetcherOptions | null
|
options: HookFetcherOptions
|
||||||
input: Input
|
input: Input
|
||||||
fetch: <T = Result, B = Body>(options: FetcherOptions<B>) => Promise<T>
|
fetch: <T = Result, B = Body>(options: FetcherOptions<B>) => Promise<T>
|
||||||
normalize?(data: Result): Data
|
normalize?(data: Result): Data
|
||||||
}) => Data | Promise<Data>
|
}) => Data | Promise<Data>
|
||||||
|
|
||||||
export type HookFetcherOptions = {
|
export type HookFetcherOptions = { method?: string } & (
|
||||||
query?: string
|
| { query: string; url?: string }
|
||||||
url?: string
|
| { query?: string; url: string }
|
||||||
method?: string
|
)
|
||||||
}
|
|
||||||
|
|
||||||
export type HookInputValue = string | number | boolean | undefined
|
export type HookInputValue = string | number | boolean | undefined
|
||||||
|
|
||||||
@ -63,7 +62,7 @@ export type HookHandler<
|
|||||||
// Input expected by the hook
|
// Input expected by the hook
|
||||||
Input extends { [k: string]: unknown } = {},
|
Input extends { [k: string]: unknown } = {},
|
||||||
// Input expected before doing a fetch operation
|
// Input expected before doing a fetch operation
|
||||||
FetchInput extends HookFetchInput = never,
|
FetchInput extends HookFetchInput = {},
|
||||||
// Data returned by the API after a fetch operation
|
// Data returned by the API after a fetch operation
|
||||||
Result = any,
|
Result = any,
|
||||||
// Body expected by the API endpoint
|
// Body expected by the API endpoint
|
||||||
@ -78,7 +77,7 @@ export type HookHandler<
|
|||||||
swrOptions?: SwrOptions<Data, FetchInput, Result>
|
swrOptions?: SwrOptions<Data, FetchInput, Result>
|
||||||
}): ResponseState<Data>
|
}): ResponseState<Data>
|
||||||
}): ResponseState<Data> & State
|
}): ResponseState<Data> & State
|
||||||
fetchOptions?: HookFetcherOptions
|
fetchOptions: HookFetcherOptions
|
||||||
fetcher?: HookFetcherFn<Data, FetchInput, Result, Body>
|
fetcher?: HookFetcherFn<Data, FetchInput, Result, Body>
|
||||||
normalizer?(data: Result): Data
|
normalizer?(data: Result): Data
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ export type ResponseState<Result> = responseInterface<Result, CommerceError> & {
|
|||||||
export type UseData = <
|
export type UseData = <
|
||||||
Data = any,
|
Data = any,
|
||||||
Input extends { [k: string]: unknown } = {},
|
Input extends { [k: string]: unknown } = {},
|
||||||
FetchInput extends HookFetchInput = never,
|
FetchInput extends HookFetchInput = {},
|
||||||
Result = any,
|
Result = any,
|
||||||
Body = any
|
Body = any
|
||||||
>(
|
>(
|
||||||
@ -33,7 +33,7 @@ export type UseData = <
|
|||||||
const useData: UseData = (options, input, fetcherFn, swrOptions) => {
|
const useData: UseData = (options, input, fetcherFn, swrOptions) => {
|
||||||
const hookInput = Array.isArray(input) ? input : Object.entries(input)
|
const hookInput = Array.isArray(input) ? input : Object.entries(input)
|
||||||
const fetcher = async (
|
const fetcher = async (
|
||||||
url?: string,
|
url: string,
|
||||||
query?: string,
|
query?: string,
|
||||||
method?: string,
|
method?: string,
|
||||||
...args: any[]
|
...args: any[]
|
||||||
|
@ -1,20 +1,62 @@
|
|||||||
|
import type { Wishlist } from '../types'
|
||||||
import type {
|
import type {
|
||||||
HookSwrInput,
|
Prop,
|
||||||
HookFetcher,
|
HookFetcherFn,
|
||||||
HookFetcherOptions,
|
UseHookInput,
|
||||||
|
UseHookResponse,
|
||||||
} from '../utils/types'
|
} from '../utils/types'
|
||||||
import useData, { ResponseState, SwrOptions } from '../utils/use-data'
|
import useData from '../utils/use-data-2'
|
||||||
|
import { Provider, useCommerce } from '..'
|
||||||
|
|
||||||
export type WishlistResponse<Result> = ResponseState<Result> & {
|
export type UseWishlistHandler<P extends Provider> = Prop<
|
||||||
isEmpty?: boolean
|
Prop<P, 'wishlist'>,
|
||||||
|
'useWishlist'
|
||||||
|
>
|
||||||
|
|
||||||
|
export type UseWishlistInput<P extends Provider> = UseHookInput<
|
||||||
|
UseWishlistHandler<P>
|
||||||
|
>
|
||||||
|
|
||||||
|
export type WishlistResponse<P extends Provider> = UseHookResponse<
|
||||||
|
UseWishlistHandler<P>
|
||||||
|
>
|
||||||
|
|
||||||
|
export type UseWishlist<P extends Provider> = Partial<
|
||||||
|
WishlistResponse<P>
|
||||||
|
> extends WishlistResponse<P>
|
||||||
|
? (input?: WishlistResponse<P>) => WishlistResponse<P>
|
||||||
|
: (input: WishlistResponse<P>) => WishlistResponse<P>
|
||||||
|
|
||||||
|
export const fetcher: HookFetcherFn<Wishlist | null> = async ({
|
||||||
|
options,
|
||||||
|
fetch,
|
||||||
|
normalize,
|
||||||
|
}) => {
|
||||||
|
const data = await fetch({ ...options })
|
||||||
|
return data && normalize ? normalize(data) : data
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useWishlist<Result, Input = null>(
|
export default function useWishlist<P extends Provider>(
|
||||||
options: HookFetcherOptions,
|
input: UseWishlistInput<P> = {}
|
||||||
input: HookSwrInput,
|
) {
|
||||||
fetcherFn: HookFetcher<Result, Input>,
|
const { providerRef, fetcherRef } = useCommerce<P>()
|
||||||
swrOptions?: SwrOptions<Result, Input>
|
|
||||||
): WishlistResponse<Result> {
|
const provider = providerRef.current
|
||||||
const response = useData(options, input, fetcherFn, swrOptions)
|
const opts = provider.wishlist?.useWishlist
|
||||||
return response
|
|
||||||
|
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
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user