diff options
author | Noah Loomans <noahloomans@gmail.com> | 2018-01-06 15:42:04 +0100 |
---|---|---|
committer | Noah Loomans <noahloomans@gmail.com> | 2018-01-06 15:42:04 +0100 |
commit | c0aa588bc8f85b13b5a55ccd6cdf11bf99048a1c (patch) | |
tree | 4914a9d09b362e222a83b0b9637ed87e11eebe7b /src/client/react | |
parent | 928edee90f4a35eea20d581e093b002be04e9b47 (diff) |
Add user page
Diffstat (limited to 'src/client/react')
-rw-r--r-- | src/client/react/actions/search.js | 5 | ||||
-rw-r--r-- | src/client/react/components/container/Search.js | 10 | ||||
-rw-r--r-- | src/client/react/components/page/Index.js | 10 | ||||
-rw-r--r-- | src/client/react/components/page/User.js | 31 | ||||
-rw-r--r-- | src/client/react/index.js | 2 | ||||
-rw-r--r-- | src/client/react/reducers/search.js | 20 | ||||
-rw-r--r-- | src/client/react/reducers/search.test.js | 22 |
7 files changed, 89 insertions, 11 deletions
diff --git a/src/client/react/actions/search.js b/src/client/react/actions/search.js index d903e64..22daeca 100644 --- a/src/client/react/actions/search.js +++ b/src/client/react/actions/search.js @@ -1,3 +1,8 @@ +export const setUser = user => ({ + type: 'SEARCH/SET_USER', + user, +}); + export const inputChange = searchText => ({ type: 'SEARCH/INPUT_CHANGE', searchText, diff --git a/src/client/react/components/container/Search.js b/src/client/react/components/container/Search.js index 06523be..27b0563 100644 --- a/src/client/react/components/container/Search.js +++ b/src/client/react/components/container/Search.js @@ -6,7 +6,7 @@ import { withRouter } from 'react-router-dom'; import SearchIcon from 'react-icons/lib/md/search'; -import { inputChange, changeSelectedResult } from '../../actions/search'; +import { setUser, inputChange, changeSelectedResult } from '../../actions/search'; import users from '../../users'; import Results from './Results'; @@ -25,6 +25,10 @@ class Search extends React.Component { this.onKeyDown = this.onKeyDown.bind(this); } + componentDidMount() { + this.props.dispatch(setUser(this.props.urlUser)); + } + onFocus() { this.setState({ hasFocus: true, @@ -97,6 +101,7 @@ class Search extends React.Component { Search.propTypes = { selectedResult: PropTypes.string, + urlUser: PropTypes.string, isExactMatch: PropTypes.bool.isRequired, searchText: PropTypes.string.isRequired, dispatch: PropTypes.func.isRequired, @@ -107,6 +112,7 @@ Search.propTypes = { Search.defaultProps = { selectedResult: null, + urlUser: null, }; const mapStateToProps = state => ({ @@ -116,4 +122,4 @@ const mapStateToProps = state => ({ isExactMatch: state.search.isExactMatch, }); -export default connect(mapStateToProps)(withRouter(Search)); +export default withRouter(connect(mapStateToProps)(Search)); diff --git a/src/client/react/components/page/Index.js b/src/client/react/components/page/Index.js index dcc521d..a91d7a9 100644 --- a/src/client/react/components/page/Index.js +++ b/src/client/react/components/page/Index.js @@ -1,16 +1,10 @@ import React from 'react'; -import PropTypes from 'prop-types'; import Search from '../container/Search'; -const App = ({ location }) => ( +const App = () => ( <div> - <Search location={location} /> + <Search /> </div> ); -App.propTypes = { - // eslint-disable-next-line react/forbid-prop-types - location: PropTypes.object.isRequired, -}; - export default App; diff --git a/src/client/react/components/page/User.js b/src/client/react/components/page/User.js new file mode 100644 index 0000000..2ad65a6 --- /dev/null +++ b/src/client/react/components/page/User.js @@ -0,0 +1,31 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Redirect } from 'react-router-dom'; +import Search from '../container/Search'; +import users from '../../users'; + +const App = ({ match }) => { + const user = `${match.params.type}/${match.params.value}`; + + if (!users.allIds.includes(user)) { + // Invalid user, redirect to index. + return <Redirect to="/" />; + } + + return ( + <div> + <Search urlUser={user} /> + </div> + ); +}; + +App.propTypes = { + match: PropTypes.shape({ + params: PropTypes.shape({ + type: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, +}; + +export default App; diff --git a/src/client/react/index.js b/src/client/react/index.js index 18dacf5..ffa5403 100644 --- a/src/client/react/index.js +++ b/src/client/react/index.js @@ -7,6 +7,7 @@ import logger from 'redux-logger'; import thunk from 'redux-thunk'; import reducer from './reducers'; import Index from './components/page/Index'; +import User from './components/page/User'; // eslint-disable-next-line no-underscore-dangle const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; @@ -20,6 +21,7 @@ ReactDOM.render( <Router> <div> <Route exact path="/" component={Index} /> + <Route path="/:type/:value" component={User} /> </div> </Router> </Provider>, diff --git a/src/client/react/reducers/search.js b/src/client/react/reducers/search.js index 6027ed7..7c7e917 100644 --- a/src/client/react/reducers/search.js +++ b/src/client/react/reducers/search.js @@ -27,6 +27,22 @@ function getSearchResults(allUsers, query) { const search = (state = DEFAULT_STATE, action) => { switch (action.type) { + case 'SEARCH/SET_USER': { + const { user } = action; + + if (user == null) { + return DEFAULT_STATE; + } + + return { + ...state, + results: [], + searchText: users.byId[user].value, + selectedResult: user, + isExactMatch: true, + }; + } + case 'SEARCH/INPUT_CHANGE': { const { searchText } = action; const results = getSearchResults(users.allUsers, action.searchText); @@ -82,3 +98,7 @@ const search = (state = DEFAULT_STATE, action) => { }; export default search; + +export const _test = { + DEFAULT_STATE, +}; diff --git a/src/client/react/reducers/search.test.js b/src/client/react/reducers/search.test.js index ddd7f9b..22d32e2 100644 --- a/src/client/react/reducers/search.test.js +++ b/src/client/react/reducers/search.test.js @@ -12,10 +12,30 @@ window.USERS = [ const deepFreeze = require('deep-freeze'); const search = require('./search').default; -const { inputChange, changeSelectedResult } = require('../actions/search'); +const { _test } = require('./search'); +const { + setUser, + inputChange, + changeSelectedResult, +} = require('../actions/search'); describe('reducers', () => { describe('search', () => { + describe('SEARCH/SET_USER', () => { + it('Resets to the default state if the user is null', () => { + expect(search({ foo: 'bar' }, setUser(null))).toEqual(_test.DEFAULT_STATE); + }); + + it('Sets all the values of that user properly', () => { + expect(search(undefined, setUser('s/18561'))).toEqual({ + results: [], + searchText: '18561', + selectedResult: 's/18561', + isExactMatch: true, + }); + }); + }); + describe('SEARCH/INPUT_CHANGE', () => { it('Returns no results when nothing is typed in', () => { expect(search(undefined, inputChange(''))).toEqual({ |