spolnik/JAlgoArena-UI

View on GitHub
src/client/users/pages/signup.tsx

Summary

Maintainability
F
3 days
Test Coverage
import * as React from 'react';
import {MouseEvent} from 'react';
import * as dom from 'react-dom';
import {Button, Col, ControlLabel, FormControl, FormGroup, Grid, HelpBlock, PageHeader} from 'react-bootstrap';
import {connect} from 'react-redux';
 
import FontAwesome from '../../common/components/FontAwesome';
import FieldGroup from '../../common/components/FieldGroup';
 
import {validateEmail, validatePassword, validateUserName} from '../utilities/RegexValidators';
import {attemptSignUp, fetchUsers, navigatedAwayFromAuthFormPage, startSignup} from "../actions";
import ErrorLabel from "../components/ErrorLabel";
 
import {fetchSubmissionStats} from "../../submissions/actions";
import {Dispatch} from "redux";
import {AppState, Config} from "../../common/reducers";
import {AuthState} from "../reducers";
 
const initialFormState = {
errorMessage: null,
isUserNameFieldIncorrect : false,
isFirstNameFieldIncorrect : false,
isSurnameFieldIncorrect : false,
isEmailFieldIncorrect : false,
isPasswordFieldIncorrect : false,
isConfirmPasswordFieldIncorrect : false
} as SignupState;
 
interface SignupForm {
email: string
password: string
confirmedPassword: string
username: string
region: string
team: string
firstname: string
surname: string
}
 
interface SignupProps {
auth: AuthState
config: Config
onUnmount: () => void
onSignUp: (formData: SignupForm) => void
}
 
interface SignupState {
errorMessage: string | null
isUserNameFieldIncorrect: boolean
isFirstNameFieldIncorrect: boolean
isSurnameFieldIncorrect: boolean
isEmailFieldIncorrect: boolean
isPasswordFieldIncorrect: boolean
isConfirmPasswordFieldIncorrect: boolean
}
 
interface InputElement extends HTMLInputElement {
focus: () => void
value: string
}
 
class SignUp extends React.Component<SignupProps, SignupState> {
 
private username: InputElement;
private password: InputElement;
private email: InputElement;
private firstname: InputElement;
private surname: InputElement;
private confirmPassword: InputElement;
private region: InputElement;
private team: InputElement;
 
Similar blocks of code found in 2 locations. Consider refactoring.
constructor(props: SignupProps) {
super(props);
this.state = Object.assign({}, initialFormState);
this.onSignUp = this.onSignUp.bind(this);
}
 
Function `componentDidUpdate` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.
componentDidUpdate() {
Similar blocks of code found in 3 locations. Consider refactoring.
if (this.props.auth.error === 'User name is already used') {
if(!this.state.isUserNameFieldIncorrect){
let newState = Object.assign({}, this.state, {isUserNameFieldIncorrect: true});
this.setState(newState);
}
SignUp.focusOn(this.username);
}
 
Similar blocks of code found in 3 locations. Consider refactoring.
if (this.props.auth.error === "Email is already used") {
if(!this.state.isEmailFieldIncorrect){
let newState = Object.assign({}, this.state, {isEmailFieldIncorrect: true});
this.setState(newState);
}
SignUp.focusOn(this.email);
}
}
 
componentWillUnmount() {
this.props.onUnmount();
}
 
Identical blocks of code found in 2 locations. Consider refactoring.
private static focusOn(ref: InputElement) {
let inputElement = dom.findDOMNode(ref) as InputElement;
if (inputElement) {
inputElement.focus();
}
}
 
Function `findErrorsInSignupForm` has 43 lines of code (exceeds 25 allowed). Consider refactoring.
Function `findErrorsInSignupForm` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.
static findErrorsInSignupForm(formData: SignupForm, emailRegex: string, emailErrorMessage: string) {
 
let newState = Object.assign({}, initialFormState);
 
if (formData.username === "") {
newState.errorMessage = "A user name is required";
newState.isUserNameFieldIncorrect = true;
}
else if (!validateUserName(formData.username)) {
newState.errorMessage = "Please enter a valid user name containing alphanumerics, dashes (-), and/or underscores (_)";
newState.isUserNameFieldIncorrect = true;
}
else if (formData.email === "") {
newState.errorMessage = "Email is required";
newState.isEmailFieldIncorrect = true;
}
else if (!validateEmail(formData.email, emailRegex)) {
newState.errorMessage = emailErrorMessage;
newState.isEmailFieldIncorrect = true;
}
else if (formData.firstname === "") {
newState.errorMessage = "First Name is required";
newState.isFirstNameFieldIncorrect = true;
}
else if (formData.surname === "") {
newState.errorMessage = "Surname is required";
newState.isSurnameFieldIncorrect = true;
}
else if (formData.password === "") {
newState.errorMessage = "Password is required";
newState.isPasswordFieldIncorrect = true;
}
else if(!validatePassword(formData.password)) {
newState.errorMessage = "Your password must contain at least 6 valid characters";
newState.isPasswordFieldIncorrect = true;
}
else if (formData.confirmedPassword === "") {
newState.errorMessage = "Please confirm your password";
newState.isConfirmPasswordFieldIncorrect = true;
}
else if (formData.confirmedPassword !== formData.password) {
newState.errorMessage = "The passwords don't match";
newState.isConfirmPasswordFieldIncorrect = true;
newState.isPasswordFieldIncorrect = true;
}
 
return newState;
}
 
onSignUp(e: MouseEvent<Button>){
e.preventDefault();
 
let formData = {
username: (dom.findDOMNode(this.username) as InputElement).value.trim(),
email: (dom.findDOMNode(this.email) as InputElement).value.trim(),
firstname: (dom.findDOMNode(this.firstname) as InputElement).value.trim(),
surname: (dom.findDOMNode(this.surname) as InputElement).value.trim(),
password: (dom.findDOMNode(this.password) as InputElement).value.trim(),
confirmedPassword: (dom.findDOMNode(this.confirmPassword) as InputElement).value.trim(),
region: (dom.findDOMNode(this.region) as InputElement).value.trim(),
team: (dom.findDOMNode(this.team) as InputElement).value.trim()
};
 
let newState = SignUp.findErrorsInSignupForm(
formData,
this.props.config.emailRegex,
this.props.config.emailErrorMessage
);
 
this.setState(newState);
if (!newState.errorMessage){
this.props.onSignUp(formData);
}
}
 
componentDidMount(){
SignUp.focusOn(this.username);
}
 
Function `render` has 56 lines of code (exceeds 25 allowed). Consider refactoring.
Function `render` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.
render() {
let regions = this.props.config.regions;
let teams = this.props.config.teams;
 
let regionOptions = regions.map(region => <option>{region}</option>);
let teamOptions = teams.map(team => <option>{team}</option>);
 
return (
<Grid>
<Col mdOffset={4} md={4}>
<form>
<PageHeader className="text-center">Create Account</PageHeader>
<ErrorLabel validationError={this.state.errorMessage} authError={this.props.auth.error} />
Similar blocks of code found in 2 locations. Consider refactoring.
<FormGroup controlId="region">
<ControlLabel>Region</ControlLabel>
<FormControl componentClass="select" inputRef={ref => { this.region = ref; }}>
{regionOptions}
</FormControl>
</FormGroup>
Similar blocks of code found in 2 locations. Consider refactoring.
<FormGroup controlId="team">
<ControlLabel>Team</ControlLabel>
<FormControl componentClass="select" inputRef={ref => { this.team = ref; }}>
{teamOptions}
</FormControl>
</FormGroup>
Similar blocks of code found in 6 locations. Consider refactoring.
<FieldGroup id="firstname" type="text" placeholder="First Name"
inputRef={ref => { this.firstname = ref; }}
validationState={this.state.isFirstNameFieldIncorrect ? "error" : null}
/>
Similar blocks of code found in 6 locations. Consider refactoring.
<FieldGroup id="surname" type="text" placeholder="Surname"
inputRef={ref => { this.surname = ref; }}
validationState={this.state.isSurnameFieldIncorrect ? "error" : null}
/>
Similar blocks of code found in 6 locations. Consider refactoring.
<FieldGroup id="username" type="text" placeholder="Username"
inputRef={ref => { this.username = ref; }}
validationState={this.state.isUserNameFieldIncorrect ? "error" : null}
/>
Similar blocks of code found in 6 locations. Consider refactoring.
<FieldGroup id="email" type="text" placeholder="Email"
inputRef={ref => { this.email = ref; }}
validationState={this.state.isEmailFieldIncorrect ? "error" : null}
/>
Similar blocks of code found in 6 locations. Consider refactoring.
<FieldGroup id="password" type="password" placeholder="Password"
inputRef={ref => { this.password = ref; }}
validationState={this.state.isPasswordFieldIncorrect ? "error" : null}
/>
Similar blocks of code found in 6 locations. Consider refactoring.
<FieldGroup id="confirmPassword" type="password" placeholder="Confirm Password"
inputRef={ref => { this.confirmPassword = ref; }}
validationState={this.state.isConfirmPasswordFieldIncorrect ? "error" : null}
/>
<Button type="submit" bsStyle="success" block onClick={this.onSignUp}>
<FontAwesome prefix="fas" name="user"/> Create Account
</Button>
<HelpBlock>
By creating account you agree to our <a href="/#/codeOfConduct" target="_blank">Code of Conduct</a>
</HelpBlock>
</form>
</Col>
</Grid>
);
}
}
 
const mapStateToProps = (state: AppState) => {
return {
auth: state.auth,
config: state.config
};
};
 
const mapDispatchToProps = (dispatch: Dispatch<any>) => {
return {
onSignUp: (formData: SignupForm) => {
dispatch(startSignup());
dispatch<any>(attemptSignUp(
formData.email, formData.password, formData.username,
formData.region, formData.team, formData.firstname, formData.surname
));
dispatch<any>(fetchUsers());
dispatch<any>(fetchSubmissionStats());
},
onUnmount: () => {
dispatch(navigatedAwayFromAuthFormPage());
}
}
};
 
const SignUpPage = connect(
mapStateToProps,
mapDispatchToProps
)(SignUp);
 
export {SignUpPage};