diff options
-rw-r--r-- | src/client/react/components/container/Search.js | 1 | ||||
-rw-r--r-- | src/client/react/components/presentational/Search.jsx | 51 | ||||
-rw-r--r-- | src/client/react/reducers/search.js | 15 |
3 files changed, 45 insertions, 22 deletions
diff --git a/src/client/react/components/container/Search.js b/src/client/react/components/container/Search.js index 206a6a1..70b3685 100644 --- a/src/client/react/components/container/Search.js +++ b/src/client/react/components/container/Search.js @@ -6,6 +6,7 @@ const mapStateToProps = state => ({ results: state.search.searchResults, value: state.search.searchInput, hasFocus: state.search.hasFocus, + exactMatch: state.search.exactMatch, }); const mapDispatchToProps = dispatch => ({ diff --git a/src/client/react/components/presentational/Search.jsx b/src/client/react/components/presentational/Search.jsx index bdddf06..78beb56 100644 --- a/src/client/react/components/presentational/Search.jsx +++ b/src/client/react/components/presentational/Search.jsx @@ -12,34 +12,37 @@ const userShape = { type: PropTypes.string.isRequired, }; -const Result = ({ user }) => { - let icon; - - switch (user.type) { +const IconFromUserType = ({ userType }) => { + switch (userType) { case 'c': - icon = <ClassIcon />; - break; + return <ClassIcon />; case 't': - icon = <TeacherIcon />; - break; + return <TeacherIcon />; case 's': - icon = <StudentIcon />; - break; + return <StudentIcon />; case 'r': - icon = <RoomIcon />; - break; + return <RoomIcon />; default: - throw new Error(`Invalid user type: ${user.type}`); + return <SearchIcon />; } +}; - return ( - <div className="search__result"> - <div className="search__icon-wrapper">{icon}</div> - <div className="search__result__text">{user.value}</div> - </div> - ); +IconFromUserType.propTypes = { + userType: PropTypes.string, }; +IconFromUserType.defaultProps = { + userType: null, +}; + + +const Result = ({ user }) => ( + <div className="search__result"> + <div className="search__icon-wrapper"><IconFromUserType userType={user.type} /></div> + <div className="search__result__text">{user.value}</div> + </div> +); + Result.propTypes = { user: PropTypes.shape(userShape).isRequired, }; @@ -51,10 +54,12 @@ const Search = ({ hasFocus, value, results, + exactMatch, }) => ( <div className={classnames('search', { 'search--has-focus': hasFocus, 'search--has-results': results.length > 0 })}> <div className="search__input-wrapper"> - <div className="search__icon-wrapper"><SearchIcon /></div> + {/* 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} /></div> <input onChange={onInputChange} value={value} @@ -76,6 +81,12 @@ Search.propTypes = { hasFocus: PropTypes.bool.isRequired, value: PropTypes.string.isRequired, results: PropTypes.arrayOf(PropTypes.shape(userShape)).isRequired, + exactMatch: PropTypes.shape(userShape), }; +Search.defaultProps = { + exactMatch: null, +}; + + export default Search; diff --git a/src/client/react/reducers/search.js b/src/client/react/reducers/search.js index 72fa469..dd737ed 100644 --- a/src/client/react/reducers/search.js +++ b/src/client/react/reducers/search.js @@ -6,6 +6,7 @@ const DEFAULT_STATE = { searchResults: [ { type: 's', value: '18561' }, ], + exactMatch: null, hasFocus: false, }; @@ -26,12 +27,22 @@ function getSearchResults(query) { const search = (state = DEFAULT_STATE, action) => { switch (action.type) { - case 'SEARCH/INPUT_CHANGE': + case 'SEARCH/INPUT_CHANGE': { + let results = getSearchResults(action.typedValue); + let exactMatch = false; + + if ((results.length > 0) && (action.typedValue === results[0].value)) { + [exactMatch] = results; + results = results.splice(1); + } + return { ...state, searchInput: action.typedValue, - searchResults: getSearchResults(action.typedValue), + searchResults: results, + exactMatch, }; + } case 'SEARCH/FOCUS_CHANGE': return { ...state, |