diff --git a/src/components/SearchFilters/SearchFilters.js b/src/components/SearchFilters/SearchFilters.js index 0891720c..f47b89df 100644 --- a/src/components/SearchFilters/SearchFilters.js +++ b/src/components/SearchFilters/SearchFilters.js @@ -164,7 +164,8 @@ const SearchFiltersComponent = props => { name="amenities" urlParam={amenitiesFilter.paramName} label={amenitiesLabel} - onSelect={handleSelectOptions} + onSubmit={handleSelectOptions} + showAsPopup options={amenitiesFilter.options} initialValues={initialAmenities} contentPlacementOffset={FILTER_DROPDOWN_OFFSET} diff --git a/src/components/SearchFiltersMobile/SearchFiltersMobile.js b/src/components/SearchFiltersMobile/SearchFiltersMobile.js index 1f871a0c..f5948d51 100644 --- a/src/components/SearchFiltersMobile/SearchFiltersMobile.js +++ b/src/components/SearchFiltersMobile/SearchFiltersMobile.js @@ -14,7 +14,7 @@ import { Button, PriceFilter, SelectSingleFilterPlain, - SelectMultipleFilterPlain, + SelectMultipleFilter, BookingDateRangeFilter, } from '../../components'; import { propTypes } from '../../util/types'; @@ -236,12 +236,13 @@ class SearchFiltersMobileComponent extends Component { const initialAmenities = this.initialValues(amenitiesFilter.paramName); const amenitiesFilterElement = amenitiesFilter ? ( - diff --git a/src/components/SearchFiltersPanel/SearchFiltersPanel.js b/src/components/SearchFiltersPanel/SearchFiltersPanel.js index ecbb9a67..d70dc8b6 100644 --- a/src/components/SearchFiltersPanel/SearchFiltersPanel.js +++ b/src/components/SearchFiltersPanel/SearchFiltersPanel.js @@ -13,16 +13,16 @@ * const initialNewFilterValues = this.initialValues(newFilter.paramName); * * const newFilterElement = newFilter ? ( - * + * /> * ) : null; */ diff --git a/src/components/SelectMultipleFilter/SelectMultipleFilter.css b/src/components/SelectMultipleFilter/SelectMultipleFilter.css index 67812d59..9a390f84 100644 --- a/src/components/SelectMultipleFilter/SelectMultipleFilter.css +++ b/src/components/SelectMultipleFilter/SelectMultipleFilter.css @@ -41,3 +41,8 @@ border: 1px solid var(--marketplaceColorDark); } } + +.fieldGroupPlain { + padding-left: 20px; + padding-bottom: 30px; +} diff --git a/src/components/SelectMultipleFilter/SelectMultipleFilter.example.js b/src/components/SelectMultipleFilter/SelectMultipleFilter.example.js index 84f239f2..935b6b6a 100644 --- a/src/components/SelectMultipleFilter/SelectMultipleFilter.example.js +++ b/src/components/SelectMultipleFilter/SelectMultipleFilter.example.js @@ -41,11 +41,12 @@ const options = [ ]; const handleSubmit = (urlParam, values, history) => { + console.log('Submitting values', values); const queryParams = values ? `?${stringify({ [urlParam]: values.join(',') })}` : ''; history.push(`${window.location.pathname}${queryParams}`); }; -const AmenitiesFilterComponent = withRouter(props => { +const AmenitiesFilterPopup = withRouter(props => { const { history, location } = props; const params = parse(location.search); @@ -54,11 +55,13 @@ const AmenitiesFilterComponent = withRouter(props => { return ( handleSubmit(urlParam, values, history)} + onSubmit={(urlParam, values) => handleSubmit(urlParam, values, history)} + showAsPopup={true} + liveEdit={false} options={options} initialValues={initialValues} contentPlacementOffset={-14} @@ -66,8 +69,38 @@ const AmenitiesFilterComponent = withRouter(props => { ); }); -export const AmenitiesFilter = { - component: AmenitiesFilterComponent, +export const AmenitiesFilterPopupExample = { + component: AmenitiesFilterPopup, props: {}, - group: 'misc', + group: 'filters', +}; + +const AmenitiesFilterPlain = withRouter(props => { + const { history, location } = props; + + const params = parse(location.search); + const amenities = params[URL_PARAM]; + const initialValues = !!amenities ? amenities.split(',') : []; + + return ( + { + handleSubmit(urlParam, values, history); + }} + showAsPopup={false} + liveEdit={true} + options={options} + initialValues={initialValues} + /> + ); +}); + +export const AmenitiesFilterPlainExample = { + component: AmenitiesFilterPlain, + props: {}, + group: 'filters', }; diff --git a/src/components/SelectMultipleFilter/SelectMultipleFilter.js b/src/components/SelectMultipleFilter/SelectMultipleFilter.js index 70e87fb7..3b04b988 100644 --- a/src/components/SelectMultipleFilter/SelectMultipleFilter.js +++ b/src/components/SelectMultipleFilter/SelectMultipleFilter.js @@ -2,71 +2,21 @@ import React, { Component } from 'react'; import { array, arrayOf, func, number, string } from 'prop-types'; import classNames from 'classnames'; import { injectIntl, intlShape } from 'react-intl'; +import { FieldCheckboxGroup } from '../../components'; -import { SelectMultipleFilterForm } from '../../forms'; +import { FilterPopup, FilterPlain } from '../../components'; import css from './SelectMultipleFilter.css'; -const KEY_CODE_ESCAPE = 27; - class SelectMultipleFilter extends Component { constructor(props) { super(props); - this.state = { isOpen: false }; this.filter = null; this.filterContent = null; - this.handleSubmit = this.handleSubmit.bind(this); - this.handleClear = this.handleClear.bind(this); - this.handleCancel = this.handleCancel.bind(this); - this.handleBlur = this.handleBlur.bind(this); - this.handleKeyDown = this.handleKeyDown.bind(this); - this.toggleOpen = this.toggleOpen.bind(this); this.positionStyleForContent = this.positionStyleForContent.bind(this); } - handleSubmit(values) { - const { name, onSelect, urlParam } = this.props; - const paramValues = values[name]; - this.setState({ isOpen: false }); - onSelect(urlParam, paramValues); - } - - handleClear() { - const { onSelect, urlParam } = this.props; - this.setState({ isOpen: false }); - onSelect(urlParam, null); - } - - handleCancel() { - const { onSelect, initialValues, urlParam } = this.props; - this.setState({ isOpen: false }); - onSelect(urlParam, initialValues); - } - - handleBlur(event) { - // FocusEvent is fired faster than the link elements native click handler - // gets its own event. Therefore, we need to check the origin of this FocusEvent. - if (!this.filter.contains(event.relatedTarget)) { - this.setState({ isOpen: false }); - } - } - - handleKeyDown(e) { - // Gather all escape presses to close menu - if (e.keyCode === KEY_CODE_ESCAPE) { - this.toggleOpen(false); - } - } - - toggleOpen(enforcedState) { - if (enforcedState) { - this.setState({ isOpen: enforcedState }); - } else { - this.setState(prevState => ({ isOpen: !prevState.isOpen })); - } - } - positionStyleForContent() { if (this.filter && this.filterContent) { // Render the filter content to the right from the menu @@ -91,54 +41,94 @@ class SelectMultipleFilter extends Component { } render() { - const { rootClassName, className, id, name, label, options, initialValues, intl } = this.props; + const { + rootClassName, + className, + id, + name, + label, + options, + initialValues, + contentPlacementOffset, + onSubmit, + urlParam, + intl, + showAsPopup, + ...rest + } = this.props; + const classes = classNames(rootClassName || css.root, className); const hasInitialValues = initialValues.length > 0; - const labelStyles = hasInitialValues ? css.labelSelected : css.label; - - const buttonLabel = hasInitialValues + const labelForPopup = hasInitialValues ? intl.formatMessage( { id: 'SelectMultipleFilter.labelSelected' }, { labelText: label, count: initialValues.length } ) : label; + const labelForPlain = hasInitialValues + ? intl.formatMessage( + { id: 'SelectMultipleFilterPlainForm.labelSelected' }, + { labelText: label, count: initialValues.length } + ) + : label; + const contentStyle = this.positionStyleForContent(); // pass the initial values with the name key so that // they can be passed to the correct field const namedInitialValues = { [name]: initialValues }; - return ( -
{ + const usedValue = values ? values[name] : values; + onSubmit(urlParam, usedValue); + }; + + return showAsPopup ? ( + { - this.filter = node; - }} + rootClassName={rootClassName} + popupClassName={css.popupSize} + name={name} + label={labelForPopup} + isSelected={hasInitialValues} + id={`${id}.popup`} + showAsPopup + contentPlacementOffset={contentPlacementOffset} + onSubmit={handleSubmit} + initialValues={namedInitialValues} + urlParam={urlParam} + {...rest} > - - { - this.filterContent = node; - }} - style={contentStyle} /> -
+ + ) : ( + + + ); } } @@ -157,7 +147,7 @@ SelectMultipleFilter.propTypes = { name: string.isRequired, urlParam: string.isRequired, label: string.isRequired, - onSelect: func.isRequired, + onSubmit: func.isRequired, options: array.isRequired, initialValues: arrayOf(string), contentPlacementOffset: number, diff --git a/src/translations/en.json b/src/translations/en.json index f0d3c3a7..d2d15955 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -689,9 +689,6 @@ "SectionLocations.listingsInLocation": "Saunas in {location}", "SectionLocations.title": "Explore exotic locations in Finland", "SelectMultipleFilter.labelSelected": "{labelText} • {count}", - "SelectMultipleFilterForm.cancel": "Cancel", - "SelectMultipleFilterForm.clear": "Clear", - "SelectMultipleFilterForm.submit": "Apply", "SelectMultipleFilterPlainForm.clear": "Clear", "SelectMultipleFilterPlainForm.labelSelected": "{labelText} • {count}", "SelectSingleFilter.clear": "Clear",