aboutsummaryrefslogtreecommitdiff
path: root/src/client/react/components
diff options
context:
space:
mode:
authorNoah Loomans <noahloomans@gmail.com>2017-12-21 12:06:41 +0100
committerNoah Loomans <noahloomans@gmail.com>2017-12-21 12:06:41 +0100
commitf0c8cf0e79f003514fd65a70def5820205955a77 (patch)
treecb66d325fb5d16d8b7fa0f14c91ad17dd4ff7c6c /src/client/react/components
parent569b2969d530f08e55798c5cb3079948c7c037cd (diff)
Move to typescript
Diffstat (limited to 'src/client/react/components')
-rw-r--r--src/client/react/components/container/Results.js35
-rw-r--r--src/client/react/components/container/Results.tsx26
-rw-r--r--src/client/react/components/container/Search.tsx (renamed from src/client/react/components/container/Search.js)69
-rw-r--r--src/client/react/components/presentational/IconFromUserType.js37
-rw-r--r--src/client/react/components/presentational/IconFromUserType.tsx31
-rw-r--r--src/client/react/components/presentational/Result.tsx (renamed from src/client/react/components/presentational/Result.js)12
6 files changed, 107 insertions, 103 deletions
diff --git a/src/client/react/components/container/Results.js b/src/client/react/components/container/Results.js
deleted file mode 100644
index 911ea27..0000000
--- a/src/client/react/components/container/Results.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
-import classnames from 'classnames';
-import Result from '../presentational/Result';
-
-const Results = (({ results, isExactMatch, selectedResult }) => (
- <div
- className={classnames('search__results', {
- 'search__results--has-results': !isExactMatch && results.length > 0,
- })}
- >
- {!isExactMatch && results.map(userId => (
- <Result key={userId} userId={userId} isSelected={userId === selectedResult} />
- ))}
- </div>
-));
-
-Results.propTypes = {
- results: PropTypes.arrayOf(PropTypes.string).isRequired,
- isExactMatch: PropTypes.bool.isRequired,
- selectedResult: PropTypes.string,
-};
-
-Results.defaultProps = {
- selectedResult: null,
-};
-
-const mapStateToProps = state => ({
- results: state.search.results,
- isExactMatch: state.search.isExactMatch,
- selectedResult: state.search.selectedResult,
-});
-
-export default connect(mapStateToProps)(Results);
diff --git a/src/client/react/components/container/Results.tsx b/src/client/react/components/container/Results.tsx
new file mode 100644
index 0000000..21d3378
--- /dev/null
+++ b/src/client/react/components/container/Results.tsx
@@ -0,0 +1,26 @@
+import * as React from 'react';
+import { connect } from 'react-redux';
+import * as classnames from 'classnames';
+import Result from '../presentational/Result';
+import { User } from '../../users';
+import { State } from '../../reducers';
+
+const Results: React.StatelessComponent<{ results: string[], isExactMatch: boolean, selectedResult: string }> = (props) => (
+ <div
+ className={classnames('search__results', {
+ 'search__results--has-results': !props.isExactMatch && props.results.length > 0,
+ })}
+ >
+ {!props.isExactMatch && props.results.map(userId => (
+ <Result key={userId} userId={userId} isSelected={userId === props.selectedResult} />
+ ))}
+ </div>
+);
+
+const mapStateToProps = (state: State) => ({
+ results: state.search.results,
+ isExactMatch: state.search.isExactMatch,
+ selectedResult: state.search.selectedResult,
+});
+
+export default connect(mapStateToProps)(Results);
diff --git a/src/client/react/components/container/Search.js b/src/client/react/components/container/Search.tsx
index e49e6a7..fdd6c83 100644
--- a/src/client/react/components/container/Search.js
+++ b/src/client/react/components/container/Search.tsx
@@ -1,18 +1,30 @@
-import React from 'react';
-import PropTypes from 'prop-types';
+import * as React from 'react';
+import { Dispatch } from 'redux';
import { connect } from 'react-redux';
-import classnames from 'classnames';
+import * as classnames from 'classnames';
-import SearchIcon from 'react-icons/lib/md/search';
+import SearchIcon = require('react-icons/lib/md/search');
import { inputChange, changeSelectedResult } from '../../actions/search';
+import { Action } from '../../reducers/search';
+import { State } from '../../reducers';
import users from '../../users';
import Results from './Results';
import IconFromUserType from '../presentational/IconFromUserType';
-class Search extends React.Component {
- constructor(props) {
+interface SearchStatehProps {
+ selectedResult: string,
+ isExactMatch: boolean,
+}
+
+interface SearchDispatchProps {
+ changeSelectedResult(relativeChange: 1 | -1): void,
+ inputChange(typedValue: string): void,
+}
+
+class Search extends React.Component<SearchStatehProps & SearchDispatchProps, any> {
+ constructor(props: SearchStatehProps & SearchDispatchProps) {
super(props);
this.state = {
@@ -36,15 +48,15 @@ class Search extends React.Component {
});
}
- onKeyDown(event) {
+ onKeyDown(event: React.KeyboardEvent<any>) {
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
event.preventDefault();
switch (event.key) {
case 'ArrowUp':
- this.props.dispatch(changeSelectedResult(-1));
+ this.props.changeSelectedResult(-1);
break;
case 'ArrowDown':
- this.props.dispatch(changeSelectedResult(+1));
+ this.props.changeSelectedResult(+1);
break;
default:
throw new Error('This should never happen... pls?');
@@ -56,7 +68,7 @@ class Search extends React.Component {
const {
selectedResult,
isExactMatch,
- dispatch,
+ inputChange,
} = this.props;
const {
@@ -74,7 +86,7 @@ class Search extends React.Component {
</div>
<input
id="search__input"
- onChange={event => dispatch(inputChange(event.target.value))}
+ onChange={event => inputChange(event.target.value)}
onKeyDown={this.onKeyDown}
placeholder="Zoeken"
onFocus={this.onFocus}
@@ -87,20 +99,33 @@ class Search extends React.Component {
}
}
-Search.propTypes = {
- selectedResult: PropTypes.string,
- isExactMatch: PropTypes.bool.isRequired,
- dispatch: PropTypes.func.isRequired,
-};
+// Search.propTypes = {
+// selectedResult: PropTypes.string,
+// isExactMatch: PropTypes.bool.isRequired,
+// dispatch: PropTypes.func.isRequired,
+// };
-Search.defaultProps = {
- selectedResult: null,
-};
+// Search.defaultProps = {
+// selectedResult: null,
+// };
-const mapStateToProps = state => ({
- results: state.search.results,
+const mapStateToProps = (state: State):SearchStatehProps => ({
selectedResult: state.search.selectedResult,
isExactMatch: state.search.isExactMatch,
});
-export default connect(mapStateToProps)(Search);
+// const mapDispatchToProps = {
+// inputChange,
+// changeSelectedResult,
+// };
+
+const mapDispatchToProps = (dispatch: any): SearchDispatchProps => ({
+ inputChange(typedValue) {
+ dispatch(inputChange(typedValue));
+ },
+ changeSelectedResult(relativeChange) {
+ dispatch(changeSelectedResult(relativeChange))
+ }
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(Search);
diff --git a/src/client/react/components/presentational/IconFromUserType.js b/src/client/react/components/presentational/IconFromUserType.js
deleted file mode 100644
index ee0e04b..0000000
--- a/src/client/react/components/presentational/IconFromUserType.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import StudentIcon from 'react-icons/lib/md/person';
-import RoomIcon from 'react-icons/lib/md/room';
-import ClassIcon from 'react-icons/lib/md/group';
-import TeacherIcon from 'react-icons/lib/md/account-circle';
-
-const IconFromUserType = ({ userType, defaultIcon }) => {
- switch (userType) {
- case 'c':
- return <ClassIcon />;
- case 't':
- return <TeacherIcon />;
- case 's':
- return <StudentIcon />;
- case 'r':
- return <RoomIcon />;
- default:
- if (defaultIcon) {
- return defaultIcon;
- }
-
- throw new Error('`userType` was invalid or not given, but `defaultIcon` is not defined.');
- }
-};
-
-IconFromUserType.propTypes = {
- userType: PropTypes.string,
- defaultIcon: PropTypes.element,
-};
-
-IconFromUserType.defaultProps = {
- userType: null,
- defaultIcon: null,
-};
-
-export default IconFromUserType;
diff --git a/src/client/react/components/presentational/IconFromUserType.tsx b/src/client/react/components/presentational/IconFromUserType.tsx
new file mode 100644
index 0000000..d77ea1b
--- /dev/null
+++ b/src/client/react/components/presentational/IconFromUserType.tsx
@@ -0,0 +1,31 @@
+import * as React from 'react';
+import StudentIcon = require('react-icons/lib/md/person');
+import RoomIcon = require('react-icons/lib/md/room');
+import ClassIcon = require('react-icons/lib/md/group');
+import TeacherIcon = require('react-icons/lib/md/account-circle');
+
+// interface IconFromUserTypeProps {
+// userType: string,
+// defaultIcon?: JSX.Element,
+// }
+
+const IconFromUserType: React.StatelessComponent<{ userType: string, defaultIcon?: JSX.Element }> = (props) => {
+ switch (props.userType) {
+ case 'c':
+ return <ClassIcon />;
+ case 't':
+ return <TeacherIcon />;
+ case 's':
+ return <StudentIcon />;
+ case 'r':
+ return <RoomIcon />;
+ default:
+ if (props.defaultIcon) {
+ return props.defaultIcon;
+ }
+
+ throw new Error('`userType` was invalid or not given, but `defaultIcon` is not defined.');
+ }
+};
+
+export default IconFromUserType;
diff --git a/src/client/react/components/presentational/Result.js b/src/client/react/components/presentational/Result.tsx
index 0b9e024..b33a365 100644
--- a/src/client/react/components/presentational/Result.js
+++ b/src/client/react/components/presentational/Result.tsx
@@ -1,11 +1,10 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classnames from 'classnames';
+import * as React from 'react';
+import * as classnames from 'classnames';
import users from '../../users';
import IconFromUserType from './IconFromUserType';
-const Result = ({ userId, isSelected }) => (
+const Result: React.StatelessComponent<{ userId: string, isSelected: boolean }> = ({ userId, isSelected }) => (
<div
className={classnames('search__result', {
'search__result--selected': isSelected,
@@ -16,9 +15,4 @@ const Result = ({ userId, isSelected }) => (
</div>
);
-Result.propTypes = {
- userId: PropTypes.string.isRequired,
- isSelected: PropTypes.bool.isRequired,
-};
-
export default Result;