mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
Search
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import getAllProducts from '../../operations/get-all-products'
|
||||
import type { ProductsHandlers } from '../products'
|
||||
|
||||
// Return current cart info
|
||||
@@ -11,9 +12,18 @@ const getProducts: ProductsHandlers['getProducts'] = async ({
|
||||
|
||||
if (search) url.searchParams.set('keyword', search)
|
||||
|
||||
const { data } = await config.storeApiFetch(url.pathname + url.search)
|
||||
// We only want the id of each product
|
||||
url.searchParams.set('include_fields', 'id')
|
||||
|
||||
res.status(200).json({ data })
|
||||
const { data } = await config.storeApiFetch<{ data: { id: number }[] }>(
|
||||
url.pathname + url.search
|
||||
)
|
||||
const entityIds = data.map((p) => p.id)
|
||||
const found = entityIds.length > 0
|
||||
// We want the GraphQL version of each product
|
||||
const { products } = await getAllProducts({ variables: { entityIds } })
|
||||
|
||||
res.status(200).json({ data: { products, found } })
|
||||
}
|
||||
|
||||
export default getProducts
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import type { definitions } from '../definitions/catalog'
|
||||
import isAllowedMethod from '../utils/is-allowed-method'
|
||||
import createApiHandler, {
|
||||
BigcommerceApiHandler,
|
||||
@@ -6,22 +5,24 @@ import createApiHandler, {
|
||||
} from '../utils/create-api-handler'
|
||||
import { BigcommerceApiError } from '../utils/errors'
|
||||
import getProducts from './handlers/get-products'
|
||||
import { Products } from '../operations/get-all-products'
|
||||
|
||||
export type Product = definitions['product_Full']
|
||||
export type SearchProductsData = {
|
||||
products: Products
|
||||
found: boolean
|
||||
}
|
||||
|
||||
export type ProductsHandlers = {
|
||||
getProducts: BigcommerceHandler<Product[], { search?: 'string' }>
|
||||
getProducts: BigcommerceHandler<SearchProductsData, { search?: 'string' }>
|
||||
}
|
||||
|
||||
const METHODS = ['GET']
|
||||
|
||||
// TODO: a complete implementation should have schema validation for `req.body`
|
||||
const cartApi: BigcommerceApiHandler<Product[], ProductsHandlers> = async (
|
||||
req,
|
||||
res,
|
||||
config,
|
||||
handlers
|
||||
) => {
|
||||
const cartApi: BigcommerceApiHandler<
|
||||
SearchProductsData,
|
||||
ProductsHandlers
|
||||
> = async (req, res, config, handlers) => {
|
||||
if (!isAllowedMethod(req, res, METHODS)) return
|
||||
|
||||
try {
|
||||
|
@@ -17,6 +17,7 @@ export const productInfoFragment = /* GraphQL */ `
|
||||
path
|
||||
brand {
|
||||
name
|
||||
entityId
|
||||
}
|
||||
description
|
||||
prices {
|
||||
|
@@ -9,6 +9,7 @@ import { BigcommerceConfig, getConfig, Images, ProductImageVariables } from '..'
|
||||
|
||||
export const getAllProductsQuery = /* GraphQL */ `
|
||||
query getAllProducts(
|
||||
$entityIds: [Int!]
|
||||
$first: Int = 10
|
||||
$imgSmallWidth: Int = 320
|
||||
$imgSmallHeight: Int
|
||||
@@ -20,7 +21,7 @@ export const getAllProductsQuery = /* GraphQL */ `
|
||||
$imgXLHeight: Int
|
||||
) {
|
||||
site {
|
||||
products(first: $first) {
|
||||
products(first: $first, entityIds: $entityIds) {
|
||||
pageInfo {
|
||||
startCursor
|
||||
endCursor
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import useSWR, { ConfigInterface } from 'swr'
|
||||
import { HookDeps, HookFetcher } from '@lib/commerce/utils/types'
|
||||
import { ConfigInterface } from 'swr'
|
||||
import { HookFetcher } from '@lib/commerce/utils/types'
|
||||
import useCommerceSearch from '@lib/commerce/products/use-search'
|
||||
import type { Product } from '../api/catalog/products'
|
||||
import { useCommerce } from '..'
|
||||
import type { SearchProductsData } from '../api/catalog/products'
|
||||
|
||||
const defaultOpts = {
|
||||
url: '/api/bigcommerce/catalog/products',
|
||||
@@ -13,7 +12,7 @@ export type SearchProductsInput = {
|
||||
search?: string
|
||||
}
|
||||
|
||||
export const fetcher: HookFetcher<Product[], SearchProductsInput> = (
|
||||
export const fetcher: HookFetcher<SearchProductsData, SearchProductsInput> = (
|
||||
options,
|
||||
{ search },
|
||||
fetch
|
||||
@@ -34,7 +33,7 @@ export function extendHook(
|
||||
swrOptions?: ConfigInterface
|
||||
) {
|
||||
const useSearch = (input: SearchProductsInput = {}) => {
|
||||
const response = useCommerceSearch<Product[]>(
|
||||
const response = useCommerceSearch<SearchProductsData>(
|
||||
defaultOpts,
|
||||
[['search', input.search]],
|
||||
customFetcher,
|
||||
|
3
lib/bigcommerce/schema.d.ts
vendored
3
lib/bigcommerce/schema.d.ts
vendored
@@ -1674,7 +1674,7 @@ export type ProductInfoFragment = { __typename?: 'Product' } & Pick<
|
||||
Product,
|
||||
'entityId' | 'name' | 'path' | 'description'
|
||||
> & {
|
||||
brand?: Maybe<{ __typename?: 'Brand' } & Pick<Brand, 'name'>>
|
||||
brand?: Maybe<{ __typename?: 'Brand' } & Pick<Brand, 'name' | 'entityId'>>
|
||||
prices?: Maybe<
|
||||
{ __typename?: 'Prices' } & {
|
||||
price: { __typename?: 'Money' } & Pick<Money, 'value' | 'currencyCode'>
|
||||
@@ -1759,6 +1759,7 @@ export type GetAllProductPathsQuery = { __typename?: 'Query' } & {
|
||||
}
|
||||
|
||||
export type GetAllProductsQueryVariables = Exact<{
|
||||
entityIds?: Maybe<Array<Scalars['Int']>>
|
||||
first?: Maybe<Scalars['Int']>
|
||||
imgSmallWidth?: Maybe<Scalars['Int']>
|
||||
imgSmallHeight?: Maybe<Scalars['Int']>
|
||||
|
@@ -3,23 +3,27 @@ import type { HookInput, HookFetcher, HookFetcherOptions } from './types'
|
||||
import { useCommerce } from '..'
|
||||
|
||||
export default function useData<T, Input = any>(
|
||||
options: HookFetcherOptions,
|
||||
options: HookFetcherOptions | (() => HookFetcherOptions | null),
|
||||
input: HookInput,
|
||||
fetcherFn: HookFetcher<T, Input>,
|
||||
swrOptions?: ConfigInterface<T>
|
||||
) {
|
||||
const { fetcherRef } = useCommerce()
|
||||
const fetcher = (url?: string, query?: string, ...args: any[]) =>
|
||||
fetcherFn(
|
||||
const fetcher = (url?: string, query?: string, ...args: any[]) => {
|
||||
return fetcherFn(
|
||||
{ url, query },
|
||||
args.reduce((obj, val, i) => {
|
||||
obj[input[i][1]!] = val
|
||||
obj[input[i][0]!] = val
|
||||
return obj
|
||||
}, {}),
|
||||
fetcherRef.current
|
||||
)
|
||||
}
|
||||
const response = useSWR(
|
||||
[options.url, options.query, ...input.map((e) => e[1])],
|
||||
() => {
|
||||
const opts = typeof options === 'function' ? options() : options
|
||||
return opts ? [opts.url, opts.query, ...input.map((e) => e[1])] : null
|
||||
},
|
||||
fetcher,
|
||||
swrOptions
|
||||
)
|
||||
|
Reference in New Issue
Block a user