Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3038 | Rev 3190 | 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'
5
import { styled } from '@mui/material'
6
import { Mail, Lock } from '@mui/icons-material'
7
import Recaptcha from 'react-recaptcha'
8
 
9
import { axios } from '../../utils'
10
import { login } from '../../redux/auth/auth.actions'
11
import { addNotification } from '../../redux/notification/notification.actions'
12
import CryptoJSAesJson from '../../utils/crypto-js/cryptojs-aes-format'
13
 
14
import XIcon from 'components/UI/icons/XIcon'
15
import FacebookIcon from 'components/UI/icons/FacebookIcon'
16
import GoogleIcon from 'components/UI/icons/GoogleIcon'
17
 
18
import AuthForm from '../../components/auth/AuthForm'
19
import Spinner from 'components/UI/Spinner'
20
import Input from 'components/UI/inputs/Input'
21
import Checkbox from 'components/UI/checkbox/Checkbox'
22
import Button from '@app/components/UI/buttons/Buttons'
2888 stevensc 23
import { useMobile } from '@hooks'
2630 stevensc 24
 
25
const SocialButton = styled(Button)`
26
  background-color: white;
27
  border: 1px solid black;
28
  padding: 0.5rem 1rem;
29
  font-size: 1rem;
30
  color: #383838;
31
  width: 100%;
32
  box-sizing: border-box;
33
  margin-bottom: 10px;
34
  svg {
35
    width: 16px;
36
    height: 16px;
37
  }
38
`
39
 
40
const Login = ({
41
  facebookOauth = '/signin/facebook',
42
  twitterOauth = '/signin/twitter',
43
  googleOauth = '/signin/google'
44
}) => {
45
  const [isLoading, setIsLoading] = useState(false)
46
  const [isVerified, setIsVerified] = useState(false)
2888 stevensc 47
  const isMobile = useMobile()
2630 stevensc 48
 
49
  const reCaptchaToken = useRef('')
50
  const reCaptchaInstance = useRef(null)
51
 
52
  const navigate = useNavigate()
53
 
54
  const dispatch = useDispatch()
55
  const { site_key, aes, access_usign_social_networks } = useSelector(
56
    ({ auth }) => auth
57
  )
58
  const rrssOptions = [
59
    { label: 'Facebook', icon: FacebookIcon, href: facebookOauth },
60
    { label: 'Twitter', icon: XIcon, href: twitterOauth },
61
    { label: 'Google', icon: GoogleIcon, href: googleOauth }
62
  ]
63
 
64
  const {
65
    handleSubmit,
66
    control,
67
    setError,
68
    getValues,
69
    setValue,
2802 stevensc 70
    reset,
71
    formState: { errors }
2630 stevensc 72
  } = useForm({ mode: 'all' })
73
 
74
  const onSubmitHandler = handleSubmit(
75
    async ({ email, password, remember }) => {
76
      const formData = new FormData()
77
      formData.append('email', CryptoJSAesJson.encrypt(email, aes))
78
      formData.append('password', CryptoJSAesJson.encrypt(password, aes))
79
      formData.append('remember', remember ? 1 : 0)
80
      formData.append('captcha', reCaptchaToken.current)
81
 
82
      await axios
83
        .post('/signin', formData)
84
        .then(({ data: response }) => {
85
          const { success, data } = response
86
 
87
          if (!success) {
88
            loginExpiredCallbackHandler()
89
            reCaptchaInstance.current.reset()
90
 
91
            if (data.constructor.name === 'Object') {
92
              Object.entries(data).forEach(([key, value]) => {
93
                if (key in getValues()) {
94
                  setError(key, {
95
                    type: 'manual',
96
                    message: Array.isArray(value) ? value[0] : value
97
                  })
98
                }
99
              })
100
              return
101
            }
102
 
103
            dispatch(addNotification({ style: 'danger', msg: data }))
104
            return
105
          }
106
 
107
          const url = data.redirect.split('.com')[1]
108
          reCaptchaInstance.current.reset()
109
          loginExpiredCallbackHandler()
110
          reset()
111
          dispatch(login())
2888 stevensc 112
 
2960 stevensc 113
          isMobile ? navigate('/apps-navigation') : navigate(url)
2630 stevensc 114
        })
115
        .catch((err) => {
116
          console.log(err)
117
          reCaptchaInstance.current.reset()
118
 
119
          loginExpiredCallbackHandler()
120
          setValue('password', '')
121
 
122
          dispatch(
123
            addNotification({
124
              style: 'danger',
125
              msg: 'Disculpe, ha ocurrido un error'
126
            })
127
          )
128
        })
129
        .finally(() => setIsLoading(false))
130
    }
131
  )
132
 
133
  const loginVerifyCallbackHandler = (response) => {
134
    reCaptchaToken.current = response
135
    setIsVerified(true)
136
  }
137
 
138
  const loginExpiredCallbackHandler = () => {
139
    reCaptchaToken.current = ''
140
    setIsVerified(false)
141
  }
142
 
143
  const handleOnRecaptchaLoad = () => {
144
    reCaptchaToken.current = ''
145
  }
146
 
147
  const getRedirectUrl = async (endpoint) => {
148
    try {
149
      const res = await axios.get(endpoint)
150
      if (res.data && res.data.data) {
151
        window.location.href = res.data.data
152
      }
153
    } catch (error) {
154
      console.log('>>: error > ', error)
155
    }
156
  }
157
 
158
  useEffect(() => {
159
    reCaptchaInstance.current?.reset()
160
  }, [])
161
 
162
  return (
163
    <AuthForm onSubmit={onSubmitHandler}>
164
      <h3>Entrar</h3>
165
 
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: {
174
            value: /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/i,
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
 
204
      <Checkbox control={control} name='remember' label='Recuerdame' />
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
      )}
244
 
245
      {isLoading && <Spinner />}
246
    </AuthForm>
247
  )
248
}
249
 
250
export default Login