mirror of
https://github.com/vercel/commerce.git
synced 2025-05-17 15:06:59 +00:00
Add pagination, increment categories to 4
This commit is contained in:
parent
87134e2990
commit
a9f4a0394f
@ -12,7 +12,7 @@ const LIMIT = 12
|
|||||||
// Return current cart info
|
// Return current cart info
|
||||||
const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
|
const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
|
||||||
res,
|
res,
|
||||||
body: { search, categoryId, brandId, sort },
|
body: { search, categoryId, brandId, sort, page },
|
||||||
config,
|
config,
|
||||||
commerce,
|
commerce,
|
||||||
}) => {
|
}) => {
|
||||||
@ -30,6 +30,8 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
|
|||||||
if (brandId && Number.isInteger(Number(brandId)))
|
if (brandId && Number.isInteger(Number(brandId)))
|
||||||
url.searchParams.set('brand_id', String(brandId))
|
url.searchParams.set('brand_id', String(brandId))
|
||||||
|
|
||||||
|
if (page) url.searchParams.set('page', String(page))
|
||||||
|
|
||||||
if (sort) {
|
if (sort) {
|
||||||
const [_sort, direction] = sort.split('-')
|
const [_sort, direction] = sort.split('-')
|
||||||
const sortValue = SORT[_sort]
|
const sortValue = SORT[_sort]
|
||||||
@ -43,9 +45,12 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
|
|||||||
// We only want the id of each product
|
// We only want the id of each product
|
||||||
url.searchParams.set('include_fields', 'id')
|
url.searchParams.set('include_fields', 'id')
|
||||||
|
|
||||||
const { data } = await config.storeApiFetch<{ data: { id: number }[] }>(
|
const { data, meta } = await config.storeApiFetch<{
|
||||||
url.pathname + url.search
|
data: { id: number }[]
|
||||||
)
|
meta: any
|
||||||
|
}>(url.pathname + url.search)
|
||||||
|
|
||||||
|
const pagination = meta.pagination
|
||||||
|
|
||||||
const ids = data.map((p) => String(p.id))
|
const ids = data.map((p) => String(p.id))
|
||||||
const found = ids.length > 0
|
const found = ids.length > 0
|
||||||
@ -73,7 +78,7 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
|
|||||||
if (product) products.push(product)
|
if (product) products.push(product)
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).json({ data: { products, found } })
|
res.status(200).json({ data: { products, found, pagination } })
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getProducts
|
export default getProducts
|
||||||
|
@ -10,6 +10,7 @@ export type SearchProductsInput = {
|
|||||||
brandId?: number
|
brandId?: number
|
||||||
sort?: string
|
sort?: string
|
||||||
locale?: string
|
locale?: string
|
||||||
|
page?: string | number
|
||||||
}
|
}
|
||||||
|
|
||||||
export const handler: SWRHook<SearchProductsHook> = {
|
export const handler: SWRHook<SearchProductsHook> = {
|
||||||
@ -17,7 +18,11 @@ export const handler: SWRHook<SearchProductsHook> = {
|
|||||||
url: '/api/catalog/products',
|
url: '/api/catalog/products',
|
||||||
method: 'GET',
|
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
|
// Use a dummy base as we only care about the relative path
|
||||||
const url = new URL(options.url!, 'http://a')
|
const url = new URL(options.url!, 'http://a')
|
||||||
|
|
||||||
@ -27,6 +32,7 @@ export const handler: SWRHook<SearchProductsHook> = {
|
|||||||
if (Number.isInteger(brandId))
|
if (Number.isInteger(brandId))
|
||||||
url.searchParams.set('brandId', String(brandId))
|
url.searchParams.set('brandId', String(brandId))
|
||||||
if (sort) url.searchParams.set('sort', sort)
|
if (sort) url.searchParams.set('sort', sort)
|
||||||
|
if (page) url.searchParams.set('page', String(page))
|
||||||
|
|
||||||
return fetch({
|
return fetch({
|
||||||
url: url.pathname + url.search,
|
url: url.pathname + url.search,
|
||||||
@ -42,6 +48,7 @@ export const handler: SWRHook<SearchProductsHook> = {
|
|||||||
['categoryId', input.categoryId],
|
['categoryId', input.categoryId],
|
||||||
['brandId', input.brandId],
|
['brandId', input.brandId],
|
||||||
['sort', input.sort],
|
['sort', input.sort],
|
||||||
|
['page', input.page],
|
||||||
],
|
],
|
||||||
swrOptions: {
|
swrOptions: {
|
||||||
revalidateOnFocus: false,
|
revalidateOnFocus: false,
|
||||||
|
@ -52,6 +52,7 @@ export type SearchProductsBody = {
|
|||||||
brandId?: string | number
|
brandId?: string | number
|
||||||
sort?: string
|
sort?: string
|
||||||
locale?: string
|
locale?: string
|
||||||
|
page?: string | number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProductTypes = {
|
export type ProductTypes = {
|
||||||
@ -63,6 +64,7 @@ export type SearchProductsHook<T extends ProductTypes = ProductTypes> = {
|
|||||||
data: {
|
data: {
|
||||||
products: T['product'][]
|
products: T['product'][]
|
||||||
found: boolean
|
found: boolean
|
||||||
|
pagination: any
|
||||||
}
|
}
|
||||||
body: T['searchBody']
|
body: T['searchBody']
|
||||||
input: T['searchBody']
|
input: T['searchBody']
|
||||||
|
@ -108,7 +108,7 @@ const Layout: React.FC<Props> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { acceptedCookies, onAcceptCookies } = useAcceptCookies()
|
const { acceptedCookies, onAcceptCookies } = useAcceptCookies()
|
||||||
const { locale = 'en-US' } = useRouter()
|
const { locale = 'en-US' } = useRouter()
|
||||||
const navBarlinks = categories.slice(0, 2).map((c) => ({
|
const navBarlinks = categories.slice(0, 4).map((c) => ({
|
||||||
label: c.name,
|
label: c.name,
|
||||||
href: `/search/${c.slug}`,
|
href: `/search/${c.slug}`,
|
||||||
}))
|
}))
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import cn from 'clsx'
|
import cn from 'clsx'
|
||||||
import type { SearchPropsType } from '@lib/search-props'
|
import type { SearchPropsType } from '@lib/search-props'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
import { Layout } from '@components/common'
|
import { Layout } from '@components/common'
|
||||||
@ -31,6 +31,7 @@ import {
|
|||||||
export default function Search({ categories, brands }: SearchPropsType) {
|
export default function Search({ categories, brands }: SearchPropsType) {
|
||||||
const [activeFilter, setActiveFilter] = useState('')
|
const [activeFilter, setActiveFilter] = useState('')
|
||||||
const [toggleFilter, setToggleFilter] = useState(false)
|
const [toggleFilter, setToggleFilter] = useState(false)
|
||||||
|
const [page, SetPage] = useState(1)
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { asPath, locale } = router
|
const { asPath, locale } = router
|
||||||
@ -51,9 +52,14 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
categoryId: activeCategory?.id,
|
categoryId: activeCategory?.id,
|
||||||
brandId: (activeBrand as any)?.entityId,
|
brandId: (activeBrand as any)?.entityId,
|
||||||
sort: typeof sort === 'string' ? sort : '',
|
sort: typeof sort === 'string' ? sort : '',
|
||||||
|
page: page,
|
||||||
locale,
|
locale,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.scrollTo(0, 0)
|
||||||
|
}, [page])
|
||||||
|
|
||||||
const handleClick = (event: any, filter: string) => {
|
const handleClick = (event: any, filter: string) => {
|
||||||
if (filter !== activeFilter) {
|
if (filter !== activeFilter) {
|
||||||
setToggleFilter(true)
|
setToggleFilter(true)
|
||||||
@ -336,6 +342,28 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}{' '}
|
)}{' '}
|
||||||
|
<div className="flex justify-center mt-5">
|
||||||
|
{page !== 1 && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="mr-3 rounded-sm border border-accent-3 px-4 py-3 bg-accent-0 text-sm leading-5 font-medium text-accent-4 hover:text-accent-5 focus:outline-none focus:border-blue-300 focus:shadow-outline-normal active:bg-accent-1 active:text-accent-8 transition ease-in-out duration-150"
|
||||||
|
onClick={() => SetPage(page - 1)}
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
Previous{' '}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{data?.pagination.total_pages !== data?.pagination.current_page && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="rounded-sm border border-accent-3 px-4 py-3 bg-accent-0 text-sm leading-5 font-medium text-accent-4 hover:text-accent-5 focus:outline-none focus:border-blue-300 focus:shadow-outline-normal active:bg-accent-1 active:text-accent-8 transition ease-in-out duration-150"
|
||||||
|
onClick={() => SetPage(page + 1)}
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
Next{' '}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Sort */}
|
{/* Sort */}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user