mirror of
https://github.com/vercel/commerce.git
synced 2025-07-23 04:36:49 +00:00
✨ feat: filter product
:%s
This commit is contained in:
@@ -14,7 +14,7 @@ export default function getAllProductsOperation({
|
|||||||
variables?: ProductVariables
|
variables?: ProductVariables
|
||||||
config?: Partial<VendureConfig>
|
config?: Partial<VendureConfig>
|
||||||
preview?: boolean
|
preview?: boolean
|
||||||
}): Promise<{ products: Product[] }>
|
}): Promise<{ products: Product[], totalItems: number }>
|
||||||
|
|
||||||
async function getAllProducts({
|
async function getAllProducts({
|
||||||
query = getAllProductsQuery,
|
query = getAllProductsQuery,
|
||||||
@@ -25,7 +25,7 @@ export default function getAllProductsOperation({
|
|||||||
variables?: ProductVariables
|
variables?: ProductVariables
|
||||||
config?: Partial<VendureConfig>
|
config?: Partial<VendureConfig>
|
||||||
preview?: boolean
|
preview?: boolean
|
||||||
} = {}): Promise<{ products: Product[] | any[] }> {
|
} = {}): Promise<{ products: Product[] | any[], totalItems: number }> {
|
||||||
const config = commerce.getConfig(cfg)
|
const config = commerce.getConfig(cfg)
|
||||||
const variables = {
|
const variables = {
|
||||||
input: {
|
input: {
|
||||||
@@ -40,6 +40,7 @@ export default function getAllProductsOperation({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
products: data.search.items.map((item) => normalizeSearchResult(item)),
|
products: data.search.items.map((item) => normalizeSearchResult(item)),
|
||||||
|
totalItems: data.search.totalItems as number,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
framework/vendure/schema.d.ts
vendored
3
framework/vendure/schema.d.ts
vendored
@@ -3219,7 +3219,8 @@ export type GetAllProductsQueryVariables = Exact<{
|
|||||||
|
|
||||||
export type GetAllProductsQuery = { __typename?: 'Query' } & {
|
export type GetAllProductsQuery = { __typename?: 'Query' } & {
|
||||||
search: { __typename?: 'SearchResponse' } & {
|
search: { __typename?: 'SearchResponse' } & {
|
||||||
items: Array<{ __typename?: 'SearchResult' } & SearchResultFragment>
|
items: Array<{ __typename?: 'SearchResult' } & SearchResultFragment>,
|
||||||
|
'totalItems'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ import { searchResultFragment } from '../fragments/search-result-fragment'
|
|||||||
export const getAllProductsQuery = /* GraphQL */ `
|
export const getAllProductsQuery = /* GraphQL */ `
|
||||||
query getAllProducts($input: SearchInput!) {
|
query getAllProducts($input: SearchInput!) {
|
||||||
search(input: $input) {
|
search(input: $input) {
|
||||||
|
totalItems
|
||||||
items {
|
items {
|
||||||
...SearchResult
|
...SearchResult
|
||||||
}
|
}
|
||||||
|
@@ -13,16 +13,19 @@ import ProductListBanner from '../src/components/modules/product-list/ProductLis
|
|||||||
interface Props {
|
interface Props {
|
||||||
facets: Facet[],
|
facets: Facet[],
|
||||||
collections: Collection[],
|
collections: Collection[],
|
||||||
products: ProductCard[],
|
productsResult: { products: ProductCard[], totalItems: number },
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Products({ facets, collections, products }: Props) {
|
export default function Products({ facets, collections, productsResult }: Props) {
|
||||||
// console.log("facets: ", products)
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ProductListBanner />
|
<ProductListBanner />
|
||||||
<ProductListFilter collections={collections} facets={facets} products={products} />
|
<ProductListFilter
|
||||||
|
collections={collections}
|
||||||
|
facets={facets}
|
||||||
|
products={productsResult.products}
|
||||||
|
total={productsResult.totalItems} />
|
||||||
<ViewedProducts />
|
<ViewedProducts />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
@@ -70,7 +73,7 @@ export async function getStaticProps({
|
|||||||
config,
|
config,
|
||||||
preview,
|
preview,
|
||||||
})
|
})
|
||||||
promisesWithKey.push({ key: 'products', promise: productsPromise, keyResult: 'products' })
|
promisesWithKey.push({ key: 'productsResult', promise: productsPromise })
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@@ -4,13 +4,16 @@
|
|||||||
padding: 1.6rem;
|
padding: 1.6rem;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
.imgWrap {
|
.imgWrap {
|
||||||
min-width: 10rem;
|
min-height: 10rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
img {
|
||||||
|
min-height: 10rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.description {
|
.description {
|
||||||
color: var(--disabled);
|
color: var(--disabled);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: .8rem;
|
margin-top: 0.8rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,9 +6,10 @@ interface Props {
|
|||||||
heading: string,
|
heading: string,
|
||||||
queryKey: string,
|
queryKey: string,
|
||||||
categories: { name: string, slug?: string, code?: string }[]
|
categories: { name: string, slug?: string, code?: string }[]
|
||||||
|
isSingleSelect?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const MenuNavigation = ({ heading, queryKey, categories }: Props) => {
|
const MenuNavigation = ({ heading, queryKey, categories, isSingleSelect }: Props) => {
|
||||||
return (
|
return (
|
||||||
<section className={s.menuNavigationWrapper}>
|
<section className={s.menuNavigationWrapper}>
|
||||||
<h2 className={s.menuNavigationHeading}>{heading}({categories.length})</h2>
|
<h2 className={s.menuNavigationHeading}>{heading}({categories.length})</h2>
|
||||||
@@ -19,6 +20,7 @@ const MenuNavigation = ({ heading, queryKey, categories }: Props) => {
|
|||||||
name={item.name}
|
name={item.name}
|
||||||
value={item.slug || item.code || ''}
|
value={item.slug || item.code || ''}
|
||||||
queryKey={queryKey}
|
queryKey={queryKey}
|
||||||
|
isSingleSelect={isSingleSelect}
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
@@ -1,16 +1,18 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { QUERY_SPLIT_SEPERATOR, ROUTE } from 'src/utils/constanst.utils'
|
import { QUERY_KEY, QUERY_SPLIT_SEPERATOR, ROUTE } from 'src/utils/constanst.utils'
|
||||||
import s from './MenuNavigationItem.module.scss'
|
import s from './MenuNavigationItem.module.scss'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
name: string
|
name: string
|
||||||
value: string
|
value: string
|
||||||
queryKey: string,
|
queryKey: string
|
||||||
|
isSingleSelect?: boolean
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MenuNavigationItem = ({ name, value, queryKey }: Props) => {
|
const MenuNavigationItem = ({ name, value, queryKey, isSingleSelect }: Props) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [isActive, setIsActive] = useState<boolean>()
|
const [isActive, setIsActive] = useState<boolean>()
|
||||||
|
|
||||||
@@ -26,21 +28,30 @@ const MenuNavigationItem = ({ name, value, queryKey }: Props) => {
|
|||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
const queryString = router.query[queryKey] as string || ''
|
const queryString = router.query[queryKey] as string || ''
|
||||||
const prevQuery = queryString.split(QUERY_SPLIT_SEPERATOR)
|
const prevQuery = queryString.split(QUERY_SPLIT_SEPERATOR)
|
||||||
|
|
||||||
let newQuery = [] as string[]
|
let newQuery = ''
|
||||||
if (isActive) {
|
if (isSingleSelect) {
|
||||||
newQuery = prevQuery.filter(item => item !== value)
|
newQuery = isActive ? '' : value
|
||||||
} else {
|
} else {
|
||||||
newQuery = [...prevQuery, value]
|
if (isActive) {
|
||||||
|
newQuery = prevQuery.filter(item => item !== value).join(QUERY_SPLIT_SEPERATOR)
|
||||||
|
} else {
|
||||||
|
newQuery = [...prevQuery, value].join(QUERY_SPLIT_SEPERATOR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = {
|
||||||
|
...router.query,
|
||||||
|
[queryKey]: newQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryKey === QUERY_KEY.CATEGORY) {
|
||||||
|
query[QUERY_KEY.PAGE] = "0"
|
||||||
}
|
}
|
||||||
// setIsActive(!isActive)
|
|
||||||
|
|
||||||
router.push({
|
router.push({
|
||||||
pathname: ROUTE.PRODUCTS,
|
pathname: ROUTE.PRODUCTS,
|
||||||
query: {
|
query
|
||||||
...router.query,
|
|
||||||
[queryKey]: newQuery.join(QUERY_SPLIT_SEPERATOR)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
undefined, { shallow: true }
|
undefined, { shallow: true }
|
||||||
)
|
)
|
||||||
@@ -50,8 +61,6 @@ const MenuNavigationItem = ({ name, value, queryKey }: Props) => {
|
|||||||
onClick={handleClick}>
|
onClick={handleClick}>
|
||||||
{name}
|
{name}
|
||||||
</li>)
|
</li>)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MenuNavigationItem
|
export default MenuNavigationItem
|
||||||
|
@@ -1,10 +1,19 @@
|
|||||||
.wrapper{
|
.wrapper {
|
||||||
margin-top: 4rem;
|
margin-top: 4rem;
|
||||||
.list{
|
.list {
|
||||||
@apply flex flex-wrap justify-around;
|
@apply flex flex-wrap justify-around;
|
||||||
|
.empty {
|
||||||
|
button {
|
||||||
|
margin-top: 1.6rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.pagination{
|
.pagination {
|
||||||
padding-top: 4.8rem;
|
padding-top: 4.8rem;
|
||||||
@apply flex justify-center items-center ;
|
@apply flex justify-center items-center;
|
||||||
|
&.hide {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,28 +1,50 @@
|
|||||||
import React, { useState } from 'react'
|
import classNames from 'classnames'
|
||||||
import { DEFAULT_PAGE_SIZE } from 'src/utils/constanst.utils'
|
import { useRouter } from 'next/router'
|
||||||
|
import React from 'react'
|
||||||
|
import { DEFAULT_PAGE_SIZE, ROUTE } from 'src/utils/constanst.utils'
|
||||||
|
import { ButtonCommon, EmptyCommon } from '..'
|
||||||
import PaginationCommon from '../PaginationCommon/PaginationCommon'
|
import PaginationCommon from '../PaginationCommon/PaginationCommon'
|
||||||
import ProductCard, { ProductCardProps } from '../ProductCard/ProductCard'
|
import ProductCard, { ProductCardProps } from '../ProductCard/ProductCard'
|
||||||
import s from "./ProductList.module.scss"
|
import s from "./ProductList.module.scss"
|
||||||
|
|
||||||
interface ProductListProps {
|
interface ProductListProps {
|
||||||
data: ProductCardProps[]
|
data: ProductCardProps[],
|
||||||
|
total?: number,
|
||||||
|
defaultCurrentPage?: number
|
||||||
|
onPageChange?: (page: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductList = ({data}: ProductListProps) => {
|
const ProductList = ({ data, total = data.length, defaultCurrentPage, onPageChange }: ProductListProps) => {
|
||||||
const [currentPage, setCurrentPage] = useState(0)
|
const router = useRouter()
|
||||||
const onPageChange = (page:number) => {
|
const handlePageChange = (page: number) => {
|
||||||
setCurrentPage(page)
|
onPageChange && onPageChange(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleShowAllProduct = () => {
|
||||||
|
router.push({
|
||||||
|
pathname: ROUTE.PRODUCTS,
|
||||||
|
},
|
||||||
|
undefined, { shallow: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={s.wrapper}>
|
<div className={s.wrapper}>
|
||||||
<div className={s.list}>
|
<div className={s.list}>
|
||||||
{
|
{
|
||||||
data.slice(currentPage*DEFAULT_PAGE_SIZE,(currentPage+1)* DEFAULT_PAGE_SIZE).map((product,index)=>{
|
data.map((product, index) => {
|
||||||
return <ProductCard {...product} key={index}/>
|
return <ProductCard {...product} key={index} />
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
data.length === 0 && <div className={s.empty}>
|
||||||
|
<EmptyCommon />
|
||||||
|
<ButtonCommon onClick={handleShowAllProduct}>Show all products</ButtonCommon>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className={s.pagination}>
|
<div className={classNames(s.pagination, { [s.hide]: data.length === 0 })}>
|
||||||
<PaginationCommon total={data.length} pageSize={DEFAULT_PAGE_SIZE} onChange={onPageChange}/>
|
<PaginationCommon defaultCurrent={defaultCurrentPage} total={total} pageSize={DEFAULT_PAGE_SIZE} onChange={handlePageChange} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
3
src/components/hooks/product/index.ts
Normal file
3
src/components/hooks/product/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export { default as useSearchProducts } from './useSearchProducts'
|
||||||
|
|
||||||
|
|
14
src/components/hooks/product/useSearchProducts.tsx
Normal file
14
src/components/hooks/product/useSearchProducts.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { GetAllProductsQuery, QuerySearchArgs } from '@framework/schema'
|
||||||
|
import { normalizeSearchResult } from '@framework/utils/normalize'
|
||||||
|
import { getAllProductsQuery } from '@framework/utils/queries/get-all-products-query'
|
||||||
|
import gglFetcher from 'src/utils/gglFetcher'
|
||||||
|
import useSWR from 'swr'
|
||||||
|
|
||||||
|
const useSearchProducts = (options?: QuerySearchArgs) => {
|
||||||
|
const { data, isValidating, ...rest } = useSWR<GetAllProductsQuery>([getAllProductsQuery, options], gglFetcher)
|
||||||
|
console.log("on search ", data?.search.totalItems, options, data?.search.items)
|
||||||
|
|
||||||
|
return { products: data?.search.items.map((item) => normalizeSearchResult(item)), totalItems: data?.search.totalItems, loading: isValidating, ...rest }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useSearchProducts
|
@@ -14,12 +14,12 @@
|
|||||||
@apply flex;
|
@apply flex;
|
||||||
}
|
}
|
||||||
.list{
|
.list{
|
||||||
@screen md {
|
@apply w-full;
|
||||||
@apply flex justify-between flex-wrap w-full;
|
.top {
|
||||||
margin: 1rem 0;
|
@screen md {
|
||||||
}
|
@apply flex justify-between flex-wrap w-full;
|
||||||
@screen xl {
|
margin: 1rem 0;
|
||||||
width:75%;
|
}
|
||||||
}
|
}
|
||||||
.inner{
|
.inner{
|
||||||
@screen md {
|
@screen md {
|
||||||
|
@@ -1,8 +1,13 @@
|
|||||||
import { ProductCard } from '@commerce/types/product'
|
import { ProductCard } from '@commerce/types/product'
|
||||||
import { Collection, Facet } from '@framework/schema'
|
import { Collection, Facet, FacetValue, QuerySearchArgs } from '@framework/schema'
|
||||||
import React from 'react'
|
import { useRouter } from 'next/router'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
import { HeadingCommon, ProductList } from 'src/components/common'
|
import { HeadingCommon, ProductList } from 'src/components/common'
|
||||||
import BreadcrumbCommon from 'src/components/common/BreadcrumbCommon/BreadcrumbCommon'
|
import BreadcrumbCommon from 'src/components/common/BreadcrumbCommon/BreadcrumbCommon'
|
||||||
|
import SkeletonImage from 'src/components/common/SkeletonCommon/SkeletonImage/SkeletonImage'
|
||||||
|
import { useSearchProducts } from 'src/components/hooks/product'
|
||||||
|
import { DEFAULT_PAGE_SIZE, QUERY_KEY, QUERY_SPLIT_SEPERATOR, ROUTE } from 'src/utils/constanst.utils'
|
||||||
|
import { getFacetIdsFromCodes, getPageFromQuery } from 'src/utils/funtion.utils'
|
||||||
import s from './ProductListFilter.module.scss'
|
import s from './ProductListFilter.module.scss'
|
||||||
import ProductsMenuNavigationTablet from './ProductsMenuNavigationTablet/ProductsMenuNavigationTablet'
|
import ProductsMenuNavigationTablet from './ProductsMenuNavigationTablet/ProductsMenuNavigationTablet'
|
||||||
import ProductSort from './ProductSort/ProductSort'
|
import ProductSort from './ProductSort/ProductSort'
|
||||||
@@ -11,6 +16,7 @@ interface ProductListFilterProps {
|
|||||||
facets: Facet[]
|
facets: Facet[]
|
||||||
collections: Collection[]
|
collections: Collection[]
|
||||||
products: ProductCard[]
|
products: ProductCard[]
|
||||||
|
total: number
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +27,64 @@ const BREADCRUMB = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const ProductListFilter = ({ facets, collections, products }: ProductListFilterProps) => {
|
|
||||||
|
const DEFAULT_SEARCH_ARGS = {
|
||||||
|
groupByProduct: true, take: DEFAULT_PAGE_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProductListFilter = ({ facets, collections, products, total }: ProductListFilterProps) => {
|
||||||
|
const router = useRouter()
|
||||||
|
const [initialQueryFlag, setInitialQueryFlag] = useState<boolean>(true)
|
||||||
|
const [optionQueryProduct, setOptionQueryProduct] = useState<QuerySearchArgs>({ input: DEFAULT_SEARCH_ARGS })
|
||||||
|
const { products: productSearchResult, totalItems, loading } = useSearchProducts(optionQueryProduct)
|
||||||
|
const [currentPage, setCurrentPage] = useState(0)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const page = getPageFromQuery(router.query[QUERY_KEY.PAGE] as string)
|
||||||
|
setCurrentPage(page)
|
||||||
|
}, [router.query])
|
||||||
|
|
||||||
|
const onPageChange = (page: number) => {
|
||||||
|
setCurrentPage(page)
|
||||||
|
|
||||||
|
router.push({
|
||||||
|
pathname: ROUTE.PRODUCTS,
|
||||||
|
query: {
|
||||||
|
...router.query,
|
||||||
|
[QUERY_KEY.PAGE]: page
|
||||||
|
}
|
||||||
|
},
|
||||||
|
undefined, { shallow: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const query = { input: { ...DEFAULT_SEARCH_ARGS } } as QuerySearchArgs
|
||||||
|
|
||||||
|
const page = getPageFromQuery(router.query[QUERY_KEY.PAGE] as string)
|
||||||
|
query.input.skip = page * DEFAULT_PAGE_SIZE
|
||||||
|
|
||||||
|
// collections
|
||||||
|
const categoryQuery = router.query[QUERY_KEY.CATEGORY] as string
|
||||||
|
if (categoryQuery) {
|
||||||
|
query.input.collectionSlug = categoryQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
// facets
|
||||||
|
const facetsQuery = [router.query[QUERY_KEY.FEATURED] as string, router.query[QUERY_KEY.BRAND] as string].join(QUERY_SPLIT_SEPERATOR)
|
||||||
|
if (facetsQuery) {
|
||||||
|
const facetsValue = [] as FacetValue[]
|
||||||
|
facets.map((item: Facet) => {
|
||||||
|
facetsValue.push(...item.values)
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
|
||||||
|
query.input.facetValueIds = getFacetIdsFromCodes(facetsValue, facetsQuery.split(QUERY_SPLIT_SEPERATOR))
|
||||||
|
}
|
||||||
|
|
||||||
|
setOptionQueryProduct(query)
|
||||||
|
setInitialQueryFlag(false)
|
||||||
|
}, [router.query, facets])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={s.warpper}>
|
<div className={s.warpper}>
|
||||||
@@ -31,12 +94,17 @@ const ProductListFilter = ({ facets, collections, products }: ProductListFilterP
|
|||||||
<div className={s.main}>
|
<div className={s.main}>
|
||||||
<ProductsMenuNavigationTablet facets={facets} collections={collections} />
|
<ProductsMenuNavigationTablet facets={facets} collections={collections} />
|
||||||
<div className={s.list}>
|
<div className={s.list}>
|
||||||
<HeadingCommon align="left">SPECIAL RECIPES</HeadingCommon>
|
<div className={s.top}>
|
||||||
|
<HeadingCommon align="left">SPECIAL RECIPES</HeadingCommon>
|
||||||
|
|
||||||
<div className={s.boxSelect}>
|
<div className={s.boxSelect}>
|
||||||
<ProductSort/>
|
<ProductSort />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ProductList data={products} />
|
{
|
||||||
|
(!initialQueryFlag && loading && !productSearchResult) && <SkeletonImage />
|
||||||
|
}
|
||||||
|
<ProductList data={initialQueryFlag ? products : (productSearchResult || [])} total={totalItems !== undefined ? totalItems : total} onPageChange={onPageChange} defaultCurrentPage={currentPage} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -13,7 +13,11 @@ interface Props {
|
|||||||
const ProductsMenuNavigationTablet = ({ facets, collections }: Props) => {
|
const ProductsMenuNavigationTablet = ({ facets, collections }: Props) => {
|
||||||
return (
|
return (
|
||||||
<div className={s.productsMenuNavigationTablet}>
|
<div className={s.productsMenuNavigationTablet}>
|
||||||
<MenuNavigation categories={collections} heading="Categories" queryKey={QUERY_KEY.CATEGORY} />
|
<MenuNavigation
|
||||||
|
heading="Categories"
|
||||||
|
categories={collections}
|
||||||
|
queryKey={QUERY_KEY.CATEGORY}
|
||||||
|
isSingleSelect={true} />
|
||||||
{
|
{
|
||||||
facets.map(item => <MenuNavigation
|
facets.map(item => <MenuNavigation
|
||||||
key={item.id}
|
key={item.id}
|
||||||
|
@@ -52,7 +52,8 @@ export const QUERY_KEY = {
|
|||||||
BRAND: 'brand',
|
BRAND: 'brand',
|
||||||
FEATURED: 'featured',
|
FEATURED: 'featured',
|
||||||
SORTBY: 'sortby',
|
SORTBY: 'sortby',
|
||||||
RECIPES: 'recipes'
|
RECIPES: 'recipes',
|
||||||
|
PAGE: 'page',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PRODUCT_SORT_OPTION_VALUE = {
|
export const PRODUCT_SORT_OPTION_VALUE = {
|
||||||
|
@@ -7,6 +7,19 @@ export function isMobile() {
|
|||||||
return window.innerWidth < 768
|
return window.innerWidth < 768
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPageFromQuery(pageQuery: string) {
|
||||||
|
let page = 0
|
||||||
|
try {
|
||||||
|
page = +pageQuery
|
||||||
|
if (isNaN(page)) {
|
||||||
|
page = 0
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
page = 0
|
||||||
|
}
|
||||||
|
return page
|
||||||
|
}
|
||||||
|
|
||||||
export function removeItem<T>(arr: Array<T>, value: T): Array<T> {
|
export function removeItem<T>(arr: Array<T>, value: T): Array<T> {
|
||||||
const index = arr.indexOf(value);
|
const index = arr.indexOf(value);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
@@ -58,6 +71,16 @@ export function getFacetNamesFromIds(facets: FacetValue[], ids?: string[]): stri
|
|||||||
return names.join(", ")
|
return names.join(", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAllPromies (promies: PromiseWithKey[]) {
|
export function getFacetIdsFromCodes(facets: FacetValue[], codes?: string[]): string[] {
|
||||||
|
if (!codes || codes?.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const facetItems = facets.filter((item: FacetValue) => codes.includes(item.code))
|
||||||
|
const ids = facetItems.map((item: FacetValue) => item.id)
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAllPromies(promies: PromiseWithKey[]) {
|
||||||
return promies.map(item => item.promise)
|
return promies.map(item => item.promise)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user