From 49f95fd43b9a6230c587ac23592969b3875e3685 Mon Sep 17 00:00:00 2001 From: Tiago Gimenes Date: Mon, 20 Jun 2022 13:23:52 -0300 Subject: [PATCH] feat: `PriceRange` filter on PLP (#121) --- @generated/graphql/index.ts | 161 ++-- @generated/graphql/persisted.json | 2 +- CHANGELOG.md | 2 + codegen.yml | 1 + cypress/integration/plp.test.js | 4 +- package.json | 16 +- src/components/search/Filter/Facets.tsx | 99 ++- src/components/search/Filter/Filter.tsx | 70 +- src/components/search/Filter/useFilter.ts | 85 +- src/components/search/Sort/Sort.tsx | 17 +- .../ui/PriceRange/PriceRange.stories.mdx | 104 +++ src/components/ui/PriceRange/PriceRange.tsx | 23 + src/components/ui/PriceRange/index.ts | 1 + .../ui/PriceRange/price-range.module.scss | 92 +++ src/pages/[...slug].tsx | 25 +- src/sdk/graphql/prefetchQuery.ts | 14 +- src/sdk/product/useFormattedPrice.ts | 16 +- src/sdk/product/useProductsQuery.ts | 6 +- yarn.lock | 749 ++++-------------- 19 files changed, 706 insertions(+), 781 deletions(-) create mode 100644 src/components/ui/PriceRange/PriceRange.stories.mdx create mode 100644 src/components/ui/PriceRange/PriceRange.tsx create mode 100644 src/components/ui/PriceRange/index.ts create mode 100644 src/components/ui/PriceRange/price-range.module.scss diff --git a/@generated/graphql/index.ts b/@generated/graphql/index.ts index a9dc081f..9535a0e8 100644 --- a/@generated/graphql/index.ts +++ b/@generated/graphql/index.ts @@ -27,9 +27,9 @@ export type IStoreCart = { } export type IStoreCurrency = { - /** Currency code, e.g: USD */ + /** Currency code (e.g: USD). */ code: Scalars['String'] - /** Currency symbol, e.g: $ */ + /** Currency symbol (e.g: $). */ symbol: Scalars['String'] } @@ -55,7 +55,7 @@ export type IStoreOffer = { seller: IStoreOrganization } -/** Offer input. */ +/** Order input. */ export type IStoreOrder = { /** Array with information on each accepted offer. */ acceptedOffer: Array @@ -104,9 +104,11 @@ export type IStorePropertyValue = { valueReference: Scalars['String'] } -/** Selected facet input. */ +/** Selected search facet input. */ export type IStoreSelectedFacet = { + /** Selected search facet key. */ key: Scalars['String'] + /** Selected search facet value. */ value: Scalars['String'] } @@ -127,9 +129,9 @@ export type IStoreSession = { } export type Mutation = { - /** Returns the order if anything has changed in it, or `null` if the order is valid. */ + /** Checks for changes between the cart presented in the UI and the cart stored in the ecommerce platform. If changes are detected, it returns the cart stored on the platform. Otherwise, it returns `null`. */ validateCart: Maybe - /** Validate session information. */ + /** Updates a web session with the specified values. */ validateSession: Maybe } @@ -143,15 +145,15 @@ export type MutationValidateSessionArgs = { } export type Query = { - /** All collections query. */ + /** Returns information about all collections. */ allCollections: StoreCollectionConnection - /** All products query. */ + /** Returns information about all products. */ allProducts: StoreProductConnection - /** Collection query. */ + /** Returns the details of a collection based on the collection slug. */ collection: StoreCollection - /** Product query. */ + /** Returns the details of a product based on the specified locator. */ product: StoreProduct - /** Search query. */ + /** Returns the result of a product, facet, or suggestion search. */ search: StoreSearchResult } @@ -233,7 +235,7 @@ export type StoreCart = { /** Shopping cart message. */ export type StoreCartMessage = { - /** Shopping cart message status, which can be `INFO`, `WARNING` OR `ERROR`. */ + /** Shopping cart message status, which can be `INFO`, `WARNING` or `ERROR`. */ status: StoreStatus /** Shopping cart message text. */ text: Scalars['String'] @@ -255,19 +257,19 @@ export type StoreCollection = { type: StoreCollectionType } -/** Collection connection pagination information. */ +/** Collection connections, including pagination information and collections returned by the query. */ export type StoreCollectionConnection = { - /** Array with collection connection page edges. */ + /** Array with collection connection page edges, each containing a collection and a corresponding cursor.. */ edges: Array - /** Collection connection page information. */ + /** Collection pagination information. */ pageInfo: StorePageInfo } -/** Collection pagination edge. */ +/** Each collection edge contains a `node`, with product collection information, and a `cursor`, that can be used as a reference for pagination. */ export type StoreCollectionEdge = { - /** Collection pagination cursor. */ + /** Collection cursor. Used as pagination reference. */ cursor: Scalars['String'] - /** Collection pagination node. */ + /** Each collection node contains the information of a product collection returned by the query. */ node: StoreCollection } @@ -287,36 +289,55 @@ export type StoreCollectionMeta = { /** Product collection type. Possible values are `Department`, `Category`, `Brand` or `Cluster`. */ export type StoreCollectionType = + /** Product brand. */ | 'Brand' + /** Second level of product categorization. */ | 'Category' + /** Product cluster. */ | 'Cluster' + /** First level of product categorization. */ | 'Department' /** Currency information. */ export type StoreCurrency = { - /** Currency code, e.g: USD */ + /** Currency code (e.g: USD). */ code: Scalars['String'] - /** Currency symbol, e.g: $ */ + /** Currency symbol (e.g: $). */ symbol: Scalars['String'] } -/** Search facet information. */ -export type StoreFacet = { +export type StoreFacet = StoreFacetBoolean | StoreFacetRange + +/** Search facet boolean information. */ +export type StoreFacetBoolean = { + /** Facet key. */ + key: Scalars['String'] + /** Facet label. */ + label: Scalars['String'] + /** Array with information on each facet value. */ + values: Array +} + +/** Search facet range information. */ +export type StoreFacetRange = { /** Facet key. */ key: Scalars['String'] /** Facet label. */ label: Scalars['String'] - /** Facet type. Possible values are `BOOLEAN` and `RANGE`. */ - type: StoreFacetType + max: StoreFacetValueRange /** Array with information on each facet value. */ - values: Array + min: StoreFacetValueRange } /** Search facet type. */ -export type StoreFacetType = 'BOOLEAN' | 'RANGE' +export type StoreFacetType = + /** Indicates boolean search facet. */ + | 'BOOLEAN' + /** Indicates range type search facet. */ + | 'RANGE' /** Information of a specific facet value. */ -export type StoreFacetValue = { +export type StoreFacetValueBoolean = { /** Facet value label. */ label: Scalars['String'] /** Number of items with this facet. */ @@ -327,6 +348,11 @@ export type StoreFacetValue = { value: Scalars['String'] } +export type StoreFacetValueRange = { + absolute: Scalars['Float'] + selected: Scalars['Float'] +} + /** Image. */ export type StoreImage = { /** Alias for the image. */ @@ -383,15 +409,15 @@ export type StoreOrganization = { identifier: Scalars['String'] } -/** Page information. */ +/** Whenever you make a query that allows for pagination, such as `allProducts` or `allCollections`, you can check `StorePageInfo` to learn more about the complete set of items and use it to paginate your queries. */ export type StorePageInfo = { - /** Page cursor end. */ + /** Cursor corresponding to the last possible item. */ endCursor: Scalars['String'] - /** Indicates whether next page exists. */ + /** Indicates whether there is at least one more page with items after the ones returned in the current query. */ hasNextPage: Scalars['Boolean'] - /** Indicates whether previous page exists. */ + /** Indicates whether there is at least one more page with items before the ones returned in the current query. */ hasPreviousPage: Scalars['Boolean'] - /** Page cursor start. */ + /** Cursor corresponding to the first possible item. */ startCursor: Scalars['String'] /** Total number of items (products or collections), not pages. */ totalCount: Scalars['Int'] @@ -443,19 +469,19 @@ export type StoreProduct = { slug: Scalars['String'] } -/** Product connection pagination information. */ +/** Product connections, including pagination information and products returned by the query. */ export type StoreProductConnection = { - /** Array with product connection page edges. */ + /** Array with product connection edges, each containing a product and a corresponding cursor. */ edges: Array - /** Product connection page information. */ + /** Product pagination information. */ pageInfo: StorePageInfo } -/** Product pagination edge. */ +/** Each product edge contains a `node`, with product information, and a `cursor`, that can be used as a reference for pagination. */ export type StoreProductEdge = { - /** Product pagination cursor. */ + /** Product cursor. Used as pagination reference. */ cursor: Scalars['String'] - /** Product pagination node. */ + /** Each product node contains the information of a product returned by the query. */ node: StoreProduct } @@ -537,18 +563,26 @@ export type StoreSession = { postalCode: Maybe } -/** Product sorting options used in search. */ +/** Product search results sorting options. */ export type StoreSort = + /** Sort by discount value, from highest to lowest. */ | 'discount_desc' + /** Sort by name, in alphabetical order. */ | 'name_asc' + /** Sort by name, in reverse alphabetical order. */ | 'name_desc' + /** Sort by orders, from highest to lowest. */ | 'orders_desc' + /** Sort by price, from lowest to highest. */ | 'price_asc' + /** Sort by price, from highest to lowest. */ | 'price_desc' + /** Sort by release date, from highest to lowest. */ | 'release_desc' + /** Sort by product score, from highest to lowest. */ | 'score_desc' -/** Status used to indicate type of message. For instance, in shopping cart messages. */ +/** Status used to indicate a message type. For instance, a shopping cart informative or error message. */ export type StoreStatus = 'ERROR' | 'INFO' | 'WARNING' /** Suggestion term. */ @@ -588,10 +622,10 @@ export type ProductSummary_ProductFragment = { } } -export type Filter_FacetsFragment = { +export type Filter_Facets_StoreFacetBoolean_Fragment = { + __typename: 'StoreFacetBoolean' key: string label: string - type: StoreFacetType values: Array<{ label: string value: string @@ -600,6 +634,18 @@ export type Filter_FacetsFragment = { }> } +export type Filter_Facets_StoreFacetRange_Fragment = { + __typename: 'StoreFacetRange' + key: string + label: string + min: { selected: number; absolute: number } + max: { selected: number; absolute: number } +} + +export type Filter_FacetsFragment = + | Filter_Facets_StoreFacetBoolean_Fragment + | Filter_Facets_StoreFacetRange_Fragment + export type ProductDetailsFragment_ProductFragment = { sku: string name: string @@ -640,17 +686,26 @@ export type ProductGalleryQueryQueryVariables = Exact<{ export type ProductGalleryQueryQuery = { search: { products: { pageInfo: { totalCount: number } } - facets: Array<{ - key: string - label: string - type: StoreFacetType - values: Array<{ - label: string - value: string - selected: boolean - quantity: number - }> - }> + facets: Array< + | { + __typename: 'StoreFacetBoolean' + key: string + label: string + values: Array<{ + label: string + value: string + selected: boolean + quantity: number + }> + } + | { + __typename: 'StoreFacetRange' + key: string + label: string + min: { selected: number; absolute: number } + max: { selected: number; absolute: number } + } + > } } diff --git a/@generated/graphql/persisted.json b/@generated/graphql/persisted.json index 6e34d342..4aadfea2 100644 --- a/@generated/graphql/persisted.json +++ b/@generated/graphql/persisted.json @@ -1,5 +1,5 @@ { - "ProductGalleryQuery": "query ProductGalleryQuery($first: Int!, $after: String!, $sort: StoreSort!, $term: String!, $selectedFacets: [IStoreSelectedFacet!]!) {\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n }\n facets {\n key\n label\n type\n values {\n label\n value\n selected\n quantity\n }\n }\n }\n}\n", + "ProductGalleryQuery": "query ProductGalleryQuery($first: Int!, $after: String!, $sort: StoreSort!, $term: String!, $selectedFacets: [IStoreSelectedFacet!]!) {\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n }\n facets {\n ... on StoreFacetRange {\n key\n label\n min {\n selected\n absolute\n }\n max {\n selected\n absolute\n }\n __typename\n }\n ... on StoreFacetBoolean {\n key\n label\n values {\n label\n value\n selected\n quantity\n }\n __typename\n }\n }\n }\n}\n", "ServerCollectionPageQuery": "query ServerCollectionPageQuery($slug: String!) {\n collection(slug: $slug) {\n seo {\n title\n description\n }\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n meta {\n selectedFacets {\n key\n value\n }\n }\n }\n}\n", "ServerProductPageQuery": "query ServerProductPageQuery($slug: String!) {\n product(locator: [{key: \"slug\", value: $slug}]) {\n id: productID\n seo {\n title\n description\n canonical\n }\n brand {\n name\n }\n sku\n gtin\n name\n description\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n image {\n url\n alternateName\n }\n offers {\n lowPrice\n highPrice\n priceCurrency\n offers {\n availability\n price\n priceValidUntil\n priceCurrency\n itemCondition\n seller {\n identifier\n }\n listPrice\n }\n }\n isVariantOf {\n productGroupID\n name\n }\n additionalProperty {\n propertyID\n name\n value\n valueReference\n }\n }\n}\n", "ValidateCartMutation": "mutation ValidateCartMutation($cart: IStoreCart!) {\n validateCart(cart: $cart) {\n order {\n orderNumber\n acceptedOffer {\n seller {\n identifier\n }\n quantity\n price\n listPrice\n itemOffered {\n sku\n name\n image {\n url\n alternateName\n }\n brand {\n name\n }\n isVariantOf {\n productGroupID\n name\n }\n gtin\n additionalProperty {\n propertyID\n name\n value\n valueReference\n }\n }\n }\n }\n messages {\n text\n status\n }\n }\n}\n", diff --git a/CHANGELOG.md b/CHANGELOG.md index 34085ed0..49259e9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- PriceRange component ([#124](https://github.com/vtex-sites/nextjs.store/pull/124)) +- PriceRange component to PLP and StoryBook ([#121](https://github.com/vtex-sites/nextjs.store/pull/121)) - Displays the `Sandbox` tab on the storybook along with `Viewport` toolbar and `Accessibility` checks ([#129](https://github.com/vtex-sites/nextjs.store/pull/129)) - The search input now includes the last 4 previously searched terms (`SearchHistory`) ([#112](https://github.com/vtex-sites/nextjs.store/pull/112)). - The top 5 searches (`SuggestionsTopSearch`) are now integrated into the search input ([#112](https://github.com/vtex-sites/nextjs.store/pull/112)). diff --git a/codegen.yml b/codegen.yml index 9485046a..3e55eaf7 100644 --- a/codegen.yml +++ b/codegen.yml @@ -13,6 +13,7 @@ generates: skipTypename: true allowEnumStringTypes: false namingConvention: 'change-case-all#pascalCase' + exportFragmentSpreadSubTypes: true plugins: - typescript - typescript-operations diff --git a/cypress/integration/plp.test.js b/cypress/integration/plp.test.js index f17f8043..8f88c951 100644 --- a/cypress/integration/plp.test.js +++ b/cypress/integration/plp.test.js @@ -22,7 +22,9 @@ describe('Search page Filters and Sorting options', () => { // Apply filters cy.getById('open-filter-button') .click() - .getById('mobile-store-filter-accordion-button') + .get( + `[data-testid=mobile-store-filter-accordion-item][data-type=StoreFacetBoolean]>[data-testid=mobile-store-filter-accordion-button]` + ) .first() .click() .getById('mobile-store-filter-accordion-panel-checkbox') diff --git a/package.json b/package.json index c8ce5369..f43a85ed 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,10 @@ "@envelop/graphql-jit": "^1.1.1", "@envelop/parser-cache": "^2.2.0", "@envelop/validation-cache": "^2.2.0", - "@faststore/api": "^1.9.7", - "@faststore/graphql-utils": "^1.9.4", - "@faststore/sdk": "1.9.10", - "@faststore/ui": "1.9.10", + "@faststore/api": "^1.9.11", + "@faststore/graphql-utils": "^1.9.9", + "@faststore/sdk": "^1.9.11", + "@faststore/ui": "^1.9.11", "graphql": "^15.0.0", "include-media": "^1.4.10", "next": "^12.1.6", @@ -47,10 +47,10 @@ }, "devDependencies": { "@cypress/code-coverage": "^3.9.10", - "@faststore/lighthouse": "^1.9.4", - "@graphql-codegen/cli": "^2.2.1", - "@graphql-codegen/typescript": "^2.2.4", - "@graphql-codegen/typescript-operations": "^2.1.8", + "@faststore/lighthouse": "^1.9.10", + "@graphql-codegen/cli": "^2.6.2", + "@graphql-codegen/typescript": "^2.5.1", + "@graphql-codegen/typescript-operations": "^2.4.2", "@lhci/cli": "^0.9.0", "@storybook/addon-a11y": "^6.5.9", "@storybook/addon-actions": "^6.5.9", diff --git a/src/components/search/Filter/Facets.tsx b/src/components/search/Filter/Facets.tsx index ac7bad9f..e5bf6b5d 100644 --- a/src/components/search/Filter/Facets.tsx +++ b/src/components/search/Filter/Facets.tsx @@ -7,15 +7,24 @@ import type { IStoreSelectedFacet, Filter_FacetsFragment, } from '@generated/graphql' +import PriceRange from 'src/components/ui/PriceRange' + +type OnFacetChange = ( + item: IStoreSelectedFacet, + type: 'BOOLEAN' | 'RANGE' +) => void interface FacetsProps { testId: string facets: Filter_FacetsFragment[] indicesExpanded: Set - onFacetChange: (item: IStoreSelectedFacet) => void + onFacetChange: OnFacetChange onAccordionChange: (index: number) => void } +const formatRange = (min: number, max: number) => + `${min.toFixed(2)}-to-${max.toFixed(2)}` + function Facets({ testId, facets, @@ -27,37 +36,65 @@ function Facets({

Filters

- {facets.map(({ label, values, key }, index) => ( - - - {values.map((item) => { - const id = `${testId}-${label}-${item.label}` + {facets.map((facet, index) => { + const isExpanded = indicesExpanded.has(index) + const { __typename: type, label } = facet + + return ( + + {type === 'StoreFacetBoolean' && isExpanded && ( + + {facet.values.map((item) => { + const id = `${testId}-${facet.label}-${item.label}` - return ( -
  • - onFacetChange({ key, value: item.value })} - data-testid={`${testId}-accordion-panel-checkbox`} - data-value={item.value} - data-quantity={item.quantity} - /> - - {item.label} {item.quantity} - -
  • - ) - })} -
    -
    - ))} + return ( +
  • + + onFacetChange( + { key: facet.key, value: item.value }, + 'BOOLEAN' + ) + } + data-testid={`${testId}-accordion-panel-checkbox`} + data-value={item.value} + data-quantity={item.quantity} + /> + + {item.label} {item.quantity} + +
  • + ) + })} +
    + )} + {type === 'StoreFacetRange' && isExpanded && ( + + onFacetChange( + { + key: facet.key, + value: formatRange(v.min, v.max), + }, + 'RANGE' + ) + } + /> + )} +
    + ) + })}
    ) diff --git a/src/components/search/Filter/Filter.tsx b/src/components/search/Filter/Filter.tsx index c1a750ba..894f83c8 100644 --- a/src/components/search/Filter/Filter.tsx +++ b/src/components/search/Filter/Filter.tsx @@ -1,4 +1,4 @@ -import { useSearch } from '@faststore/sdk' +import { setFacet, toggleFacet, useSearch } from '@faststore/sdk' import { gql } from '@faststore/graphql-utils' import Button, { ButtonIcon } from 'src/components/ui/Button' @@ -30,10 +30,7 @@ function FilterSlider({ const { closeFilter } = useUI() const { fade, fadeOut } = useFadeEffect() - const { - setFacets, - state: { selectedFacets }, - } = useSearch() + const { resetInfiniteScroll, setState, state } = useSearch() return ( { dispatch({ type: 'selectFacets', - payload: selectedFacets, + payload: state.selectedFacets, }) fadeOut() @@ -66,8 +63,10 @@ function FilterSlider({ facets={facets} testId={`mobile-${testId}`} indicesExpanded={expanded} - onFacetChange={(facet) => - dispatch({ type: 'toggleFacet', payload: facet }) + onFacetChange={(facet, type) => + type === 'BOOLEAN' + ? dispatch({ type: 'toggleFacet', payload: facet }) + : dispatch({ type: 'setFacet', payload: { facet, unique: true } }) } onAccordionChange={(index) => dispatch({ type: 'toggleExpanded', payload: index }) @@ -85,7 +84,13 @@ function FilterSlider({ variant="primary" data-testid="filter-modal-button-apply" onClick={() => { - setFacets(selected) + resetInfiniteScroll(0) + + setState({ + ...state, + selectedFacets: selected, + page: 0, + }) fadeOut() }} > @@ -98,7 +103,7 @@ function FilterSlider({ function Filter({ facets: allFacets, testId = 'store-filter' }: Props) { const filter = useFilter(allFacets) - const { toggleFacet } = useSearch() + const { resetInfiniteScroll, state, setState } = useSearch() const { filter: displayFilter } = useUI() const { facets, expanded, dispatch } = filter @@ -109,7 +114,17 @@ function Filter({ facets: allFacets, testId = 'store-filter' }: Props) { facets={facets} testId={`desktop-${testId}`} indicesExpanded={expanded} - onFacetChange={toggleFacet} + onFacetChange={(facet, type) => { + setState({ + ...state, + selectedFacets: + type === 'BOOLEAN' + ? toggleFacet(state.selectedFacets, facet) + : setFacet(state.selectedFacets, facet, true), + page: 0, + }) + resetInfiniteScroll(0) + }} onAccordionChange={(index) => dispatch({ type: 'toggleExpanded', payload: index }) } @@ -123,14 +138,33 @@ function Filter({ facets: allFacets, testId = 'store-filter' }: Props) { export const fragment = gql` fragment Filter_facets on StoreFacet { - key - label - type - values { + ... on StoreFacetRange { + key + label + + min { + selected + absolute + } + + max { + selected + absolute + } + + __typename + } + ... on StoreFacetBoolean { + key label - value - selected - quantity + values { + label + value + selected + quantity + } + + __typename } } ` diff --git a/src/components/search/Filter/useFilter.ts b/src/components/search/Filter/useFilter.ts index ef1823ae..d61129cb 100644 --- a/src/components/search/Filter/useFilter.ts +++ b/src/components/search/Filter/useFilter.ts @@ -1,4 +1,4 @@ -import { useSearch } from '@faststore/sdk' +import { setFacet, toggleFacet, useSearch } from '@faststore/sdk' import { useEffect, useMemo, useReducer } from 'react' import type { IStoreSelectedFacet } from '@faststore/api' @@ -22,47 +22,56 @@ type Action = type: 'toggleFacet' payload: IStoreSelectedFacet } + | { + type: 'setFacet' + payload: { facet: IStoreSelectedFacet; unique?: boolean } + } const reducer = (state: State, action: Action) => { const { expanded, selected } = state const { type, payload } = action - if (type === 'toggleExpanded') { - if (expanded.has(payload)) { - expanded.delete(payload) - } else { - expanded.add(payload) - } + switch (type) { + case 'toggleExpanded': { + if (expanded.has(payload)) { + expanded.delete(payload) + } else { + expanded.add(payload) + } - return { - ...state, - expanded: new Set(expanded), + return { + ...state, + expanded: new Set(expanded), + } } - } - if (type === 'selectFacets' && payload !== selected) { - return { - ...state, - selected: payload, - } - } + case 'selectFacets': { + if (payload !== selected) { + return { + ...state, + selected: payload, + } + } - if (type === 'toggleFacet') { - const index = state.selected.findIndex( - (facet) => facet.key === payload.key && facet.value === payload.value - ) + break + } - if (index > -1) { + case 'toggleFacet': { return { ...state, - selected: state.selected.filter((_, idx) => idx !== index), + selected: toggleFacet(state.selected, payload), } } - return { - ...state, - selected: [...state.selected, payload], + case 'setFacet': { + return { + ...state, + selected: setFacet(state.selected, payload.facet, payload.unique), + } } + + default: + throw new Error(`Action ${type} not implemented`) } return state @@ -94,16 +103,20 @@ export const useFilter = (allFacets: Filter_FacetsFragment[]) => { const facets = useMemo( () => - allFacets - .filter((facet) => facet.type === 'BOOLEAN') - .map((facet) => ({ - ...facet, - values: facet.values.map(({ value, ...rest }) => ({ - ...rest, - value, - selected: Boolean(selectedMap.get(facet.key)?.has(value)), - })), - })), + allFacets.map((facet) => { + if (facet.__typename === 'StoreFacetBoolean') { + return { + ...facet, + values: facet.values.map(({ value, ...rest }) => ({ + ...rest, + value, + selected: Boolean(selectedMap.get(facet.key)?.has(value)), + })), + } + } + + return facet + }), [allFacets, selectedMap] ) diff --git a/src/components/search/Sort/Sort.tsx b/src/components/search/Sort/Sort.tsx index 21f707df..cc64e210 100644 --- a/src/components/search/Sort/Sort.tsx +++ b/src/components/search/Sort/Sort.tsx @@ -16,10 +16,7 @@ const OptionsMap = { const keys = Object.keys(OptionsMap) as Array function Sort() { - const { - setSort, - state: { sort }, - } = useSearch() + const { state, setState } = useSearch() return (