4
0
forked from crowetic/commerce

Add list of products to the returned wishlist

This commit is contained in:
Luis Alvarez 2020-10-27 02:13:22 -05:00
parent 4772878234
commit 95fd730f0a
6 changed files with 88 additions and 23 deletions

View File

@ -1,8 +1,13 @@
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
import { BigcommerceConfig, getConfig } from '..'
import { definitions } from '../definitions/wishlist'
import { BigcommerceConfig, getConfig } from '..'
import getAllProducts, { ProductEdge } from './get-all-products'
export type Wishlist = definitions['wishlist_Full']
export type Wishlist = Omit<definitions['wishlist_Full'], 'items'> & {
items?: (NonNullable<definitions['wishlist_Full']['items']>[0] & {
product?: ProductEdge['node']
})[]
}
export type GetCustomerWishlistResult<
T extends { wishlist?: any } = { wishlist?: Wishlist }
@ -15,6 +20,7 @@ export type GetCustomerWishlistVariables = {
async function getCustomerWishlist(opts: {
variables: GetCustomerWishlistVariables
config?: BigcommerceConfig
includeProducts?: boolean
}): Promise<GetCustomerWishlistResult>
async function getCustomerWishlist<
@ -24,25 +30,54 @@ async function getCustomerWishlist<
url: string
variables: V
config?: BigcommerceConfig
includeProducts?: boolean
}): Promise<GetCustomerWishlistResult<T>>
async function getCustomerWishlist({
config,
variables,
includeProducts,
}: {
url?: string
variables: GetCustomerWishlistVariables
config?: BigcommerceConfig
includeProducts?: boolean
}): Promise<GetCustomerWishlistResult> {
config = getConfig(config)
const { data } = await config.storeApiFetch<
const { data = [] } = await config.storeApiFetch<
RecursivePartial<{ data: Wishlist[] }>
>(`/v3/wishlists?customer_id=${variables.customerId}`)
const wishlists = (data as RecursiveRequired<typeof data>) ?? []
const wishlist = wishlists[0]
const wishlist = data[0]
return { wishlist }
if (includeProducts && wishlist?.items?.length) {
const entityIds = wishlist.items
?.map((item) => item?.product_id)
.filter((id): id is number => !!id)
if (entityIds?.length) {
const graphqlData = await getAllProducts({
variables: { first: 100, entityIds },
config,
})
// Put the products in an object that we can use to get them by id
const productsById = graphqlData.products.reduce<{
[k: number]: ProductEdge
}>((prods, p) => {
prods[p.node.entityId] = p
return prods
}, {})
// Populate the wishlist items with the graphql products
wishlist.items.forEach((item) => {
const product = item && productsById[item.product_id!]
if (item && product) {
item.product = product.node
}
})
}
}
return { wishlist: wishlist as RecursiveRequired<typeof wishlist> }
}
export default getCustomerWishlist

View File

@ -1,11 +1,11 @@
import getCustomerId from '../../operations/get-customer-id'
import type { Wishlist, WishlistHandlers } from '..'
import getCustomerWishlist from '../../operations/get-customer-wishlist'
import type { Wishlist, WishlistHandlers } from '..'
// Return wishlist info
const getWishlist: WishlistHandlers['getWishlist'] = async ({
res,
body: { customerToken },
body: { customerToken, includeProducts },
config,
}) => {
let result: { data?: Wishlist } = {}
@ -24,8 +24,10 @@ const getWishlist: WishlistHandlers['getWishlist'] = async ({
const { wishlist } = await getCustomerWishlist({
variables: { customerId },
includeProducts,
config,
})
result = { data: wishlist }
}

View File

@ -4,10 +4,12 @@ import createApiHandler, {
BigcommerceHandler,
} from '../utils/create-api-handler'
import { BigcommerceApiError } from '../utils/errors'
import type { Wishlist } from '../operations/get-customer-wishlist'
import getWishlist from './handlers/get-wishlist'
import addItem from './handlers/add-item'
import removeItem from './handlers/remove-item'
import { definitions } from '../definitions/wishlist'
export type { Wishlist }
export type ItemBody = {
productId: number
@ -27,10 +29,11 @@ export type WishlistBody = {
export type AddWishlistBody = { wishlist: WishlistBody }
export type Wishlist = definitions['wishlist_Full']
export type WishlistHandlers = {
getWishlist: BigcommerceHandler<Wishlist, { customerToken?: string }>
getWishlist: BigcommerceHandler<
Wishlist,
{ customerToken?: string; includeProducts?: boolean }
>
addItem: BigcommerceHandler<
Wishlist,
{ customerToken?: string } & Partial<AddItemBody>
@ -58,7 +61,10 @@ const wishlistApi: BigcommerceApiHandler<Wishlist, WishlistHandlers> = async (
try {
// Return current wishlist info
if (req.method === 'GET') {
const body = { customerToken }
const body = {
customerToken,
includeProducts: req.query.products === '1',
}
return await handlers['getWishlist']({ req, res, config, body })
}

View File

@ -11,23 +11,44 @@ const defaultOpts = {
export type { Wishlist }
export const fetcher: HookFetcher<Wishlist | null, { customerId?: number }> = (
export interface UseWishlistOptions {
includeProducts?: boolean
}
export interface UseWishlistInput extends UseWishlistOptions {
customerId?: number
}
export const fetcher: HookFetcher<Wishlist | null, UseWishlistInput> = (
options,
{ customerId },
{ customerId, includeProducts },
fetch
) => {
return customerId ? fetch({ ...defaultOpts, ...options }) : null
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, { customerId?: number }>
swrOptions?: SwrOptions<Wishlist | null, UseWishlistInput>
) {
const useWishlists = () => {
const useWishlist = ({ includeProducts }: UseWishlistOptions = {}) => {
const { data: customer } = useCustomer()
const response = useCommerceWishlist(
defaultOpts,
[['customerId', customer?.entityId]],
[
['customerId', customer?.entityId],
['includeProducts', includeProducts],
],
customFetcher,
{
revalidateOnFocus: false,
@ -47,9 +68,9 @@ export function extendHook(
return response
}
useWishlists.extend = extendHook
useWishlist.extend = extendHook
return useWishlists
return useWishlist
}
export default extendHook(fetcher)

View File

@ -21,4 +21,4 @@ export type HookFetcherOptions = {
method?: string
}
export type HookInput = [string, string | number | undefined][]
export type HookInput = [string, string | number | boolean | undefined][]

View File

@ -20,7 +20,8 @@ export default function Home({
categories,
brands,
}: InferGetStaticPropsType<typeof getStaticProps>) {
const { data } = useWishlist()
const { data } = useWishlist({ includeProducts: true })
console.log(data)
return (
<Container>
<div className="grid grid-cols-12 gap-8 mt-3 mb-20">