Skip to content

Commit 744bbf1

Browse files
committed
get token from url
1 parent bdebc53 commit 744bbf1

File tree

7 files changed

+151
-110
lines changed

7 files changed

+151
-110
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"scripts": {
88
"predeploy": "npm run build",
99
"test": "jest -i",
10-
"start": "webpack-dev-server --mode development --hot --progress --color --port 3000 --host 0.0.0.0",
10+
"start": "webpack-dev-server --mode development --hot --progress --color --port 3000",
1111
"build": "webpack -p --progress --colors",
1212
"lint": "prettier --write \"src/**/*.{ts,tsx,css}\" \"__tests__/**/*.{ts,tsx,css}\" && tslint --project .",
1313
"lint:fix": "tslint --project . --fix"

src/app/actions/User.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ export namespace UserActions {
6464
export const checkUsernameExists = (username: string) =>
6565
action(Type.CHECK_USERNAME_EXISTS, { username });
6666

67-
export const changeUserPassword = (changePasswordDetails: UserInterfaces.ChangeUserPassword) =>
68-
action(Type.CHANGE_USER_PASSWORD, changePasswordDetails);
67+
export const changeUserPassword = (newPassword: string, passwordResetToken: string) =>
68+
action(Type.CHANGE_USER_PASSWORD, {
69+
newPassword,
70+
passwordResetToken,
71+
});
6972

7073
export const toggleUserProfileModal = (isUserProfileModalOpen: boolean) =>
7174
action(Type.TOGGLE_USER_PROFILE_MODAL, { isUserProfileModalOpen });

src/app/apiFetch/User.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export const changeUserPassword = (body: UserInterfaces.ChangeUserPassword) => {
119119
Accept: 'application/json',
120120
'Content-Type': 'application/json',
121121
},
122+
method: 'POST',
122123
})
123124
.then((response) => {
124125
console.log('api fetch response');
Lines changed: 131 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,143 @@
11
import * as authStyles from 'app/styles/Authentication.module.css';
22
import * as registerStyles from 'app/styles/Register.module.css';
3-
import { changePasswordProps } from 'app/types/Authentication/ChangePassword';
3+
import { changePasswordProps, ChangePasswordState } from 'app/types/Authentication/ChangePassword';
44
import classnames from 'classnames';
55
import * as React from 'react';
66

7-
// tslint:disable-next-line: variable-name
8-
export const ChangePassword: React.FunctionComponent<changePasswordProps> = (
9-
props: changePasswordProps,
10-
) => {
11-
let passwordResetToken: string;
12-
const [password, setPassword] = React.useState('');
13-
const [repeatPassword, setRepeatPassword] = React.useState('');
14-
const [passwordError, setpasswordError] = React.useState('');
15-
const submitPassword = (e: React.MouseEvent) => {
7+
export class ChangePassword extends React.Component<changePasswordProps, ChangePasswordState> {
8+
private credentialsFormRef = React.createRef<HTMLFormElement>();
9+
private passwordResetToken = '';
10+
constructor(props: changePasswordProps) {
11+
super(props);
12+
this.state = {
13+
password: '',
14+
passwordError: '',
15+
repeatPassword: '',
16+
};
17+
}
18+
19+
public componentDidMount() {
20+
// get string from url
21+
const search = this.props.location.search;
22+
this.passwordResetToken = search.split('=')[1];
23+
}
24+
25+
public render() {
26+
return (
27+
<div className={classnames(authStyles.registerRoot)}>
28+
<div className={classnames(authStyles.registerMessage)}>
29+
<h1 className={classnames(authStyles['register-h1'])}> Reset Password </h1>
30+
<p> Enter your new password </p>
31+
</div>
32+
<div className={classnames('col-sm-12', authStyles.form)}>
33+
<form
34+
className={classnames(
35+
'registerForm d-flex flex-wrap',
36+
authStyles['main-register-form'],
37+
)}
38+
noValidate
39+
>
40+
<div className={classnames(authStyles['stage-div'])}>
41+
<form
42+
className={classnames(authStyles['stage-form'])}
43+
noValidate
44+
ref={this.credentialsFormRef}
45+
>
46+
<div className={classnames(authStyles['login-label'])}> New Password </div>
47+
<div className={classnames(registerStyles['input-group'])}>
48+
<input
49+
type="password"
50+
className={classnames('form-control', authStyles['register-input'])}
51+
id="registerValidationPassword"
52+
aria-describedby="inputGroupPrepend"
53+
pattern=".{5,}"
54+
value={this.state.password}
55+
onChange={(e) =>
56+
this.setState({
57+
password: e.target.value,
58+
})
59+
}
60+
required
61+
/>
62+
<div className={classnames('invalid-feedback', authStyles['register-error'])}>
63+
Password should have minimum 5 characters.
64+
</div>
65+
</div>
66+
<div className={classnames(authStyles['login-label'])}> Confirm Password </div>
67+
<div className={classnames(registerStyles['input-group'])}>
68+
<input
69+
type="password"
70+
className={classnames('form-control', authStyles['register-input'])}
71+
id="registerValidationrepeatPassword"
72+
aria-describedby="inputGroupPrepend"
73+
pattern=".{5,}"
74+
value={this.state.repeatPassword}
75+
onChange={(e) =>
76+
this.setState({
77+
repeatPassword: e.target.value,
78+
})
79+
}
80+
required
81+
/>
82+
</div>
83+
84+
<div
85+
className={
86+
this.state.passwordError !== ''
87+
? classnames('form-row', authStyles['register-error-active'])
88+
: classnames('form-row', authStyles['register-error-inactive'])
89+
}
90+
>
91+
<div
92+
className={classnames(
93+
'col text-center mt -0 mb-2 errorMessage',
94+
registerStyles.errorMessage,
95+
)}
96+
>
97+
{this.state.passwordError}
98+
{'\n'}
99+
{this.props.errorMessage}
100+
</div>
101+
</div>
102+
<div
103+
className={classnames(
104+
registerStyles['input-group'],
105+
'd-flex justify-content-center',
106+
)}
107+
>
108+
<button
109+
className={classnames(authStyles['register-button'])}
110+
onClick={(e) => this.submitPassword(e)}
111+
>
112+
Confirm
113+
</button>
114+
</div>
115+
</form>
116+
</div>
117+
</form>
118+
</div>
119+
</div>
120+
);
121+
}
122+
123+
private submitPassword = (e: React.MouseEvent) => {
16124
e.preventDefault();
17-
if (password !== '') {
18-
if (password.length >= 5) {
19-
if (password === repeatPassword) {
20-
setpasswordError('');
21-
props.changePassword({
22-
passwordResetToken,
23-
newPassword: password,
125+
if (this.state.password === this.state.repeatPassword) {
126+
if (this.credentialsFormRef.current) {
127+
this.credentialsFormRef.current.classList.add('was-validated');
128+
if (this.credentialsFormRef.current.checkValidity()) {
129+
this.setState({
130+
...this.state,
131+
passwordError: '',
24132
});
25-
} else {
26-
setpasswordError('Password and confirm passwords have different values');
133+
this.props.changePassword(this.state.password, this.passwordResetToken);
27134
}
28-
} else {
29-
setpasswordError('Password should have minimum 5 letters');
30135
}
31136
} else {
32-
setpasswordError('Password cannot be empty');
137+
this.setState({
138+
...this.state,
139+
passwordError: 'Password and confirm passwords have different values',
140+
});
33141
}
34142
};
35-
React.useEffect(() => {
36-
// get string from url
37-
passwordResetToken = 'token from url';
38-
});
39-
return (
40-
<div className={classnames(authStyles.registerRoot)}>
41-
<div className={classnames(authStyles.registerMessage)}>
42-
<h1 className={classnames(authStyles['register-h1'])}> Reset Password </h1>
43-
<p> Enter your new password </p>
44-
</div>
45-
<div className={classnames('col-sm-12', authStyles.form)}>
46-
<form
47-
className={classnames('registerForm d-flex flex-wrap', authStyles['main-register-form'])}
48-
noValidate
49-
>
50-
<div className={classnames(authStyles['stage-div'], authStyles['stage-form'])}>
51-
<div className={classnames(authStyles['login-label'])}> New Password </div>
52-
<div className={classnames(registerStyles['input-group'])}>
53-
<input
54-
type="password"
55-
className={classnames('form-control', authStyles['register-input'])}
56-
id="registerValidationPassword"
57-
aria-describedby="inputGroupPrepend"
58-
pattern=".{5,}"
59-
value={password}
60-
onChange={(e) => setPassword(e.target.value)}
61-
required
62-
/>
63-
<div className={classnames('invalid-feedback', authStyles['register-error'])}>
64-
Password should have minimum 5 characters.
65-
</div>
66-
</div>
67-
<div className={classnames(authStyles['login-label'])}> Confirm Password </div>
68-
<div className={classnames(registerStyles['input-group'])}>
69-
<input
70-
type="password"
71-
className={classnames('form-control', authStyles['register-input'])}
72-
id="registerValidationrepeatPassword"
73-
aria-describedby="inputGroupPrepend"
74-
pattern=".{5,}"
75-
value={repeatPassword}
76-
onChange={(e) => setRepeatPassword(e.target.value)}
77-
required
78-
/>
79-
</div>
80-
81-
<div
82-
className={
83-
passwordError !== ''
84-
? classnames('form-row', authStyles['register-error-active'])
85-
: classnames('form-row', authStyles['register-error-inactive'])
86-
}
87-
>
88-
<div
89-
className={classnames(
90-
'col text-center mt -0 mb-2 errorMessage',
91-
registerStyles.errorMessage,
92-
)}
93-
>
94-
{passwordError}
95-
{'\n'}
96-
{props.errorMessage}
97-
</div>
98-
</div>
99-
<div
100-
className={classnames(registerStyles['input-group'], 'd-flex justify-content-center')}
101-
>
102-
<button
103-
className={classnames(authStyles['register-button'])}
104-
onClick={(e) => submitPassword(e)}
105-
>
106-
Confirm
107-
</button>
108-
</div>
109-
</div>
110-
</form>
111-
</div>
112-
</div>
113-
);
114-
};
143+
}

src/app/containers/Authentication/ChangePassword.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ import { ChangePassword } from 'app/components/Authentication/ChangePassword';
33
import { RootState } from 'app/reducers';
44
import { DispatchProps, StateProps } from 'app/types/Authentication/ChangePassword';
55
import { connect } from 'react-redux';
6+
import { withRouter } from 'react-router';
67

78
const mapStateToProps = (rootState: RootState) => {
89
return {
910
errorMessage: rootState.user.errorMessage,
1011
};
1112
};
1213

14+
const componentWithRouter = withRouter(ChangePassword);
15+
1316
const changePasswordContainer = connect<StateProps, DispatchProps, {}>(mapStateToProps, {
1417
changePassword: UserActions.changeUserPassword,
15-
})(ChangePassword);
18+
})(componentWithRouter);
1619

1720
export default changePasswordContainer;

src/app/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const App = hot(module)(() => (
2424
<Route exact path={Routes.REGISTER} component={Register} />
2525
<Route exact path={Routes.LEADERBOARD} component={Leaderboard} />
2626
<Route exact path={Routes.USER_PROFILE_MODEL} component={UserProfileModal} />
27-
<Route path={Routes.CHANGE_PASSWORD} component={ChangePassword} />
27+
<Route path="/forgot-password" component={ChangePassword} />
2828
</Switch>
2929
<Sugar background="#484848" color="white" />
3030
</BrowserRouter>
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import { ChangeUserPassword } from 'app/types/User';
1+
import { RouteComponentProps } from 'react-router-dom';
22

3+
export interface ChangePasswordState {
4+
password: string;
5+
repeatPassword: string;
6+
passwordError: string;
7+
}
38
export interface StateProps {
49
errorMessage: string;
510
}
611

712
export interface DispatchProps {
8-
changePassword: (changePasswordDetails: ChangeUserPassword) => void;
13+
changePassword: (password: string, passwordResetToken: string) => void;
914
}
1015

11-
export type changePasswordProps = StateProps & DispatchProps;
16+
export type changePasswordProps = StateProps & DispatchProps & RouteComponentProps;

0 commit comments

Comments
 (0)