diff --git a/packages/sfcc/src/api/endpoints/catalog/index.ts b/packages/sfcc/src/api/endpoints/catalog/index.ts deleted file mode 100644 index 491bf0ac9..000000000 --- a/packages/sfcc/src/api/endpoints/catalog/index.ts +++ /dev/null @@ -1 +0,0 @@ -export default function noopApi(...args: any[]): void {} diff --git a/packages/sfcc/src/api/endpoints/catalog/products.ts b/packages/sfcc/src/api/endpoints/catalog/products.ts deleted file mode 100644 index 491bf0ac9..000000000 --- a/packages/sfcc/src/api/endpoints/catalog/products.ts +++ /dev/null @@ -1 +0,0 @@ -export default function noopApi(...args: any[]): void {} diff --git a/packages/sfcc/src/api/endpoints/catalog/products/get-products.ts b/packages/sfcc/src/api/endpoints/catalog/products/get-products.ts new file mode 100644 index 000000000..49d1234cf --- /dev/null +++ b/packages/sfcc/src/api/endpoints/catalog/products/get-products.ts @@ -0,0 +1,41 @@ +import { normalizeSearchProducts } from '../../../utils/normalise-product'; +import { ProductsEndpoint } from '.' + + +const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({ + req, + res, + body: { search, categoryId, brandId, sort }, + config +}) => { + const { sdk } = config; + + let searchTerm = search; + + if (categoryId) { + searchTerm = categoryId as string + } + + const searchClient = await sdk.getSearchClient(); + // use SDK search API for initial products + const searchResults = await searchClient.productSearch({ + parameters: { + q: searchTerm, + limit: 20 + } + }); + let products = []; + let found = false; + if (searchResults.total) { + found = true; + products = normalizeSearchProducts(searchResults.hits) as any[]; + } else { + // TODO: handle this better? + console.log("No results for search"); + } + + + res.status(200).json({ data: { products, found } }) +} + +export default getProducts diff --git a/packages/sfcc/src/api/endpoints/catalog/products/index.ts b/packages/sfcc/src/api/endpoints/catalog/products/index.ts new file mode 100644 index 000000000..196eb04cb --- /dev/null +++ b/packages/sfcc/src/api/endpoints/catalog/products/index.ts @@ -0,0 +1,19 @@ +import type { SFCCProviderAPI } from '../../..' + +import { createEndpoint, GetAPISchema } from '@vercel/commerce/api' +import { ProductsSchema } from '@vercel/commerce/types/product' +import getProducts from './get-products' +import productsEndpoint from '@vercel/commerce/api/endpoints/catalog/products' + +export type ProductsAPI = GetAPISchema + +export type ProductsEndpoint = ProductsAPI['endpoint'] + +export const handlers: ProductsEndpoint['handlers'] = { getProducts } + +const productsApi = createEndpoint({ + handler: productsEndpoint, + handlers, +}) + +export default productsApi diff --git a/packages/sfcc/src/commerce.config.json b/packages/sfcc/src/commerce.config.json index ede472552..1d2064520 100644 --- a/packages/sfcc/src/commerce.config.json +++ b/packages/sfcc/src/commerce.config.json @@ -3,7 +3,7 @@ "features": { "wishlist": false, "cart": false, - "search": false, + "search": true, "customerAuth": false, "customCheckout": false } diff --git a/packages/sfcc/src/fetcher.ts b/packages/sfcc/src/fetcher.ts index 27f3ceb0c..1da35718e 100644 --- a/packages/sfcc/src/fetcher.ts +++ b/packages/sfcc/src/fetcher.ts @@ -1,11 +1,17 @@ import { Fetcher } from '@vercel/commerce/utils/types' -export const fetcher: Fetcher = async () => { - console.log('FETCHER') - const res = await fetch('./data.json') - if (res.ok) { - const { data } = await res.json() - return data - } - throw res +const clientFetcher: Fetcher = async ({ method, url, body }) => { + const response = await fetch(url!, { + method, + body: body ? JSON.stringify(body) : undefined, + headers: { + 'Content-Type': 'application/json', + }, + }) + .then((response) => response.json()) + .then((response) => response.data) + + return response } + +export default clientFetcher diff --git a/packages/sfcc/src/product/use-search.tsx b/packages/sfcc/src/product/use-search.tsx index b84889cca..bb5e97160 100644 --- a/packages/sfcc/src/product/use-search.tsx +++ b/packages/sfcc/src/product/use-search.tsx @@ -1,17 +1,42 @@ import { SWRHook } from '@vercel/commerce/utils/types' import useSearch, { UseSearch } from '@vercel/commerce/product/use-search' +import { SearchProductsHook } from '@vercel/commerce/types/product' export default useSearch as UseSearch -export const handler: SWRHook = { +export const handler: SWRHook = { fetchOptions: { - query: '', + url: '/api/catalog/products', + method: 'GET', }, - async fetcher({ input, options, fetch }) {}, - useHook: () => () => { - return { - data: { - products: [], - }, - } + fetcher({ input: { search, categoryId, brandId, sort }, options, fetch }) { + console.log('search', search, categoryId, options) + // Use a dummy base as we only care about the relative path + const url = new URL(options.url!, 'http://a') + + if (search) url.searchParams.set('search', String(search)) + if (categoryId) url.searchParams.set('categoryId', String(categoryId)) + if (brandId) url.searchParams.set('brandId', String(brandId)) + if (sort) url.searchParams.set('sort', String(sort)) + + return fetch({ + url: url.pathname + url.search, + method: options.method, + }) }, + useHook: + ({ useData }) => + (input = {}) => { + return useData({ + input: [ + ['search', input.search], + ['categoryId', input.categoryId], + ['brandId', input.brandId], + ['sort', input.sort], + ], + swrOptions: { + revalidateOnFocus: false, + ...input.swrOptions, + }, + }) + }, } diff --git a/packages/sfcc/src/provider.ts b/packages/sfcc/src/provider.ts index 77692c216..47063f82f 100644 --- a/packages/sfcc/src/provider.ts +++ b/packages/sfcc/src/provider.ts @@ -1,4 +1,4 @@ -import { fetcher } from './fetcher' +import fetcher from './fetcher' import { handler as useCart } from './cart/use-cart' import { handler as useAddItem } from './cart/use-add-item' import { handler as useUpdateItem } from './cart/use-update-item'