diff --git a/packages/bigcommerce/src/api/endpoints/catalog/products/get-products.ts b/packages/bigcommerce/src/api/endpoints/catalog/products/get-products.ts index f88a231e1f..b1c8a2c8a7 100644 --- a/packages/bigcommerce/src/api/endpoints/catalog/products/get-products.ts +++ b/packages/bigcommerce/src/api/endpoints/catalog/products/get-products.ts @@ -12,7 +12,7 @@ const LIMIT = 12 // Return current cart info const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({ res, - body: { search, categoryId, brandId, sort }, + body: { search, categoryId, brandId, sort, page }, config, commerce, }) => { @@ -30,6 +30,8 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({ if (brandId && Number.isInteger(Number(brandId))) url.searchParams.set('brand_id', String(brandId)) + if (page) url.searchParams.set('page', String(page)) + if (sort) { const [_sort, direction] = sort.split('-') const sortValue = SORT[_sort] @@ -43,9 +45,12 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({ // We only want the id of each product url.searchParams.set('include_fields', 'id') - const { data } = await config.storeApiFetch<{ data: { id: number }[] }>( - url.pathname + url.search - ) + const { data, meta } = await config.storeApiFetch<{ + data: { id: number }[] + meta: any + }>(url.pathname + url.search) + + const pagination = meta.pagination const ids = data.map((p) => String(p.id)) const found = ids.length > 0 @@ -73,7 +78,7 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({ if (product) products.push(product) }) - res.status(200).json({ data: { products, found } }) + res.status(200).json({ data: { products, found, pagination } }) } export default getProducts diff --git a/packages/bigcommerce/src/product/use-search.tsx b/packages/bigcommerce/src/product/use-search.tsx index fd918e341e..2fc1b159ab 100644 --- a/packages/bigcommerce/src/product/use-search.tsx +++ b/packages/bigcommerce/src/product/use-search.tsx @@ -10,6 +10,7 @@ export type SearchProductsInput = { brandId?: number sort?: string locale?: string + page?: string | number } export const handler: SWRHook = { @@ -17,7 +18,11 @@ export const handler: SWRHook = { url: '/api/catalog/products', method: 'GET', }, - fetcher({ input: { search, categoryId, brandId, sort }, options, fetch }) { + fetcher({ + input: { search, categoryId, brandId, sort, page }, + options, + fetch, + }) { // Use a dummy base as we only care about the relative path const url = new URL(options.url!, 'http://a') @@ -27,6 +32,7 @@ export const handler: SWRHook = { if (Number.isInteger(brandId)) url.searchParams.set('brandId', String(brandId)) if (sort) url.searchParams.set('sort', sort) + if (page) url.searchParams.set('page', String(page)) return fetch({ url: url.pathname + url.search, @@ -42,6 +48,7 @@ export const handler: SWRHook = { ['categoryId', input.categoryId], ['brandId', input.brandId], ['sort', input.sort], + ['page', input.page], ], swrOptions: { revalidateOnFocus: false, diff --git a/packages/commerce/src/types/product.ts b/packages/commerce/src/types/product.ts index fb48ba00b4..46b84d9c9e 100644 --- a/packages/commerce/src/types/product.ts +++ b/packages/commerce/src/types/product.ts @@ -52,6 +52,7 @@ export type SearchProductsBody = { brandId?: string | number sort?: string locale?: string + page?: string | number } export type ProductTypes = { @@ -63,6 +64,7 @@ export type SearchProductsHook = { data: { products: T['product'][] found: boolean + pagination: any } body: T['searchBody'] input: T['searchBody'] diff --git a/site/components/common/Layout/Layout.tsx b/site/components/common/Layout/Layout.tsx index 6dda880e40..3171b4d6c5 100644 --- a/site/components/common/Layout/Layout.tsx +++ b/site/components/common/Layout/Layout.tsx @@ -108,7 +108,7 @@ const Layout: React.FC = ({ }) => { const { acceptedCookies, onAcceptCookies } = useAcceptCookies() const { locale = 'en-US' } = useRouter() - const navBarlinks = categories.slice(0, 2).map((c) => ({ + const navBarlinks = categories.slice(0, 4).map((c) => ({ label: c.name, href: `/search/${c.slug}`, })) diff --git a/site/components/search.tsx b/site/components/search.tsx index 664085e5b4..73b1ed868e 100644 --- a/site/components/search.tsx +++ b/site/components/search.tsx @@ -1,7 +1,7 @@ import cn from 'clsx' import type { SearchPropsType } from '@lib/search-props' import Link from 'next/link' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { useRouter } from 'next/router' import { Layout } from '@components/common' @@ -25,6 +25,7 @@ import { filterQuery, getCategoryPath, getDesignerPath, + getPaginationPath, useSearchMeta, } from '@lib/search' @@ -34,11 +35,11 @@ export default function Search({ categories, brands }: SearchPropsType) { const router = useRouter() const { asPath, locale } = router - const { q, sort } = router.query + const { q, sort, page } = router.query // `q` can be included but because categories and designers can't be searched // in the same way of products, it's better to ignore the search input if one // of those is selected - const query = filterQuery({ sort }) + const query = filterQuery({ sort, page }) const { pathname, category, brand } = useSearchMeta(asPath) const activeCategory = categories.find((cat: any) => cat.slug === category) @@ -51,9 +52,14 @@ export default function Search({ categories, brands }: SearchPropsType) { categoryId: activeCategory?.id, brandId: (activeBrand as any)?.entityId, sort: typeof sort === 'string' ? sort : '', + page: typeof page === 'string' ? page : '', locale, }) + useEffect(() => { + window.scrollTo(0, 0) + }, [page]) + const handleClick = (event: any, filter: string) => { if (filter !== activeFilter) { setToggleFilter(true) @@ -336,6 +342,41 @@ export default function Search({ categories, brands }: SearchPropsType) { ))} )}{' '} +
+ {data?.pagination.total_pages !== data?.pagination.current_page && ( + + + + )} + + {data?.pagination.current_page !== 1 && ( + + + + )} +
{/* Sort */} diff --git a/site/lib/search.tsx b/site/lib/search.tsx index eaeaf66fc8..7d82875197 100644 --- a/site/lib/search.tsx +++ b/site/lib/search.tsx @@ -50,3 +50,8 @@ export const getDesignerPath = (path: string, category?: string) => { category ? `/${category}` : '' }` } + +export const getPaginationPath = (path: string, currentPage?: number) => { + const category = getSlug(path) + return `${category ? `/${category}` : ''}?page=${currentPage}` +}