aboutsummaryrefslogtreecommitdiff
path: root/src/client/react/components/container
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/react/components/container')
-rw-r--r--src/client/react/components/container/Search.js30
-rw-r--r--src/client/react/components/container/Search.jsx85
2 files changed, 85 insertions, 30 deletions
diff --git a/src/client/react/components/container/Search.js b/src/client/react/components/container/Search.js
deleted file mode 100644
index 4517191..0000000
--- a/src/client/react/components/container/Search.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { connect } from 'react-redux';
-import { inputChange, focusChange } from '../../actions/search';
-import PresentationalSearch from '../presentational/Search';
-
-const mapStateToProps = state => ({
- results: state.search.results,
- value: state.search.input,
- hasFocus: state.search.hasFocus,
- exactMatch: state.search.exactMatch,
-});
-
-const mapDispatchToProps = dispatch => ({
- onInputChange: (event) => {
- dispatch(inputChange(event.target.value));
- },
- onFocus: () => {
- dispatch(focusChange(true));
- document.querySelector('#search__input').select();
- },
- onBlur: () => {
- dispatch(focusChange(false));
- },
-});
-
-const Search = connect(
- mapStateToProps,
- mapDispatchToProps,
-)(PresentationalSearch);
-
-export default Search;
diff --git a/src/client/react/components/container/Search.jsx b/src/client/react/components/container/Search.jsx
new file mode 100644
index 0000000..7a2822f
--- /dev/null
+++ b/src/client/react/components/container/Search.jsx
@@ -0,0 +1,85 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import classnames from 'classnames';
+
+import SearchIcon from 'react-icons/lib/md/search';
+
+import { inputChange, focusChange } from '../../actions/search';
+
+import IconFromUserType from '../presentational/IconFromUserType';
+import Result from '../presentational/Result';
+
+const userShape = {
+ value: PropTypes.string.isRequired,
+ type: PropTypes.string.isRequired,
+};
+
+const Search = ({
+ onInputChange,
+ onFocus,
+ onBlur,
+ hasFocus,
+ value,
+ results,
+ exactMatch,
+}) => (
+ <div className={classnames('search', { 'search--has-focus': hasFocus, 'search--has-results': results.length > 0 })}>
+ <div className="search__input-wrapper">
+ {/* Show the icon from the exact match if there is an exact match, otherwise show the search icon. */}
+ <div className="search__icon-wrapper">
+ <IconFromUserType
+ userType={exactMatch ? exactMatch.type : null}
+ default={<SearchIcon />}
+ />
+ </div>
+ <input
+ id="search__input"
+ onChange={onInputChange}
+ value={value}
+ placeholder="Zoeken"
+ onFocus={onFocus}
+ onBlur={onBlur}
+ />
+ </div>
+ {results.map(user => (
+ <Result key={user.value} user={user} />
+ ))}
+ </div>
+);
+
+Search.propTypes = {
+ onInputChange: PropTypes.func.isRequired,
+ onFocus: PropTypes.func.isRequired,
+ onBlur: PropTypes.func.isRequired,
+ hasFocus: PropTypes.bool.isRequired,
+ value: PropTypes.string.isRequired,
+ results: PropTypes.arrayOf(PropTypes.shape(userShape)).isRequired,
+ exactMatch: PropTypes.shape(userShape),
+};
+
+Search.defaultProps = {
+ exactMatch: null,
+};
+
+const mapStateToProps = state => ({
+ results: state.search.results,
+ value: state.search.input,
+ hasFocus: state.search.hasFocus,
+ exactMatch: state.search.exactMatch,
+});
+
+const mapDispatchToProps = dispatch => ({
+ onInputChange: (event) => {
+ dispatch(inputChange(event.target.value));
+ },
+ onFocus: () => {
+ dispatch(focusChange(true));
+ document.querySelector('#search__input').select();
+ },
+ onBlur: () => {
+ dispatch(focusChange(false));
+ },
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(Search);