fk-react-ui-components
Version:
Step 1 : Create a file in [ Seeds / Plants / Trees ] <br> Step 2 : It should export an Object with component name and story Component [Refer other components] <br> Step 3 : Story Component should return a react component <br> Step 3 : Created file should
280 lines (259 loc) • 8.86 kB
JavaScript
import React from 'react';
import { PropTypes } from 'prop-types';
import FilterComponent from './FilterComponent';
import CheckboxTreeFilter from '../CheckboxTreeFilter';
import Slider from '../Slider';
import ToggleComponent from '../ToggleComponent';
import Card from '../Card';
class FilterComponentWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
filterChips: [],
...props.appliedFilters
};
this.getInput = this.getInput.bind(this);
this.updateFilters = this.updateFilters.bind(this);
this.onFilterClear = this.onFilterClear.bind(this);
this.onFilterReset = this.onFilterReset.bind(this);
this.onFilterSubmit = this.onFilterSubmit.bind(this);
this.state.filterChips = this.props.templateParams
.map(param => param.name)
.reduce(
(list, key) => [...list, ...this.getFilterContent(key)],
[]
);
}
componentWillReceiveProps(newProps) {
this.setState({ ...newProps.appliedFilters });
}
onFilterClear(filterChip) {
this.updateState(prevState => {
const selectedFilter = prevState[filterChip.type];
return {
[filterChip.type]: Array.isArray(selectedFilter)
? selectedFilter.filter(filter => filter !== filterChip.key)
: undefined
};
});
}
onFilterReset() {
const state = this.props.templateParams.reduce((obj, param) => {
obj[param.name] = undefined;
return obj;
}, {});
state.filterChips = [];
this.setState(state);
}
onFilterSubmit() {
if (this.props.onFilterSubmit) {
this.props.onFilterSubmit(
this.props.templateParams.reduce((obj, param) => {
obj[param.name] = this.state[param.name];
return obj;
}, {})
);
}
}
getFilterCount() {
return this.filterChips.length;
}
getInput(param) {
switch (param.type) {
case 'toggleCheckboxTree':
return this.getToggleCheckboxTree(param);
case 'toggleSlider':
return this.getToggleSlider(param);
case 'component':
return this.getComponent(param);
default:
return null;
}
}
getFilterContent(key) {
const param = this.props.templateParams.find(item => item.name === key);
const selectedFilter = this.state[key];
return selectedFilter
? Array.isArray(selectedFilter)
? selectedFilter.map(filter => ({
key: filter,
value: param.displayContent
? param.displayContent(filter)
: filter,
type: key
}))
: [
{
key: selectedFilter,
value: param.displayContent
? param.displayContent(selectedFilter)
: selectedFilter,
type: key
}
]
: [];
}
getToggleCheckboxTree(param) {
return (
param.name && (
<CheckboxTreeFilter
{...param.props}
key={param.name}
type="checkbox"
onChange={checked =>
this.updateState({ [param.name]: checked })
}
checked={this.state[param.name] || []}
includeSearch={param.includeSearch}
searchClassName="toggle-filter-search"
placeholder={param.searchPlaceholder}
label={param.label}
nodes={param.nodes}
/>
)
);
}
getToggleSlider(param) {
const value = this.state[param.name];
return (
param.name && (
<ToggleComponent
key={param.name}
label={param.label}
name={param.name}
resetFilters={() =>
this.updateState({ [param.name]: undefined })
}
activeFilter={this.state[param.name]}
openedClass="toggle-open-carrot"
closedClass="toggle-closed-carrot"
>
<Card
width="100%"
position="absolute"
padding="10px"
boxShadow="rgba(208, 208, 208, 0.5) 1px 0px 6px 0px"
zIndex="1"
className="toggle-slider"
>
<Slider
{...param.props}
range={param.range}
min={param.min}
max={param.max}
steps={param.steps}
styles={{ slider: { width: '100%' } }}
onChange={values => {
this.updateState({
[param.name]: Array.isArray(values)
? {
min: values[0],
max: values[1]
}
: values
});
}}
value={
typeof value === 'object'
? [value.min, value.max]
: value
}
/>
</Card>
</ToggleComponent>
)
);
}
/**
*
* Can accept external Component.
* The input component should accept `onChange` and `value` props
* and handle as needed.
*/
getComponent(param) {
const { Component, name } = param;
return (
name &&
Component && (
<Component
value={this.state[name]}
onChange={value =>
this.updateState({
[name]: value
})
}
/>
)
);
}
updateFilters() {
const filterChips = this.props.templateParams
.map(param => param.name)
.reduce(
(list, key) => [...list, ...this.getFilterContent(key)],
[]
);
this.setState({ filterChips });
if (this.props.onFilterChange) {
this.props.onFilterChange(
this.props.templateParams.reduce((obj, param) => {
obj[param.name] = this.state[param.name];
return obj;
}, {})
);
}
}
updateState(state) {
if (state) {
this.setState(state, this.updateFilters);
}
}
render() {
const templateParams = this.props.templateParams || [];
const filterComponentProps = {
filterChips: this.state.filterChips,
onFilterClear: this.onFilterClear,
onFilterReset: this.onFilterReset,
onFilterSubmit: this.onFilterSubmit
};
return (
<FilterComponent {...this.props} {...filterComponentProps}>
{Array.isArray(templateParams) &&
templateParams.length &&
templateParams.map(this.getInput)}
</FilterComponent>
);
}
}
FilterComponentWrapper.defaultProps = {
expand: false,
className: '',
onFilterChange: () => {}
};
FilterComponentWrapper.propTypes = {
/**
* expands/collapses the filter component
*/
expand: PropTypes.bool,
/**
* class for the component
*/
className: PropTypes.string,
/**
* function to call on Apply clicked
*/
onFilterSubmit: PropTypes.func.isRequired,
/**
* function to call when any filter is changed
*/
onFilterChange: PropTypes.func,
/**
* Filters to be preselected
*/
appliedFilters: PropTypes.element.isRequired,
/**
* Template params used to render filter elements
*/
templateParams: PropTypes.arrayOf(PropTypes.object).isRequired
};
export default FilterComponentWrapper;