Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 2630 | Rev 2865 | 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'
23
 
24
const SocialButton = styled(Button)`
25
  background-color: white;
26
  border: 1px solid black;
27
  padding: 0.5rem 1rem;
28
  font-size: 1rem;
29
  color: #383838;
30
  width: 100%;
31
  box-sizing: border-box;
32
  margin-bottom: 10px;
33
  svg {
34
    width: 16px;
35
    height: 16px;
36
  }
37
`
38
 
39
const Login = ({
40
  facebookOauth = '/signin/facebook',
41
  twitterOauth = '/signin/twitter',
42
  googleOauth = '/signin/google'
43
}) => {
44
  const [isLoading, setIsLoading] = useState(false)
45
  const [isVerified, setIsVerified] = useState(false)
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
    register,
65
    control,
66
    setError,
67
    getValues,
68
    setValue,
2802 stevensc 69
    reset,
70
    formState: { errors }
2630 stevensc 71
  } = useForm({ mode: 'all' })
72
 
73
  const onSubmitHandler = handleSubmit(
74
    async ({ email, password, remember }) => {
75
      const formData = new FormData()
76
      formData.append('email', CryptoJSAesJson.encrypt(email, aes))
77
      formData.append('password', CryptoJSAesJson.encrypt(password, aes))
78
      formData.append('remember', remember ? 1 : 0)
79
      formData.append('captcha', reCaptchaToken.current)
80
 
81
      await axios
82
        .post('/signin', formData)
83
        .then(({ data: response }) => {
84
          const { success, data } = response
85
 
86
          if (!success) {
87
            loginExpiredCallbackHandler()
88
            reCaptchaInstance.current.reset()
89
 
90
            if (data.constructor.name === 'Object') {
91
              Object.entries(data).forEach(([key, value]) => {
92
                if (key in getValues()) {
93
                  setError(key, {
94
                    type: 'manual',
95
                    message: Array.isArray(value) ? value[0] : value
96
                  })
97
                }
98
              })
99
              return
100
            }
101
 
102
            dispatch(addNotification({ style: 'danger', msg: data }))
103
            return
104
          }
105
 
106
          const url = data.redirect.split('.com')[1]
107
          reCaptchaInstance.current.reset()
108
          loginExpiredCallbackHandler()
109
          reset()
110
          dispatch(login())
111
          navigate(url)
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 (
161
    <AuthForm onSubmit={onSubmitHandler}>
162
      <h3>Entrar</h3>
163
 
164
      <Input
165
        type='email'
166
        name='email'
167
        icon={Mail}
168
        placeholder='Correo electrónico'
169
        inputRef={register({
170
          required: 'Este campo es requerido',
171
          pattern: {
172
            value: /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/i,
173
            message: 'Debe ser una dirección de correo electrónico valida'
174
          },
175
          maxLength: {
176
            value: 64,
177
            message: 'Debe ser menor a 64 caracteres'
178
          }
179
        })}
180
        error={errors.email?.message}
181
      />
182
 
183
      <Input
184
        type='password'
185
        name='password'
186
        icon={Lock}
187
        placeholder='Clave'
188
        inputRef={register({
189
          required: 'Este campo es requerido',
190
          pattern: {
191
            value:
192
              /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$^x%x*-]).{6,16}$/i,
193
            message:
194
              'Debe contener entre 6 y 16 caracteres, incluida una letra mayúscula, un número y un carácter especial #?!@$^%*-'
195
          }
196
        })}
197
        error={errors.password?.message}
198
      />
199
 
200
      <Checkbox control={control} name='remember' label='Recuerdame' />
201
 
202
      {site_key && (
203
        <Recaptcha
204
          sitekey={site_key}
205
          verifyCallback={loginVerifyCallbackHandler}
206
          verifyCallbackName='loginVerifyCallbackHandler'
207
          expiredCallback={loginExpiredCallbackHandler}
208
          expiredCallbackName='loginExpiredCallbackHandler'
209
          ref={reCaptchaInstance}
210
          render='explicit'
211
          onloadCallback={handleOnRecaptchaLoad}
212
          hl='es'
213
        />
214
      )}
215
 
216
      <div className='links'>
217
        <Link to='/forgot-password'>¿Has olvidado tu contraseña?</Link>
218
        <Link to='/signup'>¿No tienes cuenta?</Link>
219
      </div>
220
 
221
      <Button variant='secondary' type='submit' disabled={!isVerified}>
222
        Entrar
223
      </Button>
224
 
225
      {access_usign_social_networks === 'y' && (
226
        <>
227
          <h4>Entrar usando su red social</h4>
228
          <ul>
229
            {rrssOptions.map(({ label, icon: Icon, href }) => (
230
              <li key={label}>
231
                <SocialButton onClick={() => getRedirectUrl(href)}>
232
                  <Icon />
233
                  {`Iniciar sesión con ${label}`}
234
                </SocialButton>
235
              </li>
236
            ))}
237
          </ul>
238
        </>
239
      )}
240
 
241
      {isLoading && <Spinner />}
242
    </AuthForm>
243
  )
244
}
245
 
246
export default Login