mirror of
https://github.com/vercel/commerce.git
synced 2025-05-17 15:06:59 +00:00
Add use-search hooks
Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
parent
79b659048e
commit
2401a42b63
14
packages/opencommerce/schema.d.ts
vendored
14
packages/opencommerce/schema.d.ts
vendored
@ -7937,6 +7937,8 @@ export type AuthenticateMutation = {
|
||||
export type CatalogItemsQueryVariables = Exact<{
|
||||
first?: InputMaybe<Scalars['ConnectionLimitInt']>
|
||||
sortBy?: InputMaybe<CatalogItemSortByField>
|
||||
sortOrder?: InputMaybe<SortOrder>
|
||||
sortByPriceCurrencyCode?: InputMaybe<Scalars['String']>
|
||||
tagIds?: InputMaybe<
|
||||
Array<InputMaybe<Scalars['ID']>> | InputMaybe<Scalars['ID']>
|
||||
>
|
||||
@ -8201,6 +8203,18 @@ export type GetProductBySlugQuery = {
|
||||
} | null
|
||||
}
|
||||
|
||||
export type GetShopCurrencyQueryVariables = Exact<{
|
||||
id: Scalars['ID']
|
||||
}>
|
||||
|
||||
export type GetShopCurrencyQuery = {
|
||||
__typename?: 'Query'
|
||||
shop?: {
|
||||
__typename?: 'Shop'
|
||||
currency: { __typename?: 'Currency'; code: string }
|
||||
} | null
|
||||
}
|
||||
|
||||
export type GetTagsQueryVariables = Exact<{
|
||||
first: Scalars['ConnectionLimitInt']
|
||||
shopId: Scalars['ID']
|
||||
|
@ -0,0 +1,56 @@
|
||||
import type { ProductsEndpoint } from './products'
|
||||
import getSearchVariables from '../../utils/get-search-variables'
|
||||
import getSortVariables from '../../utils/get-sort-variables'
|
||||
import { CatalogItemsQueryVariables } from '../../../../schema'
|
||||
import getShopCurrencyQuery from '../../queries/get-shop-currency-query'
|
||||
|
||||
const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
|
||||
body: { brandId, search, sort, categoryId },
|
||||
res,
|
||||
config,
|
||||
commerce,
|
||||
}) => {
|
||||
let sortParams = getSortVariables(sort)
|
||||
if (sortParams?.sortBy === 'featured' && !categoryId) {
|
||||
sortParams = null
|
||||
}
|
||||
|
||||
let currency: string | null = null
|
||||
|
||||
if (sortParams?.sortBy === 'minPrice') {
|
||||
const {
|
||||
data: {
|
||||
shop: {
|
||||
currency: { code },
|
||||
},
|
||||
},
|
||||
} = await config.fetch(getShopCurrencyQuery, {
|
||||
variables: { id: config.shopId },
|
||||
})
|
||||
currency = code
|
||||
}
|
||||
|
||||
const { products } = await commerce.getAllProducts({
|
||||
variables: {
|
||||
...getSearchVariables({ brandId, search, categoryId }),
|
||||
...(sortParams
|
||||
? {
|
||||
sortBy: sortParams.sortBy as CatalogItemsQueryVariables['sortBy'],
|
||||
sortOrder:
|
||||
sortParams.sortOrder as CatalogItemsQueryVariables['sortOrder'],
|
||||
}
|
||||
: {}),
|
||||
...(currency ? { sortByPriceCurrencyCode: currency } : {}),
|
||||
},
|
||||
config,
|
||||
})
|
||||
|
||||
res.status(200).json({
|
||||
data: {
|
||||
products,
|
||||
found: !!products.length,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export default getProducts
|
@ -1 +0,0 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
@ -1 +1,20 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
||||
import { CommerceAPI, createEndpoint, GetAPISchema } from '@vercel/commerce/api'
|
||||
import productsEndpoint from '@vercel/commerce/api/endpoints/catalog/products'
|
||||
import type { ProductsSchema } from '../../../types/product'
|
||||
import type { OpenCommerceAPI } from '../../index'
|
||||
import getProducts from './get-products'
|
||||
|
||||
export type ProductsAPI = GetAPISchema<OpenCommerceAPI, ProductsSchema>
|
||||
|
||||
export type ProductsEndpoint = ProductsAPI['endpoint']
|
||||
|
||||
export const handlers: ProductsEndpoint['handlers'] = {
|
||||
getProducts,
|
||||
}
|
||||
|
||||
const productsApi = createEndpoint<ProductsAPI>({
|
||||
handler: productsEndpoint,
|
||||
handlers,
|
||||
})
|
||||
|
||||
export default productsApi
|
||||
|
@ -15,7 +15,7 @@ export default function getAllProductsOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getAllProducts<T extends GetAllProductsOperation>(opts?: {
|
||||
variables?: T['variables']
|
||||
variables?: Omit<CatalogItemsQueryVariables, 'shopIds'>
|
||||
config?: Partial<OpenCommerceConfig>
|
||||
preview?: boolean
|
||||
}): Promise<T['data']>
|
||||
@ -26,7 +26,7 @@ export default function getAllProductsOperation({
|
||||
config,
|
||||
}: {
|
||||
query?: string
|
||||
variables?: T['variables']
|
||||
variables?: Omit<CatalogItemsQueryVariables, 'shopIds'>
|
||||
config?: Partial<OpenCommerceConfig>
|
||||
preview?: boolean
|
||||
} = {}): Promise<T['data']> {
|
||||
|
@ -2,6 +2,8 @@ const catalogItemsQuery = /* GraphQL */ `
|
||||
query catalogItems(
|
||||
$first: ConnectionLimitInt = 250
|
||||
$sortBy: CatalogItemSortByField = updatedAt
|
||||
$sortOrder: SortOrder = desc
|
||||
$sortByPriceCurrencyCode: String
|
||||
$tagIds: [ID]
|
||||
$shopIds: [ID]!
|
||||
$searchQuery: String
|
||||
@ -9,9 +11,11 @@ const catalogItemsQuery = /* GraphQL */ `
|
||||
catalogItems(
|
||||
first: $first
|
||||
sortBy: $sortBy
|
||||
sortOrder: $sortOrder
|
||||
tagIds: $tagIds
|
||||
shopIds: $shopIds
|
||||
searchQuery: $searchQuery
|
||||
sortByPriceCurrencyCode: $sortByPriceCurrencyCode
|
||||
) {
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
|
@ -0,0 +1,11 @@
|
||||
const getShopCurrencyQuery = /* GraphQL */ `
|
||||
query getShopCurrency($id: ID!) {
|
||||
shop(id: $id) {
|
||||
currency {
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default getShopCurrencyQuery
|
36
packages/opencommerce/src/api/utils/get-search-variables.ts
Normal file
36
packages/opencommerce/src/api/utils/get-search-variables.ts
Normal file
@ -0,0 +1,36 @@
|
||||
export type SearchProductsInput = {
|
||||
search?: string
|
||||
categoryId?: number | string
|
||||
brandId?: number | string
|
||||
locale?: string
|
||||
}
|
||||
|
||||
const getSearchVariables = ({
|
||||
brandId,
|
||||
search,
|
||||
categoryId,
|
||||
}: SearchProductsInput) => {
|
||||
let searchQuery = ''
|
||||
let tagIdsParam = {}
|
||||
|
||||
if (search) {
|
||||
searchQuery += search
|
||||
}
|
||||
|
||||
if (brandId) {
|
||||
searchQuery += `${search ? ' ' : ''}${brandId}`
|
||||
}
|
||||
|
||||
if (categoryId) {
|
||||
tagIdsParam = {
|
||||
tagIds: [categoryId],
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
searchQuery,
|
||||
...tagIdsParam,
|
||||
}
|
||||
}
|
||||
|
||||
export default getSearchVariables
|
25
packages/opencommerce/src/api/utils/get-sort-variables.ts
Normal file
25
packages/opencommerce/src/api/utils/get-sort-variables.ts
Normal file
@ -0,0 +1,25 @@
|
||||
type SortByField = 'minPrice' | 'featured' | 'createdAt'
|
||||
|
||||
const getSortVariables = (sort?: string) => {
|
||||
if (!sort) return null
|
||||
const [_sort, direction] = sort.split('-')
|
||||
|
||||
const SORT: { [key: string]: SortByField | undefined } = {
|
||||
price: 'minPrice',
|
||||
trending: 'featured',
|
||||
latest: 'createdAt',
|
||||
}
|
||||
|
||||
const sortValue = SORT[_sort]
|
||||
|
||||
if (sortValue && direction) {
|
||||
return {
|
||||
sortBy: sortValue,
|
||||
sortOrder: direction,
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export default getSortVariables
|
@ -1,17 +1,45 @@
|
||||
import { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import useSearch, { UseSearch } from '@vercel/commerce/product/use-search'
|
||||
import type { SearchProductsHook } from '../types/product'
|
||||
|
||||
export default useSearch as UseSearch<typeof handler>
|
||||
|
||||
export const handler: SWRHook<any> = {
|
||||
export const handler: SWRHook<SearchProductsHook> = {
|
||||
fetchOptions: {
|
||||
query: '',
|
||||
url: '/api/catalog/products',
|
||||
method: 'GET',
|
||||
},
|
||||
async fetcher({ input, options, fetch }) {},
|
||||
useHook: () => () => {
|
||||
return {
|
||||
data: {
|
||||
products: [],
|
||||
},
|
||||
}
|
||||
async fetcher({
|
||||
input: { search, categoryId, brandId, sort },
|
||||
options,
|
||||
fetch,
|
||||
}) {
|
||||
// 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', search)
|
||||
if (categoryId) url.searchParams.set('categoryId', String(categoryId))
|
||||
if (brandId) url.searchParams.set('brandId', String(brandId))
|
||||
if (sort) url.searchParams.set('sort', 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,
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
||||
locale,
|
||||
})
|
||||
|
||||
console.log({ data })
|
||||
const handleClick = (event: any, filter: string) => {
|
||||
if (filter !== activeFilter) {
|
||||
setToggleFilter(true)
|
||||
|
Loading…
x
Reference in New Issue
Block a user