containers/Login/index.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

import Constants, { SVG_ICONS } from '../../constants';
import { loginRequest, changePage, clearLoginError } from '../../reducers';
import {
  getUser, getIsLoading, getLoginError, getDestinations,
} from '../../store/common';
import SVGComponent from '../../components/SVG/SVGComponent';
import validateFields from '../../utils/validation';

const mapToProps = (state) => ({
  user: getUser(state),
  isLoading: getIsLoading(state),
  loginError: getLoginError(state),
  destinations: getDestinations(state),
});

const actionsToProps = (dispatch) => ({
  login: (payload) => dispatch(loginRequest(payload)),
  changePage: (payload) => dispatch(changePage(payload)),
  clearLoginError: () => dispatch(clearLoginError()),
});

/**
 * @class
 * @property {object} props
 * @property {string} props.loginError Login error message from API
 * @property {object} props.user Destination informations
 * @property {boolean} props.isLoading Indicate is login API is fetch
 *
 * @property {Function} props.login Login API call
 * @property {Function} props.changePage Change page
 */
class Login extends Component {
  constructor() {
    super();
    /**
     * @member {object}
     * @property {boolean} username
     * @property {boolean} password
     * @property {object} errorMgs
     */
    this.state = {
      username: '',
      password: '',
      errorMgs: {},
    };
  }

  /**
   * Go to BETS page if user is logged in
   *
   * @returns {void}
   */
  componentDidMount() {
    if (this.props.user) {
      this.props.changePage({ page: Constants.PAGES.BETS });
    }
  }

  /**
   * Change input value depending on field id
   *
   * @function
   * @param {Event} e
   * @returns {void}
   */
  handleChangeValue = (e) => {
    e.persist();
    const data = this.state;
    data[e.target.id] = e.target.value;
    this.setState({ ...this.data, errorMgs: {} });
  }

  /**
   * Call API with inserted username & password
   *
   * @function
   * @returns {void}
   */
  login = async () => {
    this.props.clearLoginError();
    if (!this.loginInProgress || this.props.loginError) {
      const validationParams = [
        {
          label: 'Username',
          fieldName: 'username',
          value: this.state.username,
          rules: ['mandatory'],
        },
        {
          label: 'Password',
          fieldName: 'password',
          value: this.state.password,
          rules: ['mandatory'],
        },
      ];
      try {
        await validateFields(validationParams);
        this.props.login({
          username: this.state.username,
          password: this.state.password,
        });
        this.loginInProgress = true;
      } catch (err) {
        this.setState({ errorMgs: err });
        this.loginInProgress = false;
      }
    }
  }

  /**
   * Render
   *
   * @returns {view}
   */
  render() {
    return (
      <>
        {this.props.loginError && (
          <div className="login-error">
            <SVGComponent
              className="login-error__icon"
              src={`${SVG_ICONS.warning}#warning`}
            />
            <div className="login-error__text">
              {this.props.loginError}
            </div>
          </div>
        )}
        <div className="m-logo" />
        <div className={`row l-form no-gutters ${this.props.loginError
          || this.state.errorMgs.username
          || this.state.errorMgs.password
          ? 'l-form--error' : ''}`}
        >
          <div className="col-sm-12 mb-3">
            <input
              type="text"
              id="username"
              className="form-control"
              placeholder="Username"
              onChange={this.handleChangeValue}
              value={this.state.username}
            />
            {this.state.errorMgs.username}
          </div>
          <div className="col-sm-12 mb-3">
            <input
              type="password"
              id="password"
              className="form-control"
              placeholder="Password"
              onChange={this.handleChangeValue}
              value={this.state.password}
            />
            {this.state.errorMgs.password}
          </div>
          <div className="col-sm-12 mb-3" onClick={this.login}>
            <button className="btn btn-primary btn-block" type="button">Login</button>
          </div>
          <div className="col-sm-12 text-center">
            <a
              className="l-form__link"
              title="Forgotten Details?"
              href={this.props.destinations.passwordRecovery}
            >
              Forgot your password?
            </a>
          </div>
        </div>
        {this.props.isLoading && (
          <div className="loading-wrap">
            <div className="loading-item" />
          </div>
        )}

      </>
    );
  }
}

export default connect(
  mapToProps,
  actionsToProps,
)(Login);