Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7aae839
chore: Ensure session with location data (#2745)
lucasfp13 Mar 26, 2025
3b41490
feat: Display `city` and `postalCode` (#2772)
lucasfp13 Apr 11, 2025
c8199b9
feat: Adds RegionPopover component and handles location update (#2775)
hellofanny Apr 25, 2025
7b64e2b
feat: Check products availability when setting postal code (#2817)
lucasfp13 Apr 30, 2025
f6d0859
chore: `No products available` label from Headless CMS and code refac…
lucasfp13 May 8, 2025
0e586e4
Fix rebase
lariciamota May 13, 2025
99475f9
feat: Adds delivery methods in PDP filters (#2826)
hellofanny May 14, 2025
c852d9f
feat: Create Global Sections Settings tab (#2845)
lariciamota May 19, 2025
0ce1b2b
feat: Add Region Slider to set/change location (#2851)
lariciamota May 22, 2025
b8c7304
feat: Shipping methods integration (#2847)
lucasfp13 May 30, 2025
26bec97
feat: Edit pickup points slideover (#2872)
hellofanny Jun 10, 2025
499339c
chore: Renames to avoid mixing delivery methods with delivery option …
hellofanny Jun 10, 2025
27ca8b4
chore: use global settings in RegionPopover and RegionModal (#2918)
lariciamota Jul 1, 2025
d2d525c
refactor: gathering delivery promise logic in one single hook to allo…
ommeirelles Jul 3, 2025
f17c489
chore: Organize Delivery Promise config in global settings (#2939)
lariciamota Jul 11, 2025
a18c025
feat: Global filter by pickup point (SFS-2458) (#2887)
lucasfp13 Jul 15, 2025
ec03fc3
feat: Add `RegionSlider` clear filter button (#2944)
lucasfp13 Jul 17, 2025
f7f589d
fix: change pickup points endpoint (#2955)
lariciamota Jul 24, 2025
e01ab65
Fix after rebase
lariciamota Jul 24, 2025
e7b2716
feat: Shipping methods integration (#2847)
lucasfp13 May 30, 2025
bec3ad1
feat: Global filter by pickup point (SFS-2458) (#2887)
lucasfp13 Jul 15, 2025
6a9eb48
Fix after rebase
lariciamota Jul 24, 2025
79d22ca
Fix after rebase
lariciamota Jul 30, 2025
ee63e58
feat: Delivery Promise 2.1 - filters by dynamic estimate (#2959)
lariciamota Aug 11, 2025
6dfa85a
feat: Filter by shipping method delivery when dynamic estimate is sel…
lariciamota Sep 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion packages/components/src/molecules/ToggleField/ToggleField.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ChangeEventHandler } from 'react'
import React, { forwardRef } from 'react'
import { Label, SROnly, Toggle, type ToggleProps } from './../../'

Expand Down Expand Up @@ -26,6 +27,14 @@ export interface ToggleFieldProps extends ToggleProps {
* Controls the component's direction.
*/
variant?: 'horizontal' | 'vertical'
/**
* Specifies if the input is checked or not.
*/
checked?: boolean
/**
* Function that is triggered when any children is checked.
*/
onChange?: ChangeEventHandler<HTMLInputElement>
}

const ToggleField = forwardRef<HTMLDivElement, ToggleFieldProps>(
Expand All @@ -43,7 +52,13 @@ const ToggleField = forwardRef<HTMLDivElement, ToggleFieldProps>(
) {
return (
<div ref={ref} data-fs-toggle-field data-testid={testId}>
<Toggle id={id} variant={variant} disabled={disabled} {...otherProps} />
<Toggle
id={id}
variant={variant}
disabled={disabled}
data-testid={`${testId}-toggle`}
{...otherProps}
/>
{displayLabel ? (
<Label data-fs-toggle-field-label htmlFor={id}>
{label}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ReactNode } from 'react'
import React from 'react'
import { Badge, Checkbox, Label, RadioField } from '../..'
import { Badge, Checkbox, Label, RadioField, ToggleField } from '../..'
import type { OnFacetChange } from './Filter'

export interface FilterFacetBooleanItemProps {
Expand Down Expand Up @@ -39,7 +39,7 @@ export interface FilterFacetBooleanItemProps {
/**
* Type of the Facet Item.
*/
type?: 'checkbox' | 'radio'
type?: 'checkbox' | 'radio' | 'toggle'
}

function FilterFacetBooleanItem({
Expand All @@ -53,31 +53,32 @@ function FilterFacetBooleanItem({
type = 'checkbox',
onFacetChange,
}: FilterFacetBooleanItemProps) {
return (
<li key={id} data-fs-filter-list-item>
{type === 'checkbox' ? (
<>
<Checkbox
id={id}
checked={selected}
onChange={() => onFacetChange({ key: facetKey, value }, 'BOOLEAN')}
data-fs-filter-list-item-checkbox
data-testid={`${testId}-accordion-panel-checkbox`}
data-value={value}
data-quantity={quantity}
/>
<Label
htmlFor={id}
className="text__title-mini-alt"
data-fs-filter-list-item-label
>
{label}
{quantity && (
<Badge data-fs-filter-list-item-badge>{quantity}</Badge>
)}
</Label>
</>
) : (
if (type === 'checkbox') {
return (
<li key={id} data-fs-filter-list-item>
<Checkbox
id={id}
checked={selected}
onChange={() => onFacetChange({ key: facetKey, value }, 'BOOLEAN')}
data-fs-filter-list-item-checkbox
data-testid={`${testId}-accordion-panel-checkbox`}
data-value={value}
data-quantity={quantity}
/>
<Label
htmlFor={id}
className="text__title-mini-alt"
data-fs-filter-list-item-label
>
{label} <Badge data-fs-filter-list-item-badge>{quantity}</Badge>
</Label>
</li>
)
}

if (type === 'radio') {
return (
<li key={id} data-fs-filter-list-item>
<RadioField
id={id}
name={facetKey}
Expand All @@ -89,9 +90,25 @@ function FilterFacetBooleanItem({
data-value={value}
label={label}
/>
)}
</li>
)
</li>
)
}

if (type === 'toggle') {
return (
<li key={id} data-fs-filter-list-item>
<ToggleField
id={id}
label={label as string}
checked={selected}
onChange={() => onFacetChange({ key: facetKey, value }, 'BOOLEAN')}
testId={`${testId}-accordion-panel-toggle-field`}
/>
</li>
)
}

return null
}

export default FilterFacetBooleanItem
34 changes: 24 additions & 10 deletions packages/components/src/organisms/Filter/FilterFacets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ export interface FilterFacetsProps {
/**
* The text displayed to identify the Facet.
*/
label: string
label?: string
/**
* The description displayed to identify the Facet.
*/
description?: string
/**
* Defines if the facet should be highlighted, it will not be displayed as an accordion button and will be expanded (not collapsible).
*/
highlighted?: boolean
}

function FilterFacets({
Expand All @@ -31,6 +35,7 @@ function FilterFacets({
children,
type,
description,
highlighted,
}: PropsWithChildren<FilterFacetsProps>) {
return (
<AccordionItem
Expand All @@ -40,16 +45,25 @@ function FilterFacets({
index={index}
data-type={type}
data-fs-filter-accordion-item
data-fs-filter-accordion-item-highlighted={highlighted}
>
<AccordionButton testId={`${testId}-accordion-button`}>
{label}
</AccordionButton>
<AccordionPanel>
{description && (
<span data-fs-filter-accordion-item-description>{description}</span>
)}
{children}
</AccordionPanel>
{highlighted ? (
<>{children}</>
) : (
<>
<AccordionButton testId={`${testId}-accordion-button`}>
{label}
</AccordionButton>
<AccordionPanel>
{description && (
<span data-fs-filter-accordion-item-description>
{description}
</span>
)}
{children}
</AccordionPanel>
</>
)}
</AccordionItem>
)
}
Expand Down
21 changes: 21 additions & 0 deletions packages/core/cms/faststore/content-types.json
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,27 @@
}
}
},
"dynamicEstimate": {
"title": "PLP/Search Filter: Dynamic Estimate",
"type": "object",
"properties": {
"enabled": {
"title": "Should display Dynamic Estimate?",
"type": "boolean",
"default": true
},
"sameDay": {
"title": "Same Day label",
"type": "string",
"default": "Receive Today"
},
"nextDay": {
"title": "Next Day label",
"type": "string",
"default": "Receive Tomorrow"
}
}
},
"deliveryPromiseBadges": {
"title": "Delivery Promise badges",
"type": "object",
Expand Down
36 changes: 33 additions & 3 deletions packages/core/src/components/search/Filter/FilterDesktop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ interface FilterDesktopProps

function FilterDesktop({
facets,
testId,
testId = 'filter-desktop',
dispatch,
expanded,
title,
Expand All @@ -48,11 +48,13 @@ function FilterDesktop({
} = useSearch()
const { openRegionSlider } = useUI()
const {
facets: filteredFacets,
highlightedFacet,
facetsWithoutHighlightedFacet,
labelsMap,
isPickupAllEnabled,
shouldDisplayDeliveryButton,
onDeliveryFacetChange,
getDynamicEstimateLabel,
} = useDeliveryPromise({
allFacets: facets,
selectedFilterFacets: searchState.selectedFacets,
Expand Down Expand Up @@ -90,7 +92,35 @@ function FilterDesktop({
</UIFilterFacets>
)}

{filteredFacets.map((facet, idx) => {
{highlightedFacet &&
highlightedFacet.__typename === 'StoreFacetBoolean' && (
<UIFilterFacets
key={`${testId}-${highlightedFacet.key}`}
testId={testId}
highlighted
type={highlightedFacet.__typename}
index={undefined}
>
{highlightedFacet.values.map((item) => (
<UIFilterFacetBooleanItem
key={`${testId}-${highlightedFacet.label}-${item.value}`}
id={`${testId}-${highlightedFacet.label}-${item.value}`}
testId={testId}
onFacetChange={(facet) => {
onDeliveryFacetChange({ facet })
resetInfiniteScroll(0)
}}
selected={item.selected}
value={item.value}
facetKey={highlightedFacet.key}
label={getDynamicEstimateLabel(item.value) ?? item.label}
type="toggle"
/>
))}
</UIFilterFacets>
)}

{facetsWithoutHighlightedFacet.map((facet, idx) => {
const index = shouldDisplayDeliveryButton ? idx + 1 : idx
const { __typename: type, label } = facet
const isExpanded = expanded.has(index)
Expand Down
36 changes: 34 additions & 2 deletions packages/core/src/components/search/Filter/FilterSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,13 @@ function FilterSlider({
const { deliveryPromise: deliveryPromiseSettings } = cmsData ?? {}

const {
facets: filteredFacets,
highlightedFacet,
facetsWithoutHighlightedFacet,
labelsMap,
isPickupAllEnabled,
shouldDisplayDeliveryButton,
onDeliveryFacetChange,
getDynamicEstimateLabel,
} = useDeliveryPromise({
selectedFilterFacets: selected,
allFacets: facets,
Expand Down Expand Up @@ -187,7 +189,37 @@ function FilterSlider({
</UIFilterFacets>
)}

{filteredFacets.map((facet, idx) => {
{highlightedFacet &&
highlightedFacet.__typename === 'StoreFacetBoolean' && (
<UIFilterFacets
key={`${testId}-${highlightedFacet.key}`}
testId={testId}
highlighted
type={highlightedFacet.__typename}
index={undefined}
>
{highlightedFacet.values.map((item) => (
<UIFilterFacetBooleanItem
key={`${testId}-${highlightedFacet.label}-${item.value}`}
id={`${testId}-${highlightedFacet.label}-${item.value}`}
testId={testId}
onFacetChange={(facet) => {
onDeliveryFacetChange({
facet,
filterDispatch: dispatch,
})
}}
selected={item.selected}
value={item.value}
facetKey={highlightedFacet.key}
label={getDynamicEstimateLabel(item.value) ?? item.label}
type="toggle"
/>
))}
</UIFilterFacets>
)}

{facetsWithoutHighlightedFacet.map((facet, idx) => {
const index = shouldDisplayDeliveryButton ? idx + 1 : idx
const { __typename: type, label } = facet
const isExpanded = expanded.has(index)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
@import "@faststore/ui/src/components/molecules/Modal/styles.scss";
@import "@faststore/ui/src/components/molecules/RadioField/styles.scss";
@import "@faststore/ui/src/components/molecules/SelectField/styles.scss";
@import "@faststore/ui/src/components/molecules/Toggle/styles.scss";
@import "@faststore/ui/src/components/molecules/ToggleField/styles.scss";
@import "@faststore/ui/src/components/organisms/Filter/styles.scss";
@import "@faststore/ui/src/components/organisms/FilterSlider/styles.scss";
@import "@faststore/ui/src/components/organisms/PriceRange/styles.scss";
Expand Down
Loading
Loading