aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Loomans <noahloomans@gmail.com>2018-01-06 15:42:04 +0100
committerNoah Loomans <noahloomans@gmail.com>2018-01-06 15:42:04 +0100
commitc0aa588bc8f85b13b5a55ccd6cdf11bf99048a1c (patch)
tree4914a9d09b362e222a83b0b9637ed87e11eebe7b
parent928edee90f4a35eea20d581e093b002be04e9b47 (diff)
Add user page
-rw-r--r--.eslintrc.js3
-rw-r--r--package.json2
-rw-r--r--src/client/react/actions/search.js5
-rw-r--r--src/client/react/components/container/Search.js10
-rw-r--r--src/client/react/components/page/Index.js10
-rw-r--r--src/client/react/components/page/User.js31
-rw-r--r--src/client/react/index.js2
-rw-r--r--src/client/react/reducers/search.js20
-rw-r--r--src/client/react/reducers/search.test.js22
-rw-r--r--yarn.lock16
10 files changed, 102 insertions, 19 deletions
diff --git a/.eslintrc.js b/.eslintrc.js
index b418fd4..376aa38 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -6,6 +6,7 @@ module.exports = {
"jest": true,
},
"rules": {
- "react/jsx-filename-extension": [1, { "extensions": [".js"] }]
+ "react/jsx-filename-extension": ["error", { "extensions": [".js"] }],
+ "no-underscore-dangle": ["error", { "allow": ["_test"] }],
}
};
diff --git a/package.json b/package.json
index fdc7374..0363675 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
"debug": "^2.6.0",
"diacritics": "^1.2.3",
"encoding": "^0.1.12",
- "eslint": "^4.13.0",
+ "eslint": "^4.14.0",
"express": "^4.13.4",
"extract-text-webpack-plugin": "^3.0.2",
"flexibility": "^2.0.1",
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({
diff --git a/yarn.lock b/yarn.lock
index 071b4df..1db80c0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1935,7 +1935,7 @@ debug@2.6.8, debug@^2.2.0, debug@^2.6.0, debug@^2.6.8:
dependencies:
ms "2.0.0"
-debug@^3.0.1, debug@^3.1.0:
+debug@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
@@ -2395,21 +2395,25 @@ eslint-scope@^3.7.1:
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint@^4.13.0:
- version "4.13.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.13.0.tgz#1991aa359586af83877bde59de9d41f53e20826d"
+eslint-visitor-keys@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
+
+eslint@^4.14.0:
+ version "4.14.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.14.0.tgz#96609768d1dd23304faba2d94b7fefe5a5447a82"
dependencies:
ajv "^5.3.0"
babel-code-frame "^6.22.0"
chalk "^2.1.0"
concat-stream "^1.6.0"
cross-spawn "^5.1.0"
- debug "^3.0.1"
+ debug "^3.1.0"
doctrine "^2.0.2"
eslint-scope "^3.7.1"
+ eslint-visitor-keys "^1.0.0"
espree "^3.5.2"
esquery "^1.0.0"
- estraverse "^4.2.0"
esutils "^2.0.2"
file-entry-cache "^2.0.0"
functional-red-black-tree "^1.0.1"