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,  | 
