Extracted SearchField from SearchBar component to its own component

This commit is contained in:
Alejandro Celaya 2018-08-19 20:29:23 +02:00
parent 03870c0c6f
commit 843c121285
4 changed files with 108 additions and 94 deletions

View file

@ -1,85 +1,43 @@
import searchIcon from '@fortawesome/fontawesome-free-solid/faSearch';
import tagsIcon from '@fortawesome/fontawesome-free-solid/faTags';
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import React from 'react';
import { connect } from 'react-redux';
import Tag from '../utils/Tag';
import { listShortUrls } from './reducers/shortUrlsList';
import { isEmpty, pick } from 'ramda';
import SearchField from '../utils/SearchField';
import './SearchBar.scss';
import { pick, isEmpty } from 'ramda';
export class SearchBar extends React.Component {
state = {
showClearBtn: false,
searchTerm: '',
};
timer = null;
export function SearchBar({ listShortUrls, shortUrlsListParams }) {
const selectedTags = shortUrlsListParams.tags || [];
render() {
const { listShortUrls, shortUrlsListParams } = this.props;
const selectedTags = shortUrlsListParams.tags || [];
return (
<div className="serach-bar-container">
<SearchField onChange={
searchTerm => listShortUrls({ ...shortUrlsListParams, searchTerm })
}/>
return (
<div className="serach-bar-container">
<div className="search-bar">
<input
type="text"
className="form-control form-control-lg search-bar__input"
placeholder="Search..."
onChange={e => this.searchTermChanged(e.target.value)}
value={this.state.searchTerm}
/>
<FontAwesomeIcon icon={searchIcon} className="search-bar__icon" />
<div
className="close search-bar__close"
hidden={! this.state.showClearBtn}
onClick={() => this.searchTermChanged('')}
id="search-bar__close"
>
&times;
</div>
</div>
{!isEmpty(selectedTags) && (
<h4 className="search-bar__selected-tag mt-2">
<FontAwesomeIcon icon={tagsIcon} className="search-bar__tags-icon" />
&nbsp;
{selectedTags.map(tag => (
<Tag
key={tag}
text={tag}
clearable
onClose={() => listShortUrls(
{
...shortUrlsListParams,
tags: selectedTags.filter(selectedTag => selectedTag !== tag)
}
)}
/>
))}
</h4>
)}
</div>
);
}
searchTermChanged(searchTerm) {
this.setState({
showClearBtn: searchTerm !== '',
searchTerm: searchTerm,
});
const resetTimer = () => {
clearTimeout(this.timer);
this.timer = null;
};
resetTimer();
this.timer = setTimeout(() => {
this.props.listShortUrls({ ...this.props.shortUrlsListParams, searchTerm });
resetTimer();
}, 500);
}
{!isEmpty(selectedTags) && (
<h4 className="search-bar__selected-tag mt-2">
<FontAwesomeIcon icon={tagsIcon} className="search-bar__tags-icon"/>
&nbsp;
{selectedTags.map(tag => (
<Tag
key={tag}
text={tag}
clearable
onClose={() => listShortUrls(
{
...shortUrlsListParams,
tags: selectedTags.filter(selectedTag => selectedTag !== tag)
}
)}
/>
))}
</h4>
)}
</div>
);
}
export default connect(pick(['shortUrlsListParams']), { listShortUrls })(SearchBar);

View file

@ -1,25 +1,3 @@
@import '../utils/mixins/vertical-align';
.search-bar {
position: relative;
}
.search-bar__input.search-bar__input {
padding-left: 40px;
padding-right: 40px;
}
.search-bar__icon {
@include vertical-align();
left: 15px;
color: #707581;
}
.search-bar__close {
@include vertical-align();
right: 15px;
}
.search-bar__tags-icon {
vertical-align: bottom;
}

57
src/utils/SearchField.js Normal file
View file

@ -0,0 +1,57 @@
import React from 'react';
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import searchIcon from '@fortawesome/fontawesome-free-solid/faSearch';
import PropTypes from 'prop-types';
import './SearchField.scss';
const propTypes = {
onChange: PropTypes.func.isRequired,
};
export default class SearchField extends React.Component {
state = { showClearBtn: false, searchTerm: '' };
timer = null;
searchTermChanged(searchTerm, timeout = 500) {
this.setState({
showClearBtn: searchTerm !== '',
searchTerm,
});
const resetTimer = () => {
clearTimeout(this.timer);
this.timer = null;
};
resetTimer();
this.timer = setTimeout(() => {
this.props.onChange(searchTerm);
resetTimer();
}, timeout);
}
render() {
return (
<div className="search-field">
<input
type="text"
className="form-control form-control-lg search-field__input"
placeholder="Search..."
onChange={e => this.searchTermChanged(e.target.value)}
value={this.state.searchTerm}
/>
<FontAwesomeIcon icon={searchIcon} className="search-field__icon" />
<div
className="close search-field__close"
hidden={! this.state.showClearBtn}
onClick={() => this.searchTermChanged('', 0)}
id="search-field__close"
>
&times;
</div>
</div>
);
}
}
SearchField.propTypes = propTypes;

View file

@ -0,0 +1,21 @@
@import '../utils/mixins/vertical-align';
.search-field {
position: relative;
}
.search-field__input.search-field__input {
padding-left: 40px;
padding-right: 40px;
}
.search-field__icon {
@include vertical-align();
left: 15px;
color: #707581;
}
.search-field__close {
@include vertical-align();
right: 15px;
}