mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 03:43:28 +10:00
Split select single filter into distinct file
This commit is contained in:
parent
25b088b22f
commit
a4b6b887ab
6 changed files with 178 additions and 121 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue