containers/Login/index.js

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

import { getFirebaseToken, getLoginError, getUser, hasError } from '../../selectors/common';
import ErrorModal from '../../components/Modals/ErrorModal';
import { MODALS, PAGES, VALIDATION_RULES } from '../../constants';
import validateFields from '../../utils/validation';
import { aClearLoginError } from '../../reducers/common';
import { aLogin } from '../../reducers/actions';
import { withRouterHooks } from '../../utils/router';

const mapToProps = (state) => ({
  loginError: getLoginError(state),
  hasError: hasError(state),
  user: getUser(state),
  firebaseToken: getFirebaseToken(state),
});

const actionsToProps = (dispatch) => ({
  login: (payload) => dispatch(aLogin(payload)),
  clearLoginError: () => dispatch(aClearLoginError()),
});

/**
 * @class
 * @property {object} props
 * @property {string} props.loginError Error for login page
 * @property {string|null} props.hasError Error message for general errors
 * @property {Function} props.login Login API call
 */
class Login extends Component {
  constructor() {
    super();
    /**
     * @member {object}
     * @property {string} username
     * @property {string} password
     */
    this.state = {
      username: '',
      password: '',
      errorMgs: {},
      showPassword: false,
    };
  }

  componentDidUpdate() {
    if (this.props.user) {
      this.props.navigate(PAGES.HOME);
    }
  }

  /**
   * Change username input field
   *
   * @function
   * @param {Event} e
   * @returns {void}
   */
  changeUsername = (e) => {
    this.setState({ username: e.target.value, errorMgs: {} });
  };

  /**
   * Change password input field
   *
   * @function
   * @param {Event} e
   * @returns {void}
   */
  changePassword = (e) => {
    this.setState({ password: e.target.value, errorMgs: {} });
  };

  /**
   * Call API with inserted username & password
   *
   * @function
   * @returns {void}
   */
  login = () => {
    this.props.clearLoginError();
    if (!this.loginInProgress || this.props.loginError) {
      const validationParams = [
        {
          label: 'Username',
          fieldName: 'username',
          value: this.state.username,
          rules: [VALIDATION_RULES.MANDATORY],
        },
        {
          label: 'Password',
          fieldName: 'password',
          value: this.state.password,
          rules: [VALIDATION_RULES.MANDATORY],
        },
      ];
      validateFields(validationParams)
        .then(() => {
          this.props.login({
            username: this.state.username,
            password: this.state.password,
            navigate: this.props.navigate,
            location: this.props.location,
            deviceId: this.props.firebaseToken,
          });
          this.loginInProgress = true;
        })
        .catch((errorMgs) => {
          this.setState({ errorMgs });
        });
    }
  };

  /**
   * @function
   * @param {Event} event
   * @returns {void}
   */
  handleKeyUp = (event) => {
    if (event.key === 'Enter') {
      this.login();
    }
  };

  togglePasswordView = () => {
    this.setState({
      showPassword: !this.state.showPassword,
    });
  };

  /**
   * Render
   *
   * @returns {view}
   */
  render() {
    return this.props.hasError ? (
      <ErrorModal
        message={this.props.hasError}
        setOpenModal={() => {}}
        additionalMessage="Please refresh application"
        modal={MODALS.GENERAL_ERROR}
      />
    ) : (
      <div className="login">
        <div className="login__wrapper">
          <div className="login__heading">Backoffice</div>
          <div className="login__form">
            <div className="s-logo" />
            <div className="login__form-input">
              {this.props.loginError && <div className="error-txt mb-3">{this.props.loginError}</div>}
              <input
                id="username_login"
                type="text"
                onKeyUp={this.handleKeyUp}
                className="form-control"
                placeholder="Username"
                onChange={this.changeUsername}
                value={this.state.username}
              />
              {this.state.errorMgs.username}
            </div>
            <div className="login__form-input">
              <span
                className={`password-toggle 
                    ${this.state.showPassword && 'show'}`}
                onClick={this.togglePasswordView}
              />
              <input
                id="password_login"
                type={this.state.showPassword ? 'text' : 'password'}
                onKeyUp={this.handleKeyUp}
                className="form-control"
                placeholder="Password"
                onChange={this.changePassword}
                value={this.state.password}
              />
              {this.state.errorMgs.password}
            </div>

            <div id="submitBtn_login" className="login__form-button" onClick={this.login}>
              Log in
            </div>
          </div>
        </div>
      </div>
    );
  }
}

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