Split select single filter into distinct file

This commit is contained in:
Hannu Lyytikainen 2018-01-11 16:42:08 +02:00
parent 25b088b22f
commit a4b6b887ab
6 changed files with 178 additions and 121 deletions

View file

@ -67,12 +67,13 @@
.modalContainer {
width: 100%;
padding: 94px 0;
margin: 0 24px;
}
.modalHeadingWrapper {
padding-bottom: 26px;
border-bottom: 1px solid var(--matterColorNegative);
margin: 0 24px 30px 24px;
margin-bottom: 30px;
}
.modalHeading {
@ -80,7 +81,7 @@
margin-top: 0;
}
.clearButton {
.resetAllButton {
@apply --marketplaceH5FontStyles;
font-weight: var(--fontWeightMedium);
color: var(--matterColorAnti);
@ -101,65 +102,6 @@
}
}
.filterLabel {
@apply --marketplaceH3FontStyles;
color: var(--matterColorDark);
padding-left: 24px;
}
.filterLabelSelected {
@apply --marketplaceH3FontStyles;
color: var(--marketplaceColor);
padding-left: 24px;
}
/* left animated "border" like hover element */
.optionBorder {
position: absolute;
top: 2px;
left: 0px;
height: calc(100% - 7px);
width: 0;
background-color: var(--matterColorDark);
transition: width var(--transitionStyleButton);
}
/* left static border for selected element */
.optionBorderSelected {
position: absolute;
top: 2px;
left: 0px;
height: calc(100% - 7px);
width: 12px;
background-color: var(--matterColorDark);
transition: width var(--transitionStyleButton);
}
.option {
@apply --marketplaceH3FontStyles;
font-weight: var(--fontWeightMedium);
color: var(--matterColor);
/* Layout */
display: block;
position: relative;
margin: 0;
padding: 4px 24px 4px 44px;
/* Override button styles */
outline: none;
border: none;
&:focus,
&:hover {
color: var(--matterColorDark);
}
&:hover .menuItemBorder {
width: 6px;
}
}
.showListingsContainer {
z-index: 11;
position: fixed;

View file

@ -7,55 +7,10 @@ import { omit } from 'lodash';
import routeConfiguration from '../../routeConfiguration';
import { createResourceLocatorString } from '../../util/routes';
import { SecondaryButton, ModalInMobile, Button } from '../../components';
import { SecondaryButton, ModalInMobile, Button, SelectSingleFilterMobile } from '../../components';
import config from '../../config';
import css from './SearchFiltersMobile.css';
class SelectSingleCustomAttributeMobile extends Component {
constructor(props) {
super(props);
this.selectOption = this.selectOption.bind(this);
}
selectOption(option) {
const customAttribute = this.props.customAttribute;
this.props.onSelect(customAttribute, option);
}
render() {
const { customAttribute, urlQueryParams, intl } = this.props;
const filterLabel = intl.formatMessage({
id: `SelectSingleCustomAttribute.${customAttribute}.label`,
});
// custom attribute content
const ca = customAttribute && config.customAttributes[customAttribute];
// name of the corresponding query parameter
const caParam = `ca_${customAttribute}`;
// current value of this custom attribute filter
const currentValue = urlQueryParams[caParam];
const labelClass = currentValue ? css.filterLabelSelected : css.filterLabel;
return (
<div>
<div className={labelClass}>{filterLabel}</div>
{ca.values.map(v => {
// check if this option is selected
const selected = currentValue === v;
// menu item border class
const optionBorderClass = selected ? css.optionBorderSelected : css.optionBorder;
return (
<button key={v} className={css.option} onClick={() => this.selectOption(v)}>
<span className={optionBorderClass} />
<FormattedMessage id={`SelectSingleCustomAttributeMobile.category.option.${v}`} />
</button>
);
})}
</div>
);
}
}
class SearchFiltersMobileComponent extends Component {
constructor(props) {
super(props);
@ -89,11 +44,11 @@ class SearchFiltersMobileComponent extends Component {
{ count: resultsCount }
);
const openMobileFilters = () => {
const openFilters = () => {
this.setState({ isFiltersOpenOnMobile: true });
};
const closeMobileFilters = () => {
const closeFilters = () => {
this.setState({ isFiltersOpenOnMobile: false });
};
@ -129,7 +84,7 @@ class SearchFiltersMobileComponent extends Component {
const hasCategoryConfig = config.customAttributes && config.customAttributes.category;
const categoryFilter = hasCategoryConfig ? (
<SelectSingleCustomAttributeMobile
<SelectSingleFilterMobile
customAttribute={customAttribute}
urlQueryParams={urlQueryParams}
onSelect={onSelectSingle}
@ -145,7 +100,7 @@ class SearchFiltersMobileComponent extends Component {
{searchInProgress ? loadingResults : null}
</div>
<div className={css.buttons}>
<SecondaryButton className={css.filterButton} onClick={openMobileFilters}>
<SecondaryButton className={css.filterButton} onClick={openFilters}>
<FormattedMessage id="SearchFilters.filtersButtonLabel" className={css.mapIconText} />
</SecondaryButton>
<div className={css.mapIcon} onClick={onMapIconClick}>
@ -155,20 +110,20 @@ class SearchFiltersMobileComponent extends Component {
<ModalInMobile
id="SearchFiltersMobile.filters"
isModalOpenOnMobile={this.state.isFiltersOpenOnMobile}
onClose={closeMobileFilters}
onClose={closeFilters}
showAsModalMaxWidth={showAsModalMaxWidth}
onManageDisableScrolling={onManageDisableScrolling}
containerClassName={css.modalContainer}
>
<div className={css.modalHeadingWrapper}>
<span className={css.modalHeading}>{filtersHeading}</span>
<button className={css.clearButton} onClick={resetAll}>
<button className={css.resetAllButton} onClick={resetAll}>
<FormattedMessage id={'SearchFiltersMobile.resetAll'} />
</button>
</div>
<div className={css.filtersContainer}>{categoryFilter}</div>
{categoryFilter}
<div className={css.showListingsContainer}>
<Button className={css.showListingsButton} onClick={closeMobileFilters}>
<Button className={css.showListingsButton} onClick={closeFilters}>
{showListingsLabel}
</Button>
</div>

View file

@ -0,0 +1,84 @@
@import '../../marketplace.css';
.root {
padding-bottom: 18px;
border-bottom: 1px solid var(--matterColorNegative);
}
.filterLabel {
@apply --marketplaceH3FontStyles;
color: var(--matterColorDark);
}
.filterLabelSelected {
@apply --marketplaceH3FontStyles;
color: var(--marketplaceColor);
}
/* left animated "border" like hover element */
.optionBorder {
position: absolute;
top: 2px;
left: -24px;
height: calc(100% - 7px);
width: 0;
background-color: var(--matterColorDark);
transition: width var(--transitionStyleButton);
}
/* left static border for selected element */
.optionBorderSelected {
position: absolute;
top: 2px;
left: -24px;
height: calc(100% - 7px);
width: 12px;
background-color: var(--matterColorDark);
transition: width var(--transitionStyleButton);
}
.option {
@apply --marketplaceH3FontStyles;
font-weight: var(--fontWeightMedium);
color: var(--matterColor);
/* Layout */
display: block;
position: relative;
margin: 0;
padding: 4px 0 4px 20px;
/* Override button styles */
outline: none;
border: none;
&:focus,
&:hover {
color: var(--matterColorDark);
}
&:hover .menuItemBorder {
width: 6px;
}
}
.clearButton {
@apply --marketplaceH5FontStyles;
font-weight: var(--fontWeightMedium);
color: var(--matterColorAnti);
/* Layout */
display: inline;
float: right;
margin-top: 6px;
/* Override button styles */
outline: none;
text-align: left;
border: none;
&:focus,
&:hover {
color: var(--matterColor);
}
}

View file

@ -0,0 +1,73 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import config from '../../config';
import css from './SelectSingleFilterMobile.css';
const SelectSingleFilterMobileComponent = props => {
const { rootClassName, className, customAttribute, urlQueryParams, onSelect, intl } = props;
const selectOption = option => {
onSelect(customAttribute, option);
};
const filterLabel = intl.formatMessage({
id: `SelectSingleFilterMobile.${customAttribute}.label`,
});
// custom attribute content
const ca = customAttribute && config.customAttributes[customAttribute];
// name of the corresponding query parameter
const caParam = `ca_${customAttribute}`;
// current value of this custom attribute filter
const currentValue = urlQueryParams[caParam];
const labelClass = currentValue ? css.filterLabelSelected : css.filterLabel;
const classes = classNames(rootClassName || css.root, className);
return (
<div className={classes}>
<div className={labelClass}>
<span>{filterLabel}</span>
<button className={css.clearButton} onClick={() => selectOption(null)}>
<FormattedMessage id={'SelectSingleFilterMobile.clear'} />
</button>
</div>
{ca.values.map(v => {
// check if this option is selected
const selected = currentValue === v;
// menu item border class
const optionBorderClass = selected ? css.optionBorderSelected : css.optionBorder;
return (
<button key={v} className={css.option} onClick={() => selectOption(v)}>
<span className={optionBorderClass} />
<FormattedMessage id={`SelectSingleFilterMobile.category.option.${v}`} />
</button>
);
})}
</div>
);
};
const { object, string, func } = PropTypes;
SelectSingleFilterMobileComponent.defaultProps = {
rootClassName: null,
className: null,
};
SelectSingleFilterMobileComponent.propTypes = {
rootClassName: string,
className: string,
customAttribute: string.isRequired,
urlQueryParams: object.isRequired,
onSelect: func.isRequired,
// from injectIntl
intl: intlShape.isRequired,
};
const SelectSingleFilterMobile = injectIntl(SelectSingleFilterMobileComponent);
export default SelectSingleFilterMobile;

View file

@ -102,6 +102,9 @@ export { default as SelectField } from './SelectField/SelectField';
export {
default as SelectSingleCustomAttribute,
} from './SelectSingleCustomAttribute/SelectSingleCustomAttribute';
export {
default as SelectSingleFilterMobile,
} from './SelectSingleFilterMobile/SelectSingleFilterMobile';
export {
default as StripeBankAccountTokenInputField,
} from './StripeBankAccountTokenInputField/StripeBankAccountTokenInputField';

View file

@ -503,12 +503,12 @@
"SelectSingleCustomAttribute.category.option.road": "Road",
"SelectSingleCustomAttribute.category.option.track": "Track",
"SelectSingleCustomAttribute.clear": "Clear",
"SelectSingleCustomAttributeMobile.category.label": "Category",
"SelectSingleCustomAttributeMobile.category.option.mountain": "Mountain",
"SelectSingleCustomAttributeMobile.category.option.other": "Other",
"SelectSingleCustomAttributeMobile.category.option.road": "Road",
"SelectSingleCustomAttributeMobile.category.option.track": "Track",
"SelectSingleCustomAttributeMobile.clear": "Clear",
"SelectSingleFilterMobile.category.label": "Category",
"SelectSingleFilterMobile.category.option.mountain": "Mountain",
"SelectSingleFilterMobile.category.option.other": "Other",
"SelectSingleFilterMobile.category.option.road": "Road",
"SelectSingleFilterMobile.category.option.track": "Track",
"SelectSingleFilterMobile.clear": "Clear",
"SendMessageForm.sendFailed": "Failed to send. Please try again.",
"SendMessageForm.sendMessage": "Send message",
"SignupForm.emailInvalid": "A valid email address is required",