mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
Refactor SelectMultipleFilter to use FilterPopup and FilterPlain
This commit is contained in:
parent
b31656791c
commit
4c6435e569
7 changed files with 125 additions and 98 deletions
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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 ? (
|
||||
<SelectMultipleFilterPlain
|
||||
<SelectMultipleFilter
|
||||
id="SearchFiltersMobile.amenitiesFilter"
|
||||
name="amenities"
|
||||
urlParam={amenitiesFilter.paramName}
|
||||
label={amenitiesLabel}
|
||||
onSelect={this.handleSelectMultiple}
|
||||
onSubmit={this.handleSelectMultiple}
|
||||
liveEdit
|
||||
options={amenitiesFilter.options}
|
||||
initialValues={initialAmenities}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -13,16 +13,16 @@
|
|||
* const initialNewFilterValues = this.initialValues(newFilter.paramName);
|
||||
*
|
||||
* const newFilterElement = newFilter ? (
|
||||
* <SelectMultipleFilterPlain
|
||||
* <SelectMultipleFilter
|
||||
* id="SearchFiltersPanel.newFilter"
|
||||
* name="newFilter"
|
||||
* urlParam={newFilter.paramName}
|
||||
* label={this.props.intl.formatMessage({ id: 'SearchFiltersPanel.newFilterLabel' })}
|
||||
* onSelect={this.handleSelectMultiple}
|
||||
* onSubmit={this.handleSelectMultiple}
|
||||
* liveEdit
|
||||
* options={multiSelectFilterXFromProps}
|
||||
* initialValues={initialNewFilterValues}
|
||||
* twoColumns
|
||||
* />
|
||||
* />
|
||||
* ) : null;
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -41,3 +41,8 @@
|
|||
border: 1px solid var(--marketplaceColorDark);
|
||||
}
|
||||
}
|
||||
|
||||
.fieldGroupPlain {
|
||||
padding-left: 20px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<SelectMultipleFilter
|
||||
id="SelectMultipleFilterExample"
|
||||
id="SelectMultipleFilterPopupExample"
|
||||
name="amenities"
|
||||
urlParam={URL_PARAM}
|
||||
label="Amenities"
|
||||
onSelect={(urlParam, values) => 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 (
|
||||
<SelectMultipleFilter
|
||||
id="SelectMultipleFilterPlainExample"
|
||||
name="amenities"
|
||||
urlParam={URL_PARAM}
|
||||
label="Amenities"
|
||||
onSubmit={(urlParam, values) => {
|
||||
handleSubmit(urlParam, values, history);
|
||||
}}
|
||||
showAsPopup={false}
|
||||
liveEdit={true}
|
||||
options={options}
|
||||
initialValues={initialValues}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export const AmenitiesFilterPlainExample = {
|
||||
component: AmenitiesFilterPlain,
|
||||
props: {},
|
||||
group: 'filters',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<div
|
||||
const handleSubmit = (urlParam, values) => {
|
||||
const usedValue = values ? values[name] : values;
|
||||
onSubmit(urlParam, usedValue);
|
||||
};
|
||||
|
||||
return showAsPopup ? (
|
||||
<FilterPopup
|
||||
className={classes}
|
||||
onBlur={this.handleBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
ref={node => {
|
||||
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}
|
||||
>
|
||||
<button className={labelStyles} onClick={() => this.toggleOpen()}>
|
||||
{buttonLabel}
|
||||
</button>
|
||||
<SelectMultipleFilterForm
|
||||
id={id}
|
||||
onSubmit={this.handleSubmit}
|
||||
initialValues={namedInitialValues}
|
||||
enableReinitialize={true}
|
||||
<FieldCheckboxGroup
|
||||
className={css.fieldGroup}
|
||||
name={name}
|
||||
onClear={this.handleClear}
|
||||
onCancel={this.handleCancel}
|
||||
id={`${id}-checkbox-group`}
|
||||
options={options}
|
||||
isOpen={this.state.isOpen}
|
||||
intl={intl}
|
||||
contentRef={node => {
|
||||
this.filterContent = node;
|
||||
}}
|
||||
style={contentStyle}
|
||||
/>
|
||||
</div>
|
||||
</FilterPopup>
|
||||
) : (
|
||||
<FilterPlain
|
||||
className={className}
|
||||
rootClassName={rootClassName}
|
||||
label={labelForPlain}
|
||||
isSelected={hasInitialValues}
|
||||
id={`${id}.plain`}
|
||||
liveEdit
|
||||
contentPlacementOffset={contentStyle}
|
||||
onSubmit={handleSubmit}
|
||||
initialValues={namedInitialValues}
|
||||
urlParam={urlParam}
|
||||
{...rest}
|
||||
>
|
||||
<FieldCheckboxGroup
|
||||
className={css.fieldGroupPlain}
|
||||
name={name}
|
||||
id={`${id}-checkbox-group`}
|
||||
options={options}
|
||||
/>
|
||||
</FilterPlain>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue