Source

components/_molecules/Inputs/InputPassword.js

/* eslint-disable prefer-regex-literals */
import React, { useState, useEffect } from "react"
import PropTypes from "prop-types"
import { useTranslation } from "react-i18next"
// chakra-ui
import {
  FormControl,
  Text,
  FormLabel,
  InputGroup,
  InputRightElement,
  IconButton,
  FormHelperText,
} from "@chakra-ui/react"
import { ViewIcon, ViewOffIcon } from "@chakra-ui/icons"
// components
import CustomInput from "components/_atoms/CustomInput"

/**
 * InputPassword Component
 * @component
 * @author Braian D. Vaylet
 * @description Componente Input para el password
 */
export const InputPassword = ({ onChange }) => {
  const [t] = useTranslation("global")
  const [value, setValue] = useState("")
  const [strengths, setStrengths] = useState(null)
  const [message, setMessage] = useState("")
  const [show, setShow] = useState(false)

  useEffect(() => {
    if (value.length > 5) {
      onChange(value)
      setStrengths(handleStrengthIndicator(value))
    }
  }, [value])

  useEffect(() => setMessage(renderStrengthMessage(strengths)), [strengths])

  /**
   * handleHasNumber
   * @function
   * @param {string} value
   * @returns {boolean}
   * @description retorno si el valor posee caracteres numéricos
   */
  const handleHasNumber = (value) => new RegExp(/[0-9]/).test(value)

  /**
   * handleHasMixed
   * @function
   * @param {string} value
   * @returns {boolean}
   * @description retorno si el valor posee caracteres alfanuméricos mayusculas y minusculas
   */
  const handleHasMixed = (value) =>
    new RegExp(/[a-z]/).test(value) && new RegExp(/[A-Z]/).test(value)

  /**
   * handleHasSpecial
   * @function
   * @param {string} value
   * @returns {boolean}
   * @description retorno si el valor posee caracteres especiales
   */
  const handleHasSpecial = (value) =>
    new RegExp(/[!#@$%^&*)(+=._-]/).test(value)

  /**
   * renderStrengthMessage
   * @function
   * @param {number} count
   * @returns {string}
   * @description retorno mensaje
   */
  const renderStrengthMessage = (count) => {
    if (count === 0) return "..."
    if (count < 2)
      return <Text color="red.300">{t("InputPassword.veryWeak")}</Text>
    if (count < 3)
      return <Text color="orange.300">{t("InputPassword.weak")}</Text>
    if (count < 4)
      return <Text color="yellow.300">{t("InputPassword.normal")}</Text>
    if (count < 5)
      return <Text color="teal.300">{t("InputPassword.good")}</Text>
    if (count < 6)
      return <Text color="green.300">{t("InputPassword.veryGood")}</Text>
  }

  /**
   * handleStrengthIndicator
   * @function
   * @param {string} value
   * @returns {number}
   * @description retorno contador de fortaleza de la clave
   */
  const handleStrengthIndicator = (value) => {
    let _strengths = 0
    if (value.length > 5) _strengths++
    if (value.length > 7) _strengths++
    if (handleHasNumber(value)) _strengths++
    if (handleHasSpecial(value)) _strengths++
    if (handleHasMixed(value)) _strengths++
    return _strengths
  }

  /**
   * handleChange
   * @function
   * @returns {string}
   * @description retorno el valor ingresado en el input
   */
  const handleChange = (event) => setValue(event.target.value)

  /**
   * handleShow
   * @function
   * @returns {boolean}
   * @description muestro la contraseña
   */
  const handleShow = () => setShow(!show)

  return (
    <FormControl p={2} isRequired>
      <FormLabel htmlFor="email">{t("InputPassword.title")}</FormLabel>
      <InputGroup>
        <CustomInput
          onChange={handleChange}
          value={value}
          name="password"
          type={show ? true : "password"}
          placeholder="******"
          minLength="5"
        />
        <InputRightElement>
          <IconButton
            size="sm"
            onClick={handleShow}
            icon={show ? <ViewOffIcon /> : <ViewIcon />}
          />
        </InputRightElement>
      </InputGroup>
      <FormHelperText maxH="1.5rem" minH="1.5rem" h="1.5rem" mt="5px">
        {value.length > 0 ? (
          <Text fontSize=".75rem">{message}</Text>
        ) : (
          <Text fontSize=".75rem">{t("InputPassword.useHelp")}</Text>
        )}
      </FormHelperText>
    </FormControl>
  )
}

InputPassword.propTypes = {
  onChange: PropTypes.func.isRequired,
}