mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 05:00:43 +10:00
Merge pull request #698 from sharetribe/mobile-features-filter
Filter search results by listing features
This commit is contained in:
commit
8237cae379
14 changed files with 229 additions and 216 deletions
|
|
@ -12,7 +12,7 @@ import { createResourceLocatorString } from '../../util/routes';
|
|||
import css from './SearchFilters.css';
|
||||
|
||||
const CATEGORY_URL_PARAM = 'pub_category';
|
||||
const AMENITIES_URL_PARAM = 'pub_amenities';
|
||||
const FEATURES_URL_PARAM = 'pub_amenities';
|
||||
|
||||
// Dropdown container can have a positional offset (in pixels)
|
||||
const FILTER_DROPDOWN_OFFSET = -14;
|
||||
|
|
@ -49,8 +49,8 @@ const SearchFiltersComponent = props => {
|
|||
id: 'SearchFilters.featuresLabel',
|
||||
});
|
||||
|
||||
const initialFeatures = !!urlQueryParams[AMENITIES_URL_PARAM]
|
||||
? urlQueryParams[AMENITIES_URL_PARAM].split(',')
|
||||
const initialFeatures = !!urlQueryParams[FEATURES_URL_PARAM]
|
||||
? urlQueryParams[FEATURES_URL_PARAM].split(',')
|
||||
: [];
|
||||
|
||||
const initialCategory = urlQueryParams[CATEGORY_URL_PARAM];
|
||||
|
|
@ -58,8 +58,8 @@ const SearchFiltersComponent = props => {
|
|||
const handleSelectOptions = (urlParam, options) => {
|
||||
const queryParams =
|
||||
options && options.length > 0
|
||||
? { ...urlQueryParams, [AMENITIES_URL_PARAM]: options.join(',') }
|
||||
: omit(urlQueryParams, AMENITIES_URL_PARAM);
|
||||
? { ...urlQueryParams, [FEATURES_URL_PARAM]: options.join(',') }
|
||||
: omit(urlQueryParams, FEATURES_URL_PARAM);
|
||||
|
||||
history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams));
|
||||
};
|
||||
|
|
@ -88,7 +88,7 @@ const SearchFiltersComponent = props => {
|
|||
const featuresFilter = features ? (
|
||||
<SelectMultipleFilter
|
||||
name="amenities"
|
||||
urlParam={AMENITIES_URL_PARAM}
|
||||
urlParam={FEATURES_URL_PARAM}
|
||||
label={featuresLabel}
|
||||
onSelect={handleSelectOptions}
|
||||
options={features}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@
|
|||
.modalHeadingWrapper {
|
||||
padding-bottom: 31px;
|
||||
border-bottom: 1px solid var(--matterColorNegative);
|
||||
margin-bottom: 27px;
|
||||
}
|
||||
|
||||
.modalHeading {
|
||||
|
|
@ -95,6 +94,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
.filtersWrapper {
|
||||
/* add bottom margin so that the last filter won't be hidden
|
||||
* under the bottom bar */
|
||||
margin-bottom: 160px;
|
||||
}
|
||||
|
||||
.showListingsContainer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
|
|
|
|||
|
|
@ -7,11 +7,18 @@ import { omit, toPairs } from 'lodash';
|
|||
|
||||
import routeConfiguration from '../../routeConfiguration';
|
||||
import { createResourceLocatorString } from '../../util/routes';
|
||||
import { SecondaryButton, ModalInMobile, Button, SelectSingleFilterMobile } from '../../components';
|
||||
import {
|
||||
SecondaryButton,
|
||||
ModalInMobile,
|
||||
Button,
|
||||
SelectSingleFilterMobile,
|
||||
SelectMultipleFilterMobile,
|
||||
} from '../../components';
|
||||
import css from './SearchFiltersMobile.css';
|
||||
|
||||
const CATEGORY_URL_PARAM = 'pub_category';
|
||||
const allowedCategories = [CATEGORY_URL_PARAM];
|
||||
const FEATURES_URL_PARAM = 'pub_amenities';
|
||||
const allowedCategories = [CATEGORY_URL_PARAM, FEATURES_URL_PARAM];
|
||||
|
||||
const validateParamValue = value => value !== null && value !== undefined && value.length > 0;
|
||||
const validateParamKey = key => allowedCategories.includes(key);
|
||||
|
|
@ -33,7 +40,8 @@ class SearchFiltersMobileComponent extends Component {
|
|||
this.cancelFilters = this.cancelFilters.bind(this);
|
||||
this.closeFilters = this.closeFilters.bind(this);
|
||||
this.resetAll = this.resetAll.bind(this);
|
||||
this.onSelectSingle = this.onSelectSingle.bind(this);
|
||||
this.handleSelectSingle = this.handleSelectSingle.bind(this);
|
||||
this.handleSelectMultiple = this.handleSelectMultiple.bind(this);
|
||||
}
|
||||
|
||||
// Open filters modal, set the initial parameters to current ones
|
||||
|
|
@ -65,7 +73,7 @@ class SearchFiltersMobileComponent extends Component {
|
|||
this.setState({ isFiltersOpenOnMobile: false });
|
||||
}
|
||||
|
||||
onSelectSingle(urlParam, option) {
|
||||
handleSelectSingle(urlParam, option) {
|
||||
const { urlQueryParams, history } = this.props;
|
||||
|
||||
// query parameters after selecting the option
|
||||
|
|
@ -77,11 +85,22 @@ class SearchFiltersMobileComponent extends Component {
|
|||
history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams));
|
||||
}
|
||||
|
||||
handleSelectMultiple(urlParam, options) {
|
||||
const { urlQueryParams, history } = this.props;
|
||||
|
||||
const queryParams =
|
||||
options && options.length > 0
|
||||
? { ...urlQueryParams, [FEATURES_URL_PARAM]: options.join(',') }
|
||||
: omit(urlQueryParams, FEATURES_URL_PARAM);
|
||||
|
||||
history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams));
|
||||
}
|
||||
|
||||
// Reset all filter query parameters
|
||||
resetAll(e) {
|
||||
const { urlQueryParams, history } = this.props;
|
||||
|
||||
const queryParams = omit(urlQueryParams, CATEGORY_URL_PARAM);
|
||||
const queryParams = omit(urlQueryParams, [CATEGORY_URL_PARAM, FEATURES_URL_PARAM]);
|
||||
history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams));
|
||||
|
||||
// blur event target if event is passed
|
||||
|
|
@ -102,6 +121,7 @@ class SearchFiltersMobileComponent extends Component {
|
|||
onMapIconClick,
|
||||
onManageDisableScrolling,
|
||||
categories,
|
||||
features,
|
||||
intl,
|
||||
} = this.props;
|
||||
|
||||
|
|
@ -139,13 +159,30 @@ class SearchFiltersMobileComponent extends Component {
|
|||
<SelectSingleFilterMobile
|
||||
urlParam={CATEGORY_URL_PARAM}
|
||||
label={categoryLabel}
|
||||
onSelect={this.onSelectSingle}
|
||||
onSelect={this.handleSelectSingle}
|
||||
options={categories}
|
||||
initialValue={initialCategory}
|
||||
intl={intl}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
const featuresLabel = intl.formatMessage({ id: 'SearchFiltersMobile.featuresLabel' });
|
||||
|
||||
const initialFeatures = !!urlQueryParams[FEATURES_URL_PARAM]
|
||||
? urlQueryParams[FEATURES_URL_PARAM].split(',')
|
||||
: [];
|
||||
|
||||
const featuresFilter = features ? (
|
||||
<SelectMultipleFilterMobile
|
||||
name="amenities"
|
||||
urlParam={FEATURES_URL_PARAM}
|
||||
label={featuresLabel}
|
||||
onSelect={this.handleSelectMultiple}
|
||||
options={features}
|
||||
initialValues={initialFeatures}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={css.searchResultSummary}>
|
||||
|
|
@ -174,7 +211,10 @@ class SearchFiltersMobileComponent extends Component {
|
|||
<FormattedMessage id={'SearchFiltersMobile.resetAll'} />
|
||||
</button>
|
||||
</div>
|
||||
{categoryFilter}
|
||||
<div className={css.filtersWrapper}>
|
||||
{categoryFilter}
|
||||
{featuresFilter}
|
||||
</div>
|
||||
<div className={css.showListingsContainer}>
|
||||
<Button className={css.showListingsButton} onClick={this.closeFilters}>
|
||||
{showListingsLabel}
|
||||
|
|
@ -193,6 +233,8 @@ SearchFiltersMobileComponent.defaultProps = {
|
|||
searchingInProgress: false,
|
||||
onOpenModal: null,
|
||||
onCloseModal: null,
|
||||
categories: null,
|
||||
features: null,
|
||||
};
|
||||
|
||||
SearchFiltersMobileComponent.propTypes = {
|
||||
|
|
@ -208,6 +250,7 @@ SearchFiltersMobileComponent.propTypes = {
|
|||
onOpenModal: func,
|
||||
onCloseModal: func,
|
||||
categories: array,
|
||||
features: array,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ class SelectMultipleFilter extends Component {
|
|||
{buttonLabel}
|
||||
</button>
|
||||
<SelectMultipleFilterForm
|
||||
form={`SelectMultipleFilterForm.${name}`}
|
||||
onSubmit={this.handleSubmit}
|
||||
initialValues={namedInitialValues}
|
||||
enableReinitialize={true}
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ SelectMultipleFilterFormComponent.propTypes = {
|
|||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const defaultFormName = 'SelectMultipleFilterForm';
|
||||
|
||||
export default compose(reduxForm({ form: defaultFormName }), injectIntl)(
|
||||
const SelectMultipleFilterForm = compose(reduxForm({}), injectIntl)(
|
||||
SelectMultipleFilterFormComponent
|
||||
);
|
||||
|
||||
export default SelectMultipleFilterForm;
|
||||
|
|
|
|||
|
|
@ -2,5 +2,60 @@
|
|||
|
||||
.root {
|
||||
padding-bottom: 16px;
|
||||
margin-top: 30px;
|
||||
border-bottom: 1px solid var(--matterColorNegative);
|
||||
}
|
||||
|
||||
.filterLabel,
|
||||
.filterLabelSelected {
|
||||
@apply --marketplaceH3FontStyles;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.filterLabel {
|
||||
color: var(--matterColorDark);
|
||||
}
|
||||
|
||||
.filterLabelSelected {
|
||||
color: var(--marketplaceColor);
|
||||
}
|
||||
|
||||
.labelButton {
|
||||
/* Override button styles */
|
||||
outline: none;
|
||||
text-align: left;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.optionsContainerOpen {
|
||||
padding-left: 20px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.optionsContainerClosed {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.clearButton {
|
||||
@apply --marketplaceH5FontStyles;
|
||||
font-weight: var(--fontWeightMedium);
|
||||
color: var(--matterColorAnti);
|
||||
|
||||
/* Layout */
|
||||
display: inline;
|
||||
float: right;
|
||||
margin-top: 6px;
|
||||
padding: 0;
|
||||
|
||||
/* Override button styles */
|
||||
outline: none;
|
||||
text-align: left;
|
||||
border: none;
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: var(--matterColor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,73 +1,105 @@
|
|||
import React from 'react';
|
||||
import { array, string, arrayOf, func, shape } from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { array, string, func } from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
||||
|
||||
import SelectMultipleFilterMobileForm from './SelectMultipleFilterMobileForm';
|
||||
import { arrayToFormValues, formValuesToArray } from '../../util/data';
|
||||
|
||||
import css from './SelectMultipleFilterMobile.css';
|
||||
|
||||
const SelectMultipleFilterMobile = props => {
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
name,
|
||||
urlParam,
|
||||
label,
|
||||
onSelect,
|
||||
options,
|
||||
initialValues,
|
||||
} = props;
|
||||
class SelectMultipleFilterMobileComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { isOpen: true };
|
||||
|
||||
const handleSelect = values => {
|
||||
this.handleSelect = this.handleSelect.bind(this);
|
||||
this.handleClear = this.handleClear.bind(this);
|
||||
this.toggleIsOpen = this.toggleIsOpen.bind(this);
|
||||
}
|
||||
|
||||
handleSelect(values) {
|
||||
const { urlParam, name, onSelect } = this.props;
|
||||
const selectedKeys = formValuesToArray(values[name]);
|
||||
onSelect(urlParam, selectedKeys);
|
||||
};
|
||||
}
|
||||
|
||||
const handleClear = () => {
|
||||
handleClear() {
|
||||
const { urlParam, onSelect } = this.props;
|
||||
onSelect(urlParam, null);
|
||||
};
|
||||
}
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
toggleIsOpen() {
|
||||
this.setState(prevState => ({ isOpen: !prevState.isOpen }));
|
||||
}
|
||||
|
||||
const initialValuesObj = arrayToFormValues(initialValues);
|
||||
const namedInitialValues = { [name]: initialValuesObj };
|
||||
render() {
|
||||
const { rootClassName, className, name, label, options, initialValues, intl } = this.props;
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<SelectMultipleFilterMobileForm
|
||||
name={name}
|
||||
label={label}
|
||||
options={options}
|
||||
initialValues={namedInitialValues}
|
||||
initialValuesCount={initialValues.length}
|
||||
onChange={handleSelect}
|
||||
onClear={handleClear}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
SelectMultipleFilterMobile.defaultProps = {
|
||||
const hasInitialValues = initialValues.length > 0;
|
||||
const labelClass = hasInitialValues ? css.filterLabelSelected : css.filterLabel;
|
||||
|
||||
const labelText = hasInitialValues
|
||||
? intl.formatMessage(
|
||||
{ id: 'SelectMultipleFilterMobileForm.labelSelected' },
|
||||
{ labelText: label, count: initialValues.length }
|
||||
)
|
||||
: label;
|
||||
|
||||
const optionsContainerClass = this.state.isOpen
|
||||
? css.optionsContainerOpen
|
||||
: css.optionsContainerClosed;
|
||||
|
||||
const initialValuesObj = arrayToFormValues(initialValues);
|
||||
const namedInitialValues = { [name]: initialValuesObj };
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={labelClass}>
|
||||
<button type="button" className={css.labelButton} onClick={this.toggleIsOpen}>
|
||||
<span className={labelClass}>{labelText}</span>
|
||||
</button>
|
||||
<button type="button" className={css.clearButton} onClick={this.handleClear}>
|
||||
<FormattedMessage id={'SelectMultipleFilterMobileForm.clear'} />
|
||||
</button>
|
||||
</div>
|
||||
<SelectMultipleFilterMobileForm
|
||||
form={`SelectMultipleFilterMobileForm.${name}`}
|
||||
className={optionsContainerClass}
|
||||
name={name}
|
||||
options={options}
|
||||
initialValues={namedInitialValues}
|
||||
onChange={this.handleSelect}
|
||||
enableReinitialize={true}
|
||||
keepDirtyOnReinitialize={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SelectMultipleFilterMobileComponent.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
initialValues: [],
|
||||
};
|
||||
|
||||
SelectMultipleFilterMobile.propTypes = {
|
||||
SelectMultipleFilterMobileComponent.propTypes = {
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
name: string.isRequired,
|
||||
urlParam: string.isRequired,
|
||||
label: string.isRequired,
|
||||
onSelect: func.isRequired,
|
||||
options: arrayOf(
|
||||
shape({
|
||||
key: string.isRequired,
|
||||
label: string.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
options: array.isRequired,
|
||||
initialValues: array,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const SelectMultipleFilterMobile = injectIntl(SelectMultipleFilterMobileComponent);
|
||||
|
||||
export default SelectMultipleFilterMobile;
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
}
|
||||
|
||||
.filterLabel,
|
||||
.filterLabelSelected {
|
||||
@apply --marketplaceH3FontStyles;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.filterLabel {
|
||||
color: var(--matterColorDark);
|
||||
}
|
||||
|
||||
.filterLabelSelected {
|
||||
color: var(--marketplaceColor);
|
||||
}
|
||||
|
||||
.labelButton {
|
||||
/* Override button styles */
|
||||
outline: none;
|
||||
text-align: left;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.optionsContainerOpen {
|
||||
padding-left: 20px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.optionsContainerClosed {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.clearButton {
|
||||
@apply --marketplaceH5FontStyles;
|
||||
font-weight: var(--fontWeightMedium);
|
||||
color: var(--matterColorAnti);
|
||||
|
||||
/* Layout */
|
||||
display: inline;
|
||||
float: right;
|
||||
margin-top: 6px;
|
||||
padding: 0;
|
||||
|
||||
/* Override button styles */
|
||||
outline: none;
|
||||
text-align: left;
|
||||
border: none;
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: var(--matterColor);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,92 +1,35 @@
|
|||
import React, { Component } from 'react';
|
||||
import { arrayOf, func, node, number, shape, string } from 'prop-types';
|
||||
import { compose } from 'redux';
|
||||
import React from 'react';
|
||||
import { arrayOf, shape, string, node } from 'prop-types';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
||||
|
||||
import { FieldGroupCheckbox, Form } from '../../components';
|
||||
import css from './SelectMultipleFilterMobileForm.css';
|
||||
|
||||
class SelectMultipleFilterMobileFormComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { isOpen: true };
|
||||
const SelectMultipleFilterMobileFormComponent = props => {
|
||||
const { form, className, name, options } = props;
|
||||
|
||||
this.handleClear = this.handleClear.bind(this);
|
||||
this.toggleIsOpen = this.toggleIsOpen.bind(this);
|
||||
}
|
||||
|
||||
handleClear() {
|
||||
const { destroy, onClear } = this.props;
|
||||
// destroy redux form state so that initial values passed
|
||||
// to the form are also cleared
|
||||
destroy();
|
||||
onClear();
|
||||
}
|
||||
|
||||
toggleIsOpen() {
|
||||
this.setState(prevState => ({ isOpen: !prevState.isOpen }));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { form, name, label, options, initialValuesCount, intl } = this.props;
|
||||
|
||||
const hasInitialValues = initialValuesCount > 0;
|
||||
const labelClass = hasInitialValues ? css.filterLabelSelected : css.filterLabel;
|
||||
|
||||
const labelText = hasInitialValues
|
||||
? intl.formatMessage(
|
||||
{ id: 'SelectMultipleFilterMobileForm.labelSelected' },
|
||||
{ labelText: label, count: initialValuesCount }
|
||||
)
|
||||
: label;
|
||||
|
||||
const optionsContainerClass = this.state.isOpen
|
||||
? css.optionsContainerOpen
|
||||
: css.optionsContainerClosed;
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<div className={labelClass}>
|
||||
<button type="button" className={css.labelButton} onClick={this.toggleIsOpen}>
|
||||
<span className={labelClass}>{labelText}</span>
|
||||
</button>
|
||||
<button type="button" className={css.clearButton} onClick={this.handleClear}>
|
||||
<FormattedMessage id={'SelectMultipleFilterMobileForm.clear'} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className={optionsContainerClass}>
|
||||
<FieldGroupCheckbox name={name} id={`${form}.${name}`} options={options} />
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Form className={className}>
|
||||
<FieldGroupCheckbox name={name} id={`${form}.${name}`} options={options} />
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
SelectMultipleFilterMobileFormComponent.defaultProps = {
|
||||
initialValuesCount: 0,
|
||||
className: null,
|
||||
};
|
||||
|
||||
SelectMultipleFilterMobileFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
className: string,
|
||||
name: string.isRequired,
|
||||
label: string.isRequired,
|
||||
onClear: func.isRequired,
|
||||
options: arrayOf(
|
||||
shape({
|
||||
key: string.isRequired,
|
||||
label: node.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
initialValuesCount: number,
|
||||
|
||||
// form injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const defaultFormName = 'SelectMultipleFilterMobileForm';
|
||||
const SelectMultipleFilterMobileForm = reduxForm({})(SelectMultipleFilterMobileFormComponent);
|
||||
|
||||
export default compose(reduxForm({ form: defaultFormName }), injectIntl)(
|
||||
SelectMultipleFilterMobileFormComponent
|
||||
);
|
||||
export default SelectMultipleFilterMobileForm;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
.root {
|
||||
padding-bottom: 16px;
|
||||
margin-top: 30px;
|
||||
border-bottom: 1px solid var(--matterColorNegative);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@ export class SearchPageComponent extends Component {
|
|||
onOpenModal={this.onOpenMobileModal}
|
||||
onCloseModal={this.onCloseMobileModal}
|
||||
categories={categories}
|
||||
features={features}
|
||||
/>
|
||||
<div
|
||||
className={classNames(css.listings, {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ describe('SearchPageComponent', () => {
|
|||
sendVerificationEmailInProgress: false,
|
||||
onResendVerificationEmail: noop,
|
||||
categories: [{ key: 'cat1', label: 'Cat 1' }, { key: 'cat2', label: 'Cat 2' }],
|
||||
features: [{ key: 'dog1', label: 'Dog 1' }, { key: 'dog2', label: 'Dog 2' }],
|
||||
};
|
||||
const tree = renderShallow(<SearchPageComponent {...props} />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
|
|
|
|||
|
|
@ -36,36 +36,12 @@ exports[`SearchPageComponent matches snapshot 1`] = `
|
|||
features={
|
||||
Array [
|
||||
Object {
|
||||
"key": "towels",
|
||||
"label": "Towels",
|
||||
"key": "dog1",
|
||||
"label": "Dog 1",
|
||||
},
|
||||
Object {
|
||||
"key": "bathroom",
|
||||
"label": "Bathroom",
|
||||
},
|
||||
Object {
|
||||
"key": "swimming_pool",
|
||||
"label": "Swimming pool",
|
||||
},
|
||||
Object {
|
||||
"key": "own_drinks",
|
||||
"label": "Own drinks allowed",
|
||||
},
|
||||
Object {
|
||||
"key": "jacuzzi",
|
||||
"label": "Jacuzzi",
|
||||
},
|
||||
Object {
|
||||
"key": "audiovisual_entertainment",
|
||||
"label": "Audiovisual entertainment",
|
||||
},
|
||||
Object {
|
||||
"key": "barbeque",
|
||||
"label": "Barbeque",
|
||||
},
|
||||
Object {
|
||||
"key": "own_food_allowed",
|
||||
"label": "Own food allowed",
|
||||
"key": "dog2",
|
||||
"label": "Dog 2",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
@ -98,6 +74,18 @@ exports[`SearchPageComponent matches snapshot 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
features={
|
||||
Array [
|
||||
Object {
|
||||
"key": "dog1",
|
||||
"label": "Dog 1",
|
||||
},
|
||||
Object {
|
||||
"key": "dog2",
|
||||
"label": "Dog 2",
|
||||
},
|
||||
]
|
||||
}
|
||||
listingsAreLoaded={true}
|
||||
onCloseModal={[Function]}
|
||||
onManageDisableScrolling={[Function]}
|
||||
|
|
|
|||
|
|
@ -494,6 +494,7 @@
|
|||
"SearchFilters.openMapView": "Map",
|
||||
"SearchFiltersMobile.cancel": "CANCEL",
|
||||
"SearchFiltersMobile.categoryLabel": "Category",
|
||||
"SearchFiltersMobile.featuresLabel": "Amenities",
|
||||
"SearchFiltersMobile.heading": "Filter saunas",
|
||||
"SearchFiltersMobile.resetAll": "Reset all",
|
||||
"SearchFiltersMobile.showListings": "Show {count, number} {count, plural, one {sauna} other {saunas}}",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue