Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3190 | Rev 3262 | 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
 
3190 stevensc 9
import { useMobile } from '@hooks'
10
import CryptoJSAesJson from '@utils/crypto-js/cryptojs-aes-format'
2630 stevensc 11
 
3190 stevensc 12
import FacebookIcon from '@components/UI/icons/FacebookIcon'
13
import XIcon from '@components/UI/icons/XIcon'
14
import GoogleIcon from '@components/UI/icons/GoogleIcon'
15
import { axios } from '@utils'
16
import { addNotification } from '@store/notification/notification.actions'
17
import { login } from '@store/auth/auth.actions'
18
import Form from '@components/common/form'
19
import Input from '@components/UI/inputs/Input'
20
import CheckboxInput from '@components/UI/inputs/Checkbox'
21
import Spinner from '@components/UI/Spinner'
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 [isLoading, setIsLoading] = useState(false)
44
  const [isVerified, setIsVerified] = useState(false)
2888 stevensc 45
  const isMobile = useMobile()
2630 stevensc 46
 
47
  const reCaptchaToken = useRef('')
48
  const reCaptchaInstance = useRef(null)
49
 
50
  const navigate = useNavigate()
51
 
52
  const dispatch = useDispatch()
53
  const { site_key, aes, access_usign_social_networks } = useSelector(
54
    ({ auth }) => auth
55
  )
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 {
63
    handleSubmit,
64
    control,
65
    setError,
66
    getValues,
67
    setValue,
2802 stevensc 68
    reset,
69
    formState: { errors }
2630 stevensc 70
  } = useForm({ mode: 'all' })
71
 
72
  const onSubmitHandler = handleSubmit(
73
    async ({ email, password, remember }) => {
74
      const formData = new FormData()
75
      formData.append('email', CryptoJSAesJson.encrypt(email, aes))
76
      formData.append('password', CryptoJSAesJson.encrypt(password, aes))
77
      formData.append('remember', remember ? 1 : 0)
78
      formData.append('captcha', reCaptchaToken.current)
79
 
80
      await axios
81
        .post('/signin', formData)
82
        .then(({ data: response }) => {
83
          const { success, data } = response
84
 
85
          if (!success) {
86
            loginExpiredCallbackHandler()
87
            reCaptchaInstance.current.reset()
88
 
89
            if (data.constructor.name === 'Object') {
90
              Object.entries(data).forEach(([key, value]) => {
91
                if (key in getValues()) {
92
                  setError(key, {
93
                    type: 'manual',
94
                    message: Array.isArray(value) ? value[0] : value
95
                  })
96
                }
97
              })
98
              return
99
            }
100
 
101
            dispatch(addNotification({ style: 'danger', msg: data }))
102
            return
103
          }
104
 
105
          const url = data.redirect.split('.com')[1]
106
          reCaptchaInstance.current.reset()
107
          loginExpiredCallbackHandler()
108
          reset()
109
          dispatch(login())
2888 stevensc 110
 
2960 stevensc 111
          isMobile ? navigate('/apps-navigation') : navigate(url)
2630 stevensc 112
        })
113
        .catch((err) => {
114
          console.log(err)
115
          reCaptchaInstance.current.reset()
116
 
117
          loginExpiredCallbackHandler()
118
          setValue('password', '')
119
 
120
          dispatch(
121
            addNotification({
122
              style: 'danger',
123
              msg: 'Disculpe, ha ocurrido un error'
124
            })
125
          )
126
        })
127
        .finally(() => setIsLoading(false))
128
    }
129
  )
130
 
131
  const loginVerifyCallbackHandler = (response) => {
132
    reCaptchaToken.current = response
133
    setIsVerified(true)
134
  }
135
 
136
  const loginExpiredCallbackHandler = () => {
137
    reCaptchaToken.current = ''
138
    setIsVerified(false)
139
  }
140
 
141
  const handleOnRecaptchaLoad = () => {
142
    reCaptchaToken.current = ''
143
  }
144
 
145
  const getRedirectUrl = async (endpoint) => {
146
    try {
147
      const res = await axios.get(endpoint)
148
      if (res.data && res.data.data) {
149
        window.location.href = res.data.data
150
      }
151
    } catch (error) {
152
      console.log('>>: error > ', error)
153
    }
154
  }
155
 
156
  useEffect(() => {
157
    reCaptchaInstance.current?.reset()
158
  }, [])
159
 
160
  return (
3190 stevensc 161
    <Form onSubmit={onSubmitHandler}>
162
      {isLoading && <Spinner absolute />}
2630 stevensc 163
 
3190 stevensc 164
      <Typography variant='h3'>Entrar</Typography>
165
 
2630 stevensc 166
      <Input
167
        type='email'
168
        name='email'
3038 stevensc 169
        icon={<Mail />}
2630 stevensc 170
        placeholder='Correo electrónico'
2865 stevensc 171
        rules={{
2630 stevensc 172
          required: 'Este campo es requerido',
173
          pattern: {
3230 stevensc 174
            value: /^[\w-.]+@([\w-]+\.)+[\w-]{2,}$/i,
2630 stevensc 175
            message: 'Debe ser una dirección de correo electrónico valida'
176
          },
177
          maxLength: {
178
            value: 64,
179
            message: 'Debe ser menor a 64 caracteres'
180
          }
2865 stevensc 181
        }}
182
        control={control}
2630 stevensc 183
        error={errors.email?.message}
184
      />
185
 
186
      <Input
187
        type='password'
188
        name='password'
3038 stevensc 189
        icon={<Lock />}
2630 stevensc 190
        placeholder='Clave'
2865 stevensc 191
        control={control}
192
        rules={{
2630 stevensc 193
          required: 'Este campo es requerido',
194
          pattern: {
195
            value:
196
              /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$^x%x*-]).{6,16}$/i,
197
            message:
198
              'Debe contener entre 6 y 16 caracteres, incluida una letra mayúscula, un número y un carácter especial #?!@$^%*-'
199
          }
2865 stevensc 200
        }}
2630 stevensc 201
        error={errors.password?.message}
202
      />
203
 
3190 stevensc 204
      <CheckboxInput control={control} name='remember' label='Recuerdame' />
2630 stevensc 205
 
206
      {site_key && (
207
        <Recaptcha
208
          sitekey={site_key}
209
          verifyCallback={loginVerifyCallbackHandler}
210
          verifyCallbackName='loginVerifyCallbackHandler'
211
          expiredCallback={loginExpiredCallbackHandler}
212
          expiredCallbackName='loginExpiredCallbackHandler'
213
          ref={reCaptchaInstance}
214
          render='explicit'
215
          onloadCallback={handleOnRecaptchaLoad}
216
          hl='es'
217
        />
218
      )}
219
 
220
      <div className='links'>
221
        <Link to='/forgot-password'>¿Has olvidado tu contraseña?</Link>
222
        <Link to='/signup'>¿No tienes cuenta?</Link>
223
      </div>
224
 
3156 stevensc 225
      <Button color='secondary' type='submit' disabled={!isVerified}>
2630 stevensc 226
        Entrar
227
      </Button>
228
 
229
      {access_usign_social_networks === 'y' && (
230
        <>
231
          <h4>Entrar usando su red social</h4>
232
          <ul>
233
            {rrssOptions.map(({ label, icon: Icon, href }) => (
234
              <li key={label}>
235
                <SocialButton onClick={() => getRedirectUrl(href)}>
236
                  <Icon />
237
                  {`Iniciar sesión con ${label}`}
238
                </SocialButton>
239
              </li>
240
            ))}
241
          </ul>
242
        </>
243
      )}
3190 stevensc 244
    </Form>
2630 stevensc 245
  )
246
}
247
 
248
export default Login