Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize default search filters #1275

Merged
merged 7 commits into from
Mar 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ way to update this template, but currently, we follow a pattern:

## Upcoming version 2020-XX-XX

- [change] Move category and amenities search filters from primary filters to secondary filters. [#1275](https://github.com/sharetribe/ftw-daily/pull/1275)

## [v4.3.0] 2020-03-16

- [change] Redirect user back to Stripe during Connect Onboarding Flow when user is returned to
Expand Down
82 changes: 1 addition & 81 deletions src/components/SearchFilters/SearchFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import omit from 'lodash/omit';

import {
BookingDateRangeFilter,
SelectSingleFilter,
SelectMultipleFilter,
PriceFilter,
KeywordFilter,
} from '../../components';
import { BookingDateRangeFilter, PriceFilter, KeywordFilter } from '../../components';
import routeConfiguration from '../../routeConfiguration';
import { parseDateFromISO8601, stringifyDateToISO8601 } from '../../util/dates';
import { createResourceLocatorString } from '../../util/routes';
Expand All @@ -28,11 +22,6 @@ const initialValue = (queryParams, paramName) => {
return queryParams[paramName];
};

// resolve initial values for a multi value filter
const initialValues = (queryParams, paramName) => {
return !!queryParams[paramName] ? queryParams[paramName].split(',') : [];
};

const initialPriceRangeValue = (queryParams, paramName) => {
const price = queryParams[paramName];
const valuesFromParams = !!price ? price.split(',').map(v => Number.parseInt(v, RADIX)) : [];
Expand Down Expand Up @@ -67,8 +56,6 @@ const SearchFiltersComponent = props => {
listingsAreLoaded,
resultsCount,
searchInProgress,
categoryFilter,
amenitiesFilter,
priceFilter,
dateRangeFilter,
keywordFilter,
Expand All @@ -82,26 +69,10 @@ const SearchFiltersComponent = props => {
const hasNoResult = listingsAreLoaded && resultsCount === 0;
const classes = classNames(rootClassName || css.root, { [css.longInfo]: hasNoResult }, className);

const categoryLabel = intl.formatMessage({
id: 'SearchFilters.categoryLabel',
});

const amenitiesLabel = intl.formatMessage({
id: 'SearchFilters.amenitiesLabel',
});

const keywordLabel = intl.formatMessage({
id: 'SearchFilters.keywordLabel',
});

const initialAmenities = amenitiesFilter
? initialValues(urlQueryParams, amenitiesFilter.paramName)
: null;

const initialCategory = categoryFilter
? initialValue(urlQueryParams, categoryFilter.paramName)
: null;

const initialPriceRange = priceFilter
? initialPriceRangeValue(urlQueryParams, priceFilter.paramName)
: null;
Expand All @@ -114,25 +85,6 @@ const SearchFiltersComponent = props => {
? initialValue(urlQueryParams, keywordFilter.paramName)
: null;

const handleSelectOptions = (urlParam, options) => {
const queryParams =
options && options.length > 0
? { ...urlQueryParams, [urlParam]: options.join(',') }
: omit(urlQueryParams, urlParam);

history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams));
};

const handleSelectOption = (urlParam, option) => {
// query parameters after selecting the option
// if no option is passed, clear the selection for the filter
const queryParams = option
? { ...urlQueryParams, [urlParam]: option }
: omit(urlQueryParams, urlParam);

history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams));
};

const handlePrice = (urlParam, range) => {
const { minPrice, maxPrice } = range || {};
const queryParams =
Expand Down Expand Up @@ -165,32 +117,6 @@ const SearchFiltersComponent = props => {
history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams));
};

const categoryFilterElement = categoryFilter ? (
<SelectSingleFilter
urlParam={categoryFilter.paramName}
label={categoryLabel}
onSelect={handleSelectOption}
showAsPopup
options={categoryFilter.options}
initialValue={initialCategory}
contentPlacementOffset={FILTER_DROPDOWN_OFFSET}
/>
) : null;

const amenitiesFilterElement = amenitiesFilter ? (
<SelectMultipleFilter
id={'SearchFilters.amenitiesFilter'}
name="amenities"
urlParam={amenitiesFilter.paramName}
label={amenitiesLabel}
onSubmit={handleSelectOptions}
showAsPopup
options={amenitiesFilter.options}
initialValues={initialAmenities}
contentPlacementOffset={FILTER_DROPDOWN_OFFSET}
/>
) : null;

const priceFilterElement = priceFilter ? (
<PriceFilter
id="SearchFilters.priceFilter"
Expand Down Expand Up @@ -249,8 +175,6 @@ const SearchFiltersComponent = props => {
return (
<div className={classes}>
<div className={css.filters}>
{categoryFilterElement}
{amenitiesFilterElement}
{priceFilterElement}
{dateRangeFilterElement}
{keywordFilterElement}
Expand Down Expand Up @@ -285,8 +209,6 @@ SearchFiltersComponent.defaultProps = {
className: null,
resultsCount: null,
searchingInProgress: false,
categoryFilter: null,
amenitiesFilter: null,
priceFilter: null,
dateRangeFilter: null,
isSearchFiltersPanelOpen: false,
Expand All @@ -302,8 +224,6 @@ SearchFiltersComponent.propTypes = {
resultsCount: number,
searchingInProgress: bool,
onManageDisableScrolling: func.isRequired,
categoriesFilter: propTypes.filterConfig,
amenitiesFilter: propTypes.filterConfig,
priceFilter: propTypes.filterConfig,
dateRangeFilter: propTypes.filterConfig,
isSearchFiltersPanelOpen: bool,
Expand Down
51 changes: 47 additions & 4 deletions src/components/SearchFiltersPanel/SearchFiltersPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ import omit from 'lodash/omit';

import routeConfiguration from '../../routeConfiguration';
import { createResourceLocatorString } from '../../util/routes';
import { InlineTextButton } from '../../components';
import { SelectSingleFilter, SelectMultipleFilter, InlineTextButton } from '../../components';
import css from './SearchFiltersPanel.css';

// Dropdown container can have a positional offset (in pixels)
const FILTER_DROPDOWN_OFFSET = -14;

class SearchFiltersPanelComponent extends Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -101,7 +104,7 @@ class SearchFiltersPanelComponent extends Component {
// if no option is passed, clear the selection for the filter
const currentQueryParams = option
? { ...mergedQueryParams, [urlParam]: option }
: omit(mergedQueryParams, urlParam);
: { ...mergedQueryParams, [urlParam]: null };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't remove omit. (I assume that this will add URL parameter category=null&amenities=null)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, this was a bug fix. Clearing the filter didn't work without this. It removes the param from the URL correctly.


return { currentQueryParams };
});
Expand Down Expand Up @@ -151,12 +154,52 @@ class SearchFiltersPanelComponent extends Component {
}

render() {
const { rootClassName, className } = this.props;
const { rootClassName, className, intl, categoryFilter, amenitiesFilter } = this.props;
const classes = classNames(rootClassName || css.root, className);

const initialCategory = this.initialValue(categoryFilter.paramName);
const initialAmenities = this.initialValues(amenitiesFilter.paramName);

const categoryLabel = intl.formatMessage({
id: 'SearchFiltersPanel.categoryLabel',
});

const amenitiesLabel = intl.formatMessage({
id: 'SearchFiltersPanel.amenitiesLabel',
});

const categoryFilterElement = categoryFilter ? (
<SelectSingleFilter
urlParam={categoryFilter.paramName}
label={categoryLabel}
onSelect={this.handleSelectSingle}
liveEdit
options={categoryFilter.options}
initialValue={initialCategory}
contentPlacementOffset={FILTER_DROPDOWN_OFFSET}
/>
) : null;

const amenitiesFilterElement = amenitiesFilter ? (
<SelectMultipleFilter
id={'SearchFiltersPanel.amenitiesFilter'}
name="amenities"
urlParam={amenitiesFilter.paramName}
label={amenitiesLabel}
onSubmit={this.handleSelectMultiple}
liveEdit
options={amenitiesFilter.options}
initialValues={initialAmenities}
contentPlacementOffset={FILTER_DROPDOWN_OFFSET}
/>
) : null;

return (
<div className={classes}>
<div className={css.filtersWrapper}>{/* Add filters here */}</div>
<div className={css.filtersWrapper}>
{categoryFilterElement}
{amenitiesFilterElement}
</div>
<div className={css.footer}>
<InlineTextButton rootClassName={css.resetAllButton} onClick={this.resetAll}>
<FormattedMessage id={'SearchFiltersPanel.resetAll'} />
Expand Down
2 changes: 1 addition & 1 deletion src/containers/SearchPage/MainPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class MainPanel extends Component {

const isSearchFiltersPanelOpen = !!secondaryFilters && this.state.isSearchFiltersPanelOpen;

const filters = merge(primaryFilters, secondaryFilters);
const filters = merge({}, primaryFilters, secondaryFilters);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

const selectedFilters = validFilterParams(urlQueryParams, filters);
const selectedFiltersCount = Object.keys(selectedFilters).length;

Expand Down
6 changes: 4 additions & 2 deletions src/containers/SearchPage/SearchPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,12 +226,14 @@ export class SearchPageComponent extends Component {
searchParamsForPagination={parse(location.search)}
showAsModalMaxWidth={MODAL_BREAKPOINT}
primaryFilters={{
categoryFilter: filters.categoryFilter,
amenitiesFilter: filters.amenitiesFilter,
priceFilter: filters.priceFilter,
dateRangeFilter: filters.dateRangeFilter,
keywordFilter: filters.keywordFilter,
}}
secondaryFilters={{
categoryFilter: filters.categoryFilter,
amenitiesFilter: filters.amenitiesFilter,
}}
/>
<ModalInMobile
className={css.mapPanel}
Expand Down
57 changes: 30 additions & 27 deletions src/containers/SearchPage/__snapshots__/SearchPage.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -40,32 +40,6 @@ exports[`SearchPageComponent matches snapshot 1`] = `
}
primaryFilters={
Object {
"amenitiesFilter": Object {
"options": Array [
Object {
"key": "dog1",
"label": "Dog 1",
},
Object {
"key": "dog2",
"label": "Dog 2",
},
],
"paramName": "pub_amenities",
},
"categoryFilter": Object {
"options": Array [
Object {
"key": "cat1",
"label": "Cat 1",
},
Object {
"key": "cat2",
"label": "Cat 2",
},
],
"paramName": "pub_category",
},
"dateRangeFilter": Object {
"config": Object {
"active": true,
Expand Down Expand Up @@ -94,7 +68,36 @@ exports[`SearchPageComponent matches snapshot 1`] = `
searchListingsError={null}
searchParamsAreInSync={true}
searchParamsForPagination={Object {}}
secondaryFilters={null}
secondaryFilters={
Object {
"amenitiesFilter": Object {
"options": Array [
Object {
"key": "dog1",
"label": "Dog 1",
},
Object {
"key": "dog2",
"label": "Dog 2",
},
],
"paramName": "pub_amenities",
},
"categoryFilter": Object {
"options": Array [
Object {
"key": "cat1",
"label": "Cat 1",
},
Object {
"key": "cat2",
"label": "Cat 2",
},
],
"paramName": "pub_category",
},
}
}
showAsModalMaxWidth={768}
urlQueryParams={Object {}}
/>
Expand Down
4 changes: 2 additions & 2 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -696,8 +696,6 @@
"SavedCardDetails.replaceCardTitle": "Use another payment method",
"SavedCardDetails.savedPaymentMethodPlaceholderDesktop": "•••• •••• •••• {last4Digits}",
"SavedCardDetails.savedPaymentMethodPlaceholderMobile": "…{last4Digits}",
"SearchFilters.amenitiesLabel": "Amenities",
"SearchFilters.categoryLabel": "Category",
"SearchFilters.filtersButtonLabel": "Filters",
"SearchFilters.foundResults": "{count, number} {count, plural, one {result} other {results}}",
"SearchFilters.keywordLabel": "Keyword",
Expand All @@ -714,8 +712,10 @@
"SearchFiltersMobile.keywordLabel": "Keyword",
"SearchFiltersMobile.resetAll": "Reset all",
"SearchFiltersMobile.showListings": "Show {count, number} {count, plural, one {sauna} other {saunas}}",
"SearchFiltersPanel.amenitiesLabel": "Amenities",
"SearchFiltersPanel.apply": "Apply",
"SearchFiltersPanel.cancel": "Cancel",
"SearchFiltersPanel.categoryLabel": "Category",
"SearchFiltersPanel.resetAll": "Reset all",
"SearchMapInfoCard.noImage": "No image",
"SearchPage.schemaDescription": "Showing search results",
Expand Down