diff --git a/packages/atomic/src/components/commerce/atomic-commerce-breadbox/atomic-commerce-breadbox.tsx b/packages/atomic/src/components/commerce/atomic-commerce-breadbox/atomic-commerce-breadbox.tsx index 04b03cddb95..a3261de2e8d 100644 --- a/packages/atomic/src/components/commerce/atomic-commerce-breadbox/atomic-commerce-breadbox.tsx +++ b/packages/atomic/src/components/commerce/atomic-commerce-breadbox/atomic-commerce-breadbox.tsx @@ -15,6 +15,7 @@ import { Context, ContextState, buildContext, + LocationFacetValue, } from '@coveo/headless/commerce'; import {Component, h, State, Element, Prop} from '@stencil/core'; import {FocusTargetController} from '../../../utils/accessibility-utils'; @@ -42,6 +43,7 @@ import {CommerceBindings} from '../atomic-commerce-interface/atomic-commerce-int type AnyFacetValue = | RegularFacetValue + | LocationFacetValue | NumericFacetValue | DateFacetValue | CategoryFacetValue; @@ -288,7 +290,7 @@ export class AtomicCommerceBreadbox (pathValue: string) => getFieldValueCaption(field, pathValue, this.bindings.i18n) ); - default: + case 'regular': return [ getFieldValueCaption( field, @@ -296,6 +298,11 @@ export class AtomicCommerceBreadbox this.bindings.i18n ), ]; + default: { + // TODO COMHUB-291 support location breadcrumb + this.bindings.engine.logger.warn('Unexpected breadcrumb type.'); + return []; + } } }; diff --git a/packages/atomic/src/components/commerce/facets/atomic-commerce-facets/atomic-commerce-facets.tsx b/packages/atomic/src/components/commerce/facets/atomic-commerce-facets/atomic-commerce-facets.tsx index a00bb87e78a..f1c00ecfc7a 100644 --- a/packages/atomic/src/components/commerce/facets/atomic-commerce-facets/atomic-commerce-facets.tsx +++ b/packages/atomic/src/components/commerce/facets/atomic-commerce-facets/atomic-commerce-facets.tsx @@ -133,6 +133,7 @@ export class AtomicCommerceFacets implements InitializableComponent { > ); default: { + // TODO COMHUB-291 support location facet this.bindings.engine.logger.warn('Unexpected facet type.'); return; } diff --git a/packages/headless/src/commerce.index.ts b/packages/headless/src/commerce.index.ts index 0019a2bae71..42af6175ea2 100644 --- a/packages/headless/src/commerce.index.ts +++ b/packages/headless/src/commerce.index.ts @@ -199,6 +199,7 @@ export type { export type {DateFilterRange} from './controllers/core/facets/range-facet/date-facet/headless-core-date-filter.js'; export type { FacetType, + BaseFacetValue, FacetValueRequest, RegularFacetValue, LocationFacetValueRequest, diff --git a/packages/headless/src/controllers/commerce/core/breadcrumb-manager/headless-core-breadcrumb-manager.test.ts b/packages/headless/src/controllers/commerce/core/breadcrumb-manager/headless-core-breadcrumb-manager.test.ts index bb82474d915..68f42119c87 100644 --- a/packages/headless/src/controllers/commerce/core/breadcrumb-manager/headless-core-breadcrumb-manager.test.ts +++ b/packages/headless/src/controllers/commerce/core/breadcrumb-manager/headless-core-breadcrumb-manager.test.ts @@ -18,10 +18,7 @@ import { NumericFacetValue, RegularFacetValue, } from '../../../../features/commerce/facets/facet-set/interfaces/response.js'; -import { - toggleExcludeLocationFacetValue, - toggleSelectLocationFacetValue, -} from '../../../../features/commerce/facets/location-facet/location-facet-actions.js'; +import {toggleSelectLocationFacetValue} from '../../../../features/commerce/facets/location-facet/location-facet-actions.js'; import { toggleExcludeNumericFacetValue, toggleSelectNumericFacetValue, @@ -270,10 +267,23 @@ describe('core breadcrumb manager', () => { expectBreadcrumbToBePresentInState(breadcrumb); }); - describe.each([ - ['selected', toggleSelectLocationFacetValue], - ['excluded', toggleExcludeLocationFacetValue], - ])('#deselect when facet is %s', generateDeselectionTestCases(breadcrumb)); + describe('#deselect when facet is selected', () => { + beforeEach(() => { + breadcrumb.state = 'selected'; + deselectBreadcrumb(); + }); + + it('dispatches #toggleSelectActionCreator', () => { + expect(toggleSelectLocationFacetValue).toHaveBeenCalledWith({ + facetId, + selection: breadcrumb, + }); + }); + + it('dispatches #fetchProductsActionCreator', () => { + expect(fetchProductsActionCreator).toHaveBeenCalled(); + }); + }); }); describe('numeric facet breadcrumbs', () => { diff --git a/packages/headless/src/controllers/commerce/core/breadcrumb-manager/headless-core-breadcrumb-manager.ts b/packages/headless/src/controllers/commerce/core/breadcrumb-manager/headless-core-breadcrumb-manager.ts index 8c9dd6cc524..b72edaf772d 100644 --- a/packages/headless/src/controllers/commerce/core/breadcrumb-manager/headless-core-breadcrumb-manager.ts +++ b/packages/headless/src/controllers/commerce/core/breadcrumb-manager/headless-core-breadcrumb-manager.ts @@ -25,10 +25,7 @@ import { NumericFacetResponse, RegularFacetResponse, } from '../../../../features/commerce/facets/facet-set/interfaces/response.js'; -import { - toggleExcludeLocationFacetValue, - toggleSelectLocationFacetValue, -} from '../../../../features/commerce/facets/location-facet/location-facet-actions.js'; +import {toggleSelectLocationFacetValue} from '../../../../features/commerce/facets/location-facet/location-facet-actions.js'; import { toggleExcludeNumericFacetValue, toggleSelectNumericFacetValue, @@ -125,17 +122,11 @@ interface ActionCreators { toggleExcludeActionCreator?: ToggleActionCreator; } -const facetTypeWithoutExcludeAction: FacetType = 'hierarchical'; - const actions: Record = { regular: { toggleSelectActionCreator: toggleSelectFacetValue, toggleExcludeActionCreator: toggleExcludeFacetValue, }, - location: { - toggleSelectActionCreator: toggleSelectLocationFacetValue, - toggleExcludeActionCreator: toggleExcludeLocationFacetValue, - }, numericalRange: { toggleSelectActionCreator: toggleSelectNumericFacetValue, toggleExcludeActionCreator: toggleExcludeNumericFacetValue, @@ -144,7 +135,10 @@ const actions: Record = { toggleSelectActionCreator: toggleSelectDateFacetValue, toggleExcludeActionCreator: toggleExcludeDateFacetValue, }, - [facetTypeWithoutExcludeAction]: { + location: { + toggleSelectActionCreator: toggleSelectLocationFacetValue, + }, + hierarchical: { toggleSelectActionCreator: deselectAllValuesInCoreFacet, }, }; @@ -198,16 +192,19 @@ export function buildCoreBreadcrumbManager( selection, }) ); - dispatch( - updateCoreFacetFreezeCurrentValues({ - facetId: facet.facetId, - freezeCurrentValues: false, - }) - ); + + if (facet.type !== 'location') { + dispatch( + updateCoreFacetFreezeCurrentValues({ + facetId: facet.facetId, + freezeCurrentValues: false, + }) + ); + } dispatch(options.fetchProductsActionCreator()); } else if ( selection.state === 'excluded' && - facet.type !== facetTypeWithoutExcludeAction + facet.type !== 'location' ) { dispatch( actions[facet.type].toggleExcludeActionCreator!({ diff --git a/packages/headless/src/controllers/commerce/core/facets/headless-core-commerce-facet.ts b/packages/headless/src/controllers/commerce/core/facets/headless-core-commerce-facet.ts index 4fe382b45e0..14d0fa10de7 100644 --- a/packages/headless/src/controllers/commerce/core/facets/headless-core-commerce-facet.ts +++ b/packages/headless/src/controllers/commerce/core/facets/headless-core-commerce-facet.ts @@ -16,6 +16,7 @@ import { import { AnyFacetResponse, AnyFacetValueResponse, + BaseFacetValue, CategoryFacetValue, DateFacetValue, LocationFacetValue, @@ -47,6 +48,7 @@ export type { DateFacetValue, CategoryFacetValueRequest, CategoryFacetValue, + BaseFacetValue, }; export interface FacetControllerType { diff --git a/packages/headless/src/controllers/commerce/core/facets/location/headless-commerce-location-facet.test.ts b/packages/headless/src/controllers/commerce/core/facets/location/headless-commerce-location-facet.test.ts index 9878ce4fca7..ae0e5715b28 100644 --- a/packages/headless/src/controllers/commerce/core/facets/location/headless-commerce-location-facet.test.ts +++ b/packages/headless/src/controllers/commerce/core/facets/location/headless-commerce-location-facet.test.ts @@ -1,8 +1,5 @@ import {LocationFacetRequest} from '../../../../../features/commerce/facets/facet-set/interfaces/request.js'; -import { - toggleExcludeLocationFacetValue, - toggleSelectLocationFacetValue, -} from '../../../../../features/commerce/facets/location-facet/location-facet-actions.js'; +import {toggleSelectLocationFacetValue} from '../../../../../features/commerce/facets/location-facet/location-facet-actions.js'; import {CommerceAppState} from '../../../../../state/commerce-app-state.js'; import {buildMockCommerceFacetRequest} from '../../../../../test/mock-commerce-facet-request.js'; import {buildMockCommerceLocationFacetResponse} from '../../../../../test/mock-commerce-facet-response.js'; @@ -88,16 +85,6 @@ describe('LocationFacet', () => { }); }); - it('#toggleExclude dispatches #toggleExcludeLocationFacetValue with correct payload', () => { - const facetValue = buildMockCommerceLocationFacetValue({value: 'TED'}); - facet.toggleExclude(facetValue); - - expect(toggleExcludeLocationFacetValue).toHaveBeenCalledWith({ - facetId, - selection: facetValue, - }); - }); - it('#type returns "location"', () => { expect(facet.type).toBe('location'); }); diff --git a/packages/headless/src/controllers/commerce/core/facets/location/headless-commerce-location-facet.ts b/packages/headless/src/controllers/commerce/core/facets/location/headless-commerce-location-facet.ts index 05d6a2e99e0..06011ad9d36 100644 --- a/packages/headless/src/controllers/commerce/core/facets/location/headless-commerce-location-facet.ts +++ b/packages/headless/src/controllers/commerce/core/facets/location/headless-commerce-location-facet.ts @@ -1,9 +1,6 @@ import {CommerceEngine} from '../../../../../app/commerce-engine/commerce-engine.js'; import {LocationFacetValue} from '../../../../../features/commerce/facets/facet-set/interfaces/response.js'; -import { - toggleExcludeLocationFacetValue, - toggleSelectLocationFacetValue, -} from '../../../../../features/commerce/facets/location-facet/location-facet-actions.js'; +import {toggleSelectLocationFacetValue} from '../../../../../features/commerce/facets/location-facet/location-facet-actions.js'; import { CoreCommerceFacet, CoreCommerceFacetOptions, @@ -29,9 +26,9 @@ export type LocationFacetState = Omit< * The `LocationFacet` sub-controller offers a high-level programming interface for implementing a location commerce * facet UI component. */ -export type LocationFacet = CoreCommerceFacet< - FacetValueRequest, - LocationFacetValue +export type LocationFacet = Omit< + CoreCommerceFacet, + 'isValueExcluded' | 'toggleExclude' | 'toggleSingleExclude' > & { state: LocationFacetState; } & FacetControllerType<'location'>; @@ -52,14 +49,15 @@ export function buildCommerceLocationFacet( engine: CommerceEngine, options: LocationFacetOptions ): LocationFacet { - const coreController = buildCoreCommerceFacet< - FacetValueRequest, - LocationFacetValue - >(engine, { + const { + toggleSingleExclude, + toggleExclude, + isValueExcluded, + ...coreController + } = buildCoreCommerceFacet(engine, { options: { ...options, toggleSelectActionCreator: toggleSelectLocationFacetValue, - toggleExcludeActionCreator: toggleExcludeLocationFacetValue, }, }); diff --git a/packages/headless/src/features/commerce/facets/facet-set/facet-set-slice.test.ts b/packages/headless/src/features/commerce/facets/facet-set/facet-set-slice.test.ts index c5e6ad9aa82..718eac634b6 100644 --- a/packages/headless/src/features/commerce/facets/facet-set/facet-set-slice.test.ts +++ b/packages/headless/src/features/commerce/facets/facet-set/facet-set-slice.test.ts @@ -67,10 +67,7 @@ import { updateDateFacetValues, } from '../date-facet/date-facet-actions.js'; import {getFacetIdWithCommerceFieldSuggestionNamespace} from '../facet-search-set/commerce-facet-search-actions.js'; -import { - toggleExcludeLocationFacetValue, - toggleSelectLocationFacetValue, -} from '../location-facet/location-facet-actions.js'; +import {toggleSelectLocationFacetValue} from '../location-facet/location-facet-actions.js'; import { toggleExcludeNumericFacetValue, toggleSelectNumericFacetValue, @@ -1005,12 +1002,6 @@ describe('commerceFacetSetReducer', () => { facetValueState: 'selected' as FacetValueState, toggleAction: toggleSelectLocationFacetValue, }, - { - title: - 'dispatching #toggleExcludeLocationFacetValue with a registered facet id', - facetValueState: 'excluded' as FacetValueState, - toggleAction: toggleExcludeLocationFacetValue, - }, ])( '$title', ({ @@ -1104,52 +1095,6 @@ describe('commerceFacetSetReducer', () => { ).find((req) => req.value === facetValue.value); expect(targetValue?.state).toBe('idle'); }); - - it('sets #preventAutoSelect to true', () => { - const facetValue = buildMockCommerceLocationFacetValue({ - value: 'TED', - }); - const facetValueRequest = - convertLocationFacetValueToRequest(facetValue); - - state[facetId] = buildMockCommerceFacetSlice({ - request: buildMockCommerceFacetRequest({ - values: [facetValueRequest], - type: 'location', - }), - }); - - const action = toggleAction({ - facetId, - selection: facetValue, - }); - const finalState = commerceFacetSetReducer(state, action); - - expect(finalState[facetId]?.request.preventAutoSelect).toBe(true); - }); - - it('sets #freezeCurrentValues to true', () => { - const facetValue = buildMockCommerceLocationFacetValue({ - value: 'TED', - }); - const facetValueRequest = - convertLocationFacetValueToRequest(facetValue); - - state[facetId] = buildMockCommerceFacetSlice({ - request: buildMockCommerceFacetRequest({ - values: [facetValueRequest], - type: 'location', - }), - }); - - const action = toggleAction({ - facetId, - selection: facetValue, - }); - const finalState = commerceFacetSetReducer(state, action); - - expect(finalState[facetId]?.request.freezeCurrentValues).toBe(true); - }); }); describe.each([ @@ -1157,10 +1102,6 @@ describe('commerceFacetSetReducer', () => { facetValueState: 'selected' as FacetValueState, toggleAction: toggleSelectLocationFacetValue, }, - { - facetValueState: 'excluded' as FacetValueState, - toggleAction: toggleExcludeLocationFacetValue, - }, ])( 'when the facet value does not exist', ({ @@ -1214,20 +1155,6 @@ describe('commerceFacetSetReducer', () => { ).toBe(2); expect(finalState[facetId]?.request.values.length).toBe(4); }); - - it('sets #preventAutoSelect to true', () => { - state[facetId] = buildMockCommerceFacetSlice({ - request: buildMockCommerceFacetRequest({type: 'location'}), - }); - - const action = toggleAction({ - facetId, - selection: buildMockCommerceLocationFacetValue({value: 'TED'}), - }); - const finalState = commerceFacetSetReducer(state, action); - - expect(finalState[facetId]?.request.preventAutoSelect).toBe(true); - }); } ); } @@ -1258,33 +1185,6 @@ describe('commerceFacetSetReducer', () => { expect(() => commerceFacetSetReducer(state, action)).not.toThrow(); }); - - it('dispatching #toggleExcludeLocationFacetValue with an invalid id does not throw', () => { - const facetValue = buildMockCommerceLocationFacetValue({value: 'TED'}); - const action = toggleExcludeLocationFacetValue({ - facetId: '1', - selection: facetValue, - }); - - expect(() => commerceFacetSetReducer(state, action)).not.toThrow(); - }); - - it('dispatching #toggleExcludeLocationFacetValue with an invalid facet type does not throw', () => { - const facetValue = buildMockCommerceLocationFacetValue({value: 'TED'}); - const facet = buildMockCommerceFacetRequest({ - type: 'numericalRange', - values: [facetValue], - }); - state[facet.facetId] = buildMockCommerceFacetSlice({ - request: facet, - }); - const action = toggleExcludeLocationFacetValue({ - facetId: facet.facetId, - selection: facetValue, - }); - - expect(() => commerceFacetSetReducer(state, action)).not.toThrow(); - }); }); describe('for numericalRange facets', () => { diff --git a/packages/headless/src/features/commerce/facets/facet-set/facet-set-slice.ts b/packages/headless/src/features/commerce/facets/facet-set/facet-set-slice.ts index fe1b06ba9b5..11b00f1a424 100644 --- a/packages/headless/src/features/commerce/facets/facet-set/facet-set-slice.ts +++ b/packages/headless/src/features/commerce/facets/facet-set/facet-set-slice.ts @@ -44,10 +44,7 @@ import { executeCommerceFieldSuggest, getFacetIdWithCommerceFieldSuggestionNamespace, } from '../facet-search-set/commerce-facet-search-actions.js'; -import { - toggleExcludeLocationFacetValue, - toggleSelectLocationFacetValue, -} from '../location-facet/location-facet-actions.js'; +import {toggleSelectLocationFacetValue} from '../location-facet/location-facet-actions.js'; import { toggleExcludeNumericFacetValue, toggleSelectNumericFacetValue, @@ -136,8 +133,6 @@ export const commerceFacetSetReducer = createReducer( return; } - facetRequest.preventAutoSelect = true; - const existingValue = facetRequest.values.find( (req) => req.value === selection.value ); @@ -147,7 +142,6 @@ export const commerceFacetSetReducer = createReducer( } updateExistingFacetValueState(existingValue, 'select'); - facetRequest.freezeCurrentValues = true; }) .addCase(toggleSelectNumericFacetValue, (state, action) => { const {facetId, selection} = action.payload; @@ -250,27 +244,6 @@ export const commerceFacetSetReducer = createReducer( updateExistingFacetValueState(existingValue, 'exclude'); facetRequest.freezeCurrentValues = true; }) - .addCase(toggleExcludeLocationFacetValue, (state, action) => { - const {facetId, selection} = action.payload; - const facetRequest = state[facetId]?.request; - - if (!facetRequest || !ensureLocationFacetRequest(facetRequest)) { - return; - } - - facetRequest.preventAutoSelect = true; - - const existingValue = facetRequest.values.find( - (req) => req.value === selection.value - ); - if (!existingValue) { - insertNewValue(facetRequest, selection); - return; - } - - updateExistingFacetValueState(existingValue, 'exclude'); - facetRequest.freezeCurrentValues = true; - }) .addCase(toggleExcludeNumericFacetValue, (state, action) => { const {facetId, selection} = action.payload; const facetRequest = state[facetId]?.request; diff --git a/packages/headless/src/features/commerce/facets/facet-set/interfaces/request.ts b/packages/headless/src/features/commerce/facets/facet-set/interfaces/request.ts index ed34d45d8ec..413d69d223e 100644 --- a/packages/headless/src/features/commerce/facets/facet-set/interfaces/request.ts +++ b/packages/headless/src/features/commerce/facets/facet-set/interfaces/request.ts @@ -13,11 +13,17 @@ import { NumericFacetExtraProperties, } from './common.js'; +export type FreezableFacetRequestProperties = { + preventAutoSelect: boolean; + freezeCurrentValues?: boolean; +}; + export type CategoryFacetRequest = BaseCommerceFacetRequest< CategoryFacetValueRequest, 'hierarchical' > & - CategoryFacetDelimitingCharacter; + CategoryFacetDelimitingCharacter & + FreezableFacetRequestProperties; export interface CategoryFacetValueRequest extends BaseFacetValueRequest { children: CategoryFacetValueRequest[]; @@ -28,18 +34,21 @@ export interface CategoryFacetValueRequest extends BaseFacetValueRequest { export type DateFacetRequest = BaseCommerceFacetRequest< DateRangeRequest, 'dateRange' ->; +> & + FreezableFacetRequestProperties; export type NumericFacetRequest = BaseCommerceFacetRequest< NumericRangeRequest, 'numericalRange' > & - NumericFacetExtraProperties; + NumericFacetExtraProperties & + FreezableFacetRequestProperties; export type RegularFacetRequest = BaseCommerceFacetRequest< FacetValueRequest, 'regular' ->; +> & + FreezableFacetRequestProperties; export type LocationFacetValueRequest = FacetValueRequest; @@ -50,18 +59,13 @@ export type LocationFacetRequest = BaseCommerceFacetRequest< export type BaseCommerceFacetRequest = Pick< FacetRequest, - | 'facetId' - | 'field' - | 'numberOfValues' - | 'isFieldExpanded' - | 'preventAutoSelect' + 'facetId' | 'field' | 'numberOfValues' | 'isFieldExpanded' > & { displayName?: string; type: Type; values: Value[]; initialNumberOfValues: number; numberOfValues?: number; - freezeCurrentValues?: boolean; }; export type AnyFacetValueRequest = @@ -71,21 +75,15 @@ export type AnyFacetValueRequest = | NumericRangeRequest | DateRangeRequest; -export type AnyFacetRequest = Pick< - FacetRequest, - | 'facetId' - | 'field' - | 'numberOfValues' - | 'isFieldExpanded' - | 'preventAutoSelect' -> & { - displayName?: string; - type: FacetType; - values: AnyFacetValueRequest[]; - initialNumberOfValues: number; - numberOfValues?: number; - freezeCurrentValues?: boolean; -} & Partial; +export type AnyFacetRequest = BaseCommerceFacetRequest< + AnyFacetValueRequest, + FacetType +> & + Partial< + CategoryFacetDelimitingCharacter & + NumericFacetExtraProperties & + FreezableFacetRequestProperties + >; type MappedFacetRequest = { [T in FacetType]: T extends 'numericalRange' diff --git a/packages/headless/src/features/commerce/facets/facet-set/interfaces/response.ts b/packages/headless/src/features/commerce/facets/facet-set/interfaces/response.ts index 505973ea6cf..68643ece1ea 100644 --- a/packages/headless/src/features/commerce/facets/facet-set/interfaces/response.ts +++ b/packages/headless/src/features/commerce/facets/facet-set/interfaces/response.ts @@ -11,11 +11,20 @@ export type CategoryFacetResponse = BaseFacetResponse< > & CategoryFacetDelimitingCharacter; -export interface CategoryFacetValue extends BaseFacetValue { +interface NonLocationFacetValue { + numberOfResults: number; + isAutoSelected: boolean; + isSuggested: boolean; +} + +export interface CategoryFacetValue + extends BaseFacetValue, + NonLocationFacetValue { value: string; path: string[]; isLeafValue: boolean; children: CategoryFacetValue[]; + moreValuesAvailable: boolean; } export type DateFacetResponse = BaseFacetResponse; @@ -35,8 +44,14 @@ export type RegularFacetResponse = BaseFacetResponse< 'regular' >; -export interface RegularFacetValue extends BaseFacetValue { +export interface RegularFacetValue + extends BaseFacetValue, + NonLocationFacetValue { value: string; + /** + * @deprecated Use the facet's `moreValuesAvailable` property instead. + */ + moreValuesAvailable: boolean; } export type LocationFacetResponse = BaseFacetResponse< @@ -48,10 +63,16 @@ export interface LocationFacetValue extends BaseFacetValue { value: string; } -export interface RangeFacetValue extends BaseFacetValue { +export interface RangeFacetValue + extends BaseFacetValue, + NonLocationFacetValue { start: T; end: T; endInclusive: boolean; + /** + * @deprecated Use the facet's `moreValuesAvailable` property instead. + */ + moreValuesAvailable: boolean; } export interface BaseFacetResponse< @@ -71,10 +92,6 @@ export interface BaseFacetResponse< export interface BaseFacetValue { state: FacetValueState; - numberOfResults: number; - isAutoSelected: boolean; - isSuggested: boolean; - moreValuesAvailable: boolean; } export type AnyFacetValueResponse = diff --git a/packages/headless/src/features/commerce/facets/location-facet/location-facet-actions-loader.ts b/packages/headless/src/features/commerce/facets/location-facet/location-facet-actions-loader.ts index 74c25fa3ced..a024d1960af 100644 --- a/packages/headless/src/features/commerce/facets/location-facet/location-facet-actions-loader.ts +++ b/packages/headless/src/features/commerce/facets/location-facet/location-facet-actions-loader.ts @@ -2,30 +2,16 @@ import {PayloadAction} from '@reduxjs/toolkit'; import {CommerceEngine} from '../../../../app/commerce-engine/commerce-engine.js'; import {commerceFacetSetReducer as commerceFacetSet} from '../facet-set/facet-set-slice.js'; import { - ToggleExcludeFacetValuePayload, - ToggleSelectFacetValuePayload, -} from '../regular-facet/regular-facet-actions.js'; -import { - toggleExcludeLocationFacetValue, toggleSelectLocationFacetValue, + ToggleSelectLocationFacetValuePayload, } from './location-facet-actions.js'; -export type {ToggleExcludeFacetValuePayload, ToggleSelectFacetValuePayload}; +export type {ToggleSelectLocationFacetValuePayload}; /** * The location facet action creators. */ export interface LocationFacetActionCreators { - /** - * Toggles the exclusion of a given location facet value. - * - * @param payload - The action creator payload. - * @returns A dispatchable action. - */ - toggleExcludeLocationFacetValue( - payload: ToggleExcludeFacetValuePayload - ): PayloadAction; - /** * Toggles the selection of a given location facet value. * @@ -33,8 +19,8 @@ export interface LocationFacetActionCreators { * @returns A dispatchable action. */ toggleSelectLocationFacetValue( - payload: ToggleSelectFacetValuePayload - ): PayloadAction; + payload: ToggleSelectLocationFacetValuePayload + ): PayloadAction; } /** @@ -48,7 +34,6 @@ export function loadLocationFacetActions( ): LocationFacetActionCreators { engine.addReducers({commerceFacetSet}); return { - toggleExcludeLocationFacetValue, toggleSelectLocationFacetValue, }; } diff --git a/packages/headless/src/features/commerce/facets/location-facet/location-facet-actions.ts b/packages/headless/src/features/commerce/facets/location-facet/location-facet-actions.ts index 04db303b72c..f844b9137bf 100644 --- a/packages/headless/src/features/commerce/facets/location-facet/location-facet-actions.ts +++ b/packages/headless/src/features/commerce/facets/location-facet/location-facet-actions.ts @@ -5,23 +5,23 @@ import { validatePayload, } from '../../../../utils/validate-payload.js'; import {facetValueDefinition} from '../../../facets/facet-set/facet-set-validate-payload.js'; -import { - ToggleExcludeFacetValuePayload, - ToggleSelectFacetValuePayload, -} from '../regular-facet/regular-facet-actions.js'; +import {LocationFacetValue} from '../facet-set/interfaces/response.js'; -export const toggleExcludeLocationFacetValue = createAction( - 'commerce/facets/locationFacet/toggleExcludeValue', - (payload: ToggleExcludeFacetValuePayload) => - validatePayload(payload, { - facetId: requiredNonEmptyString, - selection: new RecordValue({values: facetValueDefinition}), - }) -); +export interface ToggleSelectLocationFacetValuePayload { + /** + * The unique identifier of the facet (e.g., `"1"`). + */ + facetId: string; + + /** + * The target location facet value. + */ + selection: LocationFacetValue; +} export const toggleSelectLocationFacetValue = createAction( 'commerce/facets/locationFacet/toggleSelectValue', - (payload: ToggleSelectFacetValuePayload) => + (payload: ToggleSelectLocationFacetValuePayload) => validatePayload(payload, { facetId: requiredNonEmptyString, selection: new RecordValue({values: facetValueDefinition}), diff --git a/packages/headless/src/features/commerce/pagination/pagination-slice.test.ts b/packages/headless/src/features/commerce/pagination/pagination-slice.test.ts index b4dca0520c6..72bd01a0477 100644 --- a/packages/headless/src/features/commerce/pagination/pagination-slice.test.ts +++ b/packages/headless/src/features/commerce/pagination/pagination-slice.test.ts @@ -11,10 +11,7 @@ import { toggleExcludeDateFacetValue, toggleSelectDateFacetValue, } from '../facets/date-facet/date-facet-actions.js'; -import { - toggleExcludeLocationFacetValue, - toggleSelectLocationFacetValue, -} from '../facets/location-facet/location-facet-actions.js'; +import {toggleSelectLocationFacetValue} from '../facets/location-facet/location-facet-actions.js'; import { toggleExcludeNumericFacetValue, toggleSelectNumericFacetValue, @@ -277,10 +274,6 @@ describe('pagination slice', () => { actionName: '#toggleSelectLocationFacetValue', action: toggleSelectLocationFacetValue, }, - { - actionName: '#toggleExcludeLocationFacetValue', - action: toggleExcludeLocationFacetValue, - }, { actionName: '#toggleSelectNumericFacetValue', action: toggleSelectNumericFacetValue, diff --git a/packages/headless/src/features/commerce/pagination/pagination-slice.ts b/packages/headless/src/features/commerce/pagination/pagination-slice.ts index b7adff645b0..5037c73ad74 100644 --- a/packages/headless/src/features/commerce/pagination/pagination-slice.ts +++ b/packages/headless/src/features/commerce/pagination/pagination-slice.ts @@ -9,10 +9,7 @@ import { toggleExcludeDateFacetValue, toggleSelectDateFacetValue, } from '../facets/date-facet/date-facet-actions.js'; -import { - toggleExcludeLocationFacetValue, - toggleSelectLocationFacetValue, -} from '../facets/location-facet/location-facet-actions.js'; +import {toggleSelectLocationFacetValue} from '../facets/location-facet/location-facet-actions.js'; import { toggleExcludeNumericFacetValue, toggleSelectNumericFacetValue, @@ -114,7 +111,6 @@ export const paginationReducer = createReducer( .addCase(toggleSelectFacetValue, handlePaginationReset) .addCase(toggleExcludeFacetValue, handlePaginationReset) .addCase(toggleSelectLocationFacetValue, handlePaginationReset) - .addCase(toggleExcludeLocationFacetValue, handlePaginationReset) .addCase(toggleSelectNumericFacetValue, handlePaginationReset) .addCase(toggleExcludeNumericFacetValue, handlePaginationReset) .addCase(toggleSelectDateFacetValue, handlePaginationReset) diff --git a/packages/headless/src/ssr-commerce.index.ts b/packages/headless/src/ssr-commerce.index.ts index a992a2b614d..ca3f343732a 100644 --- a/packages/headless/src/ssr-commerce.index.ts +++ b/packages/headless/src/ssr-commerce.index.ts @@ -151,6 +151,8 @@ export type { MappedGeneratedFacetController, MappedFacetStates, MappedFacetState, + LocationFacetValue, + LocationFacetState, FacetType, } from './controllers/commerce/core/facets/generator/headless-commerce-facet-generator.ssr.js'; export {defineFacetGenerator} from './controllers/commerce/core/facets/generator/headless-commerce-facet-generator.ssr.js'; diff --git a/packages/headless/src/test/mock-commerce-facet-value.ts b/packages/headless/src/test/mock-commerce-facet-value.ts index 09130506392..1b923c9aad6 100644 --- a/packages/headless/src/test/mock-commerce-facet-value.ts +++ b/packages/headless/src/test/mock-commerce-facet-value.ts @@ -26,10 +26,6 @@ export function buildMockCommerceLocationFacetValue( return { value: '', state: 'idle', - numberOfResults: 0, - isAutoSelected: false, - isSuggested: false, - moreValuesAvailable: false, ...config, }; } diff --git a/packages/samples/headless-commerce-react/src/components/breadcrumb-manager/breadcrumb-manager.tsx b/packages/samples/headless-commerce-react/src/components/breadcrumb-manager/breadcrumb-manager.tsx index 72cc88acbaf..5826c94404e 100644 --- a/packages/samples/headless-commerce-react/src/components/breadcrumb-manager/breadcrumb-manager.tsx +++ b/packages/samples/headless-commerce-react/src/components/breadcrumb-manager/breadcrumb-manager.tsx @@ -4,6 +4,7 @@ import { NumericFacetValue, DateFacetValue, BreadcrumbManager as HeadlessBreadcrumbManager, + LocationFacetValue, } from '@coveo/headless/commerce'; import {useEffect, useState} from 'react'; @@ -29,7 +30,8 @@ export default function BreadcrumbManager(props: BreadcrumbManagerProps) { | CategoryFacetValue | RegularFacetValue | NumericFacetValue - | DateFacetValue, + | DateFacetValue + | LocationFacetValue, type: string ) => { switch (type) { @@ -50,6 +52,7 @@ export default function BreadcrumbManager(props: BreadcrumbManagerProps) { (value as DateFacetValue).end ); default: + // TODO COMHUB-292 add location facet example return null; } }; diff --git a/packages/samples/headless-ssr-commerce/app/_components/breadcrumb-manager.tsx b/packages/samples/headless-ssr-commerce/app/_components/breadcrumb-manager.tsx index 0ea61e0d277..6e4eef604ae 100644 --- a/packages/samples/headless-ssr-commerce/app/_components/breadcrumb-manager.tsx +++ b/packages/samples/headless-ssr-commerce/app/_components/breadcrumb-manager.tsx @@ -5,6 +5,7 @@ import { CategoryFacetValue, BreadcrumbManager as HeadlessBreadcrumbManager, RegularFacetValue, + LocationFacetValue, } from '@coveo/headless/ssr-commerce'; import {useEffect, useState} from 'react'; @@ -27,7 +28,8 @@ export default function BreadcrumbManager(props: BreadcrumbManagerProps) { | CategoryFacetValue | RegularFacetValue | NumericFacetValue - | DateFacetValue, + | DateFacetValue + | LocationFacetValue, type: string ) => { switch (type) { @@ -48,6 +50,7 @@ export default function BreadcrumbManager(props: BreadcrumbManagerProps) { (value as DateFacetValue).end ); default: + // TODO COMHUB-291 support location breadcrumb return null; } };