colouring-montreal/app/src/frontend/user/signup.tsx

183 lines
7.2 KiB
TypeScript
Raw Normal View History

import React, { Component } from 'react';
2019-11-07 02:39:26 -05:00
import { Link, Redirect } from 'react-router-dom';
import ErrorBox from '../components/error-box';
import InfoBox from '../components/info-box';
import SupporterLogos from '../components/supporter-logos';
import { User } from '../models/user';
2018-09-13 11:58:05 -04:00
interface SignUpProps {
login: (user: User) => void;
user: User;
}
interface SignUpState {
username: string;
email: string;
confirm_email: string;
show_password: boolean;
password: string;
confirm_conditions: boolean;
error: string;
}
class SignUp extends Component<SignUpProps, SignUpState> {
constructor(props) {
super(props);
this.state = {
username: '',
email: '',
confirm_email: '',
password: '',
show_password: false,
2018-09-13 11:58:05 -04:00
confirm_conditions: false,
error: undefined
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name: keyof SignUpState = target.name;
this.setState({
[name]: value
} as Pick<SignUpState, keyof SignUpState>);
}
handleSubmit(event) {
event.preventDefault();
2018-09-13 12:02:27 -04:00
this.setState({error: undefined})
2019-08-14 09:05:49 -04:00
fetch('/api/users', {
method: 'POST',
body: JSON.stringify(this.state),
headers:{
2019-05-27 11:39:16 -04:00
'Content-Type': 'application/json'
},
credentials: 'same-origin'
}).then(
res => res.json()
).then(function(res){
if (res.error) {
2018-09-13 11:58:05 -04:00
this.setState({error: res.error})
} else {
2019-08-14 09:05:49 -04:00
fetch('/api/users/me', {
credentials: 'same-origin'
}).then(
2018-09-13 11:58:05 -04:00
(res) => res.json()
).then(
(user) => this.props.login(user)
).catch(
(err) => this.setState({error: err})
)
}
2018-09-13 11:58:05 -04:00
}.bind(this)).catch(
(err) => this.setState({error: err})
);
}
render() {
if (this.props.user) {
return <Redirect to="/my-account.html" />
}
return (
<article>
<section className="main-col">
<h1 className="h2">Sign up</h1>
<InfoBox msg="Welcome to Colouring London. You're one of the first people to sign up! ">
<br/>Please <a href="https://discuss.colouring.london/">discuss
suggestions for improvements</a> and <a
2019-05-27 11:39:16 -04:00
href="https://github.com/tomalrussell/colouring-london/issues">
report issues or problems</a>.
</InfoBox>
<p>
Create an account to start colouring in.
</p>
2018-09-13 11:58:05 -04:00
<ErrorBox msg={this.state.error} />
<form onSubmit={this.handleSubmit}>
<label htmlFor="username">Username*</label>
<input name="username" id="username"
2019-05-27 11:39:16 -04:00
className="form-control" type="text"
value={this.state.username} onChange={this.handleChange}
placeholder="not-your-real-name" required
minLength={4}
maxLength={30}
pattern="\w+"
title="Usernames can contain only letters, numbers and the underscore"
2019-05-27 11:39:16 -04:00
/>
<label htmlFor="email">Email (optional)</label>
<input name="email" id="email"
2019-05-27 11:39:16 -04:00
className="form-control" type="email"
value={this.state.email} onChange={this.handleChange}
placeholder="someone@example.com"
/>
<InfoBox msg="Please note that if you forget your password, you will only be able to recover your account if you provide an email address." />
<label htmlFor="confirm_email">Confirm email (optional)</label>
<input name="confirm_email" id="confirm_email"
2019-05-27 11:39:16 -04:00
className="form-control" type="email"
value={this.state.confirm_email} onChange={this.handleChange}
/>
<label htmlFor="password">Password (at least 8 characters)</label>
<input name="password" id="password"
2019-05-27 11:39:16 -04:00
className="form-control"
type={(this.state.show_password)? 'text': 'password'}
value={this.state.password} onChange={this.handleChange}
required
minLength={8}
maxLength={128}
2019-05-27 11:39:16 -04:00
/>
<div className="form-check">
<input id="show_password" name="show_password"
2019-05-27 11:39:16 -04:00
className="form-check-input" type="checkbox"
checked={this.state.show_password}
onChange={this.handleChange}
/>
2018-09-13 11:58:05 -04:00
<label className="form-check-label" htmlFor="show_password">
Show password?
</label>
</div>
<div className="form-check">
<input id="confirm_conditions" name="confirm_conditions"
2019-05-27 11:39:16 -04:00
className="form-check-input" type="checkbox"
checked={this.state.confirm_conditions}
onChange={this.handleChange}
required />
2018-09-13 11:58:05 -04:00
<label className="form-check-label" htmlFor="confirm_conditions">
I confirm that I have read and agree to the <Link
2019-10-02 14:26:18 -04:00
to="/privacy-policy.html">privacy policy</Link>, <Link
to="/contributor-agreement.html">contributor agreement</Link> and <Link
to="/data-accuracy.html">data accuracy agreement</Link>.
</label>
</div>
<div className="buttons-container with-space">
2018-09-13 11:09:41 -04:00
<input type="submit" value="Sign Up" className="btn btn-primary" />
</div>
Do you already have an account?
<div className="buttons-container with-space">
2018-09-13 11:09:41 -04:00
<Link to="login.html" className="btn btn-outline-dark">Log in</Link>
</div>
</form>
</section>
<hr />
<section className="main-col">
<SupporterLogos />
</section>
</article>
)
}
}
export default SignUp;