Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3230 | Rev 3263 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
2630 stevensc 1
import React, { useRef, useState, useEffect } from 'react'
2
import { Link, useNavigate } from 'react-router-dom'
3
import { useForm } from 'react-hook-form'
4
import { useDispatch, useSelector } from 'react-redux'
3190 stevensc 5
import { Button, styled, Typography } from '@mui/material'
2630 stevensc 6
import { Mail, Lock } from '@mui/icons-material'
7
import Recaptcha from 'react-recaptcha'
8
 
3262 stevensc 9
import { axios } from '@utils'
3190 stevensc 10
import { useMobile } from '@hooks'
3262 stevensc 11
import { asyncLogin } from '@store/auth/auth.actions'
12
import { addNotification } from '@store/notification/notification.actions'
3190 stevensc 13
import CryptoJSAesJson from '@utils/crypto-js/cryptojs-aes-format'
2630 stevensc 14
 
3190 stevensc 15
import FacebookIcon from '@components/UI/icons/FacebookIcon'
16
import XIcon from '@components/UI/icons/XIcon'
17
import GoogleIcon from '@components/UI/icons/GoogleIcon'
18
import Form from '@components/common/form'
19
import Input from '@components/UI/inputs/Input'
20
import CheckboxInput from '@components/UI/inputs/Checkbox'
3262 stevensc 21
import LoadingWrapper from '@components/common/loading-wrapper'
2630 stevensc 22
 
23
const SocialButton = styled(Button)`
24
  background-color: white;
25
  border: 1px solid black;
26
  padding: 0.5rem 1rem;
27
  font-size: 1rem;
28
  color: #383838;
29
  width: 100%;
30
  box-sizing: border-box;
31
  margin-bottom: 10px;
32
  svg {
33
    width: 16px;
34
    height: 16px;
35
  }
36
`
37
 
38
const Login = ({
39
  facebookOauth = '/signin/facebook',
40
  twitterOauth = '/signin/twitter',
41
  googleOauth = '/signin/google'
42
}) => {
43
  const [isVerified, setIsVerified] = useState(false)
3262 stevensc 44
  const reCaptchaInstance = useRef(null)
2630 stevensc 45
  const reCaptchaToken = useRef('')
46
  const navigate = useNavigate()
3262 stevensc 47
  const dispatch = useDispatch()
2630 stevensc 48
 
49
  const { site_key, aes, access_usign_social_networks } = useSelector(
50
    ({ auth }) => auth
51
  )
3262 stevensc 52
 
53
  const socialNetworksAccessAllowed = access_usign_social_networks === 'y'
54
  const isMobile = useMobile()
55
 
2630 stevensc 56
  const rrssOptions = [
57
    { label: 'Facebook', icon: FacebookIcon, href: facebookOauth },
58
    { label: 'Twitter', icon: XIcon, href: twitterOauth },
59
    { label: 'Google', icon: GoogleIcon, href: googleOauth }
60
  ]
61
 
62
  const {
3262 stevensc 63
    formState: { errors, isSubmitting },
64
    control,
2630 stevensc 65
    handleSubmit,
3262 stevensc 66
    reset
2630 stevensc 67
  } = useForm({ mode: 'all' })
68
 
69
  const onSubmitHandler = handleSubmit(
70
    async ({ email, password, remember }) => {
3262 stevensc 71
      try {
72
        const response = await dispatch(
73
          asyncLogin({
74
            email: CryptoJSAesJson.encrypt(email, aes),
75
            password: CryptoJSAesJson.encrypt(password, aes),
76
            remember: remember ? 1 : 0,
77
            captcha: reCaptchaToken.current
78
          })
79
        )
80
        reset()
2630 stevensc 81
 
3262 stevensc 82
        console.log(response)
2630 stevensc 83
 
3262 stevensc 84
        isMobile ? navigate('/apps-navigation') : navigate('/dashboard')
85
      } catch (error) {
86
        dispatch(addNotification({ style: 'danger', msg: error.message }))
87
      } finally {
88
        reCaptchaInstance.current.reset()
89
        loginExpiredCallbackHandler()
90
      }
2630 stevensc 91
    }
92
  )
93
 
94
  const loginVerifyCallbackHandler = (response) => {
95
    reCaptchaToken.current = response
96
    setIsVerified(true)
97
  }
98
 
99
  const loginExpiredCallbackHandler = () => {
100
    reCaptchaToken.current = ''
101
    setIsVerified(false)
102
  }
103
 
104
  const handleOnRecaptchaLoad = () => {
105
    reCaptchaToken.current = ''
106
  }
107
 
108
  const getRedirectUrl = async (endpoint) => {
109
    try {
110
      const res = await axios.get(endpoint)
111
      if (res.data && res.data.data) {
112
        window.location.href = res.data.data
113
      }
114
    } catch (error) {
115
      console.log('>>: error > ', error)
116
    }
117
  }
118
 
119
  useEffect(() => {
120
    reCaptchaInstance.current?.reset()
121
  }, [])
122
 
123
  return (
3190 stevensc 124
    <Form onSubmit={onSubmitHandler}>
3262 stevensc 125
      <LoadingWrapper loading={isSubmitting} displayChildren></LoadingWrapper>
2630 stevensc 126
 
3190 stevensc 127
      <Typography variant='h3'>Entrar</Typography>
128
 
2630 stevensc 129
      <Input
130
        type='email'
131
        name='email'
3038 stevensc 132
        icon={<Mail />}
2630 stevensc 133
        placeholder='Correo electrónico'
2865 stevensc 134
        rules={{
2630 stevensc 135
          required: 'Este campo es requerido',
136
          pattern: {
3230 stevensc 137
            value: /^[\w-.]+@([\w-]+\.)+[\w-]{2,}$/i,
2630 stevensc 138
            message: 'Debe ser una dirección de correo electrónico valida'
139
          },
140
          maxLength: {
141
            value: 64,
142
            message: 'Debe ser menor a 64 caracteres'
143
          }
2865 stevensc 144
        }}
145
        control={control}
2630 stevensc 146
        error={errors.email?.message}
147
      />
148
 
149
      <Input
150
        type='password'
151
        name='password'
3038 stevensc 152
        icon={<Lock />}
2630 stevensc 153
        placeholder='Clave'
2865 stevensc 154
        control={control}
155
        rules={{
2630 stevensc 156
          required: 'Este campo es requerido',
157
          pattern: {
158
            value:
159
              /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$^x%x*-]).{6,16}$/i,
160
            message:
161
              'Debe contener entre 6 y 16 caracteres, incluida una letra mayúscula, un número y un carácter especial #?!@$^%*-'
162
          }
2865 stevensc 163
        }}
2630 stevensc 164
        error={errors.password?.message}
165
      />
166
 
3190 stevensc 167
      <CheckboxInput control={control} name='remember' label='Recuerdame' />
2630 stevensc 168
 
169
      {site_key && (
170
        <Recaptcha
171
          sitekey={site_key}
172
          verifyCallback={loginVerifyCallbackHandler}
173
          verifyCallbackName='loginVerifyCallbackHandler'
174
          expiredCallback={loginExpiredCallbackHandler}
175
          expiredCallbackName='loginExpiredCallbackHandler'
176
          ref={reCaptchaInstance}
177
          render='explicit'
178
          onloadCallback={handleOnRecaptchaLoad}
179
          hl='es'
180
        />
181
      )}
182
 
183
      <div className='links'>
184
        <Link to='/forgot-password'>¿Has olvidado tu contraseña?</Link>
185
        <Link to='/signup'>¿No tienes cuenta?</Link>
186
      </div>
187
 
3156 stevensc 188
      <Button color='secondary' type='submit' disabled={!isVerified}>
2630 stevensc 189
        Entrar
190
      </Button>
191
 
3262 stevensc 192
      {socialNetworksAccessAllowed && (
2630 stevensc 193
        <>
194
          <h4>Entrar usando su red social</h4>
195
          <ul>
196
            {rrssOptions.map(({ label, icon: Icon, href }) => (
197
              <li key={label}>
198
                <SocialButton onClick={() => getRedirectUrl(href)}>
199
                  <Icon />
200
                  {`Iniciar sesión con ${label}`}
201
                </SocialButton>
202
              </li>
203
            ))}
204
          </ul>
205
        </>
206
      )}
3190 stevensc 207
    </Form>
2630 stevensc 208
  )
209
}
210
 
211
export default Login