Rev 3190 | Rev 3262 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
import React, { useRef, useState, useEffect } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { useForm } from 'react-hook-form'
import { useDispatch, useSelector } from 'react-redux'
import { Button, styled, Typography } from '@mui/material'
import { Mail, Lock } from '@mui/icons-material'
import Recaptcha from 'react-recaptcha'
import { useMobile } from '@hooks'
import CryptoJSAesJson from '@utils/crypto-js/cryptojs-aes-format'
import FacebookIcon from '@components/UI/icons/FacebookIcon'
import XIcon from '@components/UI/icons/XIcon'
import GoogleIcon from '@components/UI/icons/GoogleIcon'
import { axios } from '@utils'
import { addNotification } from '@store/notification/notification.actions'
import { login } from '@store/auth/auth.actions'
import Form from '@components/common/form'
import Input from '@components/UI/inputs/Input'
import CheckboxInput from '@components/UI/inputs/Checkbox'
import Spinner from '@components/UI/Spinner'
const SocialButton = styled(Button)`
background-color: white;
border: 1px solid black;
padding: 0.5rem 1rem;
font-size: 1rem;
color: #383838;
width: 100%;
box-sizing: border-box;
margin-bottom: 10px;
svg {
width: 16px;
height: 16px;
}
`
const Login = ({
facebookOauth = '/signin/facebook',
twitterOauth = '/signin/twitter',
googleOauth = '/signin/google'
}) => {
const [isLoading, setIsLoading] = useState(false)
const [isVerified, setIsVerified] = useState(false)
const isMobile = useMobile()
const reCaptchaToken = useRef('')
const reCaptchaInstance = useRef(null)
const navigate = useNavigate()
const dispatch = useDispatch()
const { site_key, aes, access_usign_social_networks } = useSelector(
({ auth }) => auth
)
const rrssOptions = [
{ label: 'Facebook', icon: FacebookIcon, href: facebookOauth },
{ label: 'Twitter', icon: XIcon, href: twitterOauth },
{ label: 'Google', icon: GoogleIcon, href: googleOauth }
]
const {
handleSubmit,
control,
setError,
getValues,
setValue,
reset,
formState: { errors }
} = useForm({ mode: 'all' })
const onSubmitHandler = handleSubmit(
async ({ email, password, remember }) => {
const formData = new FormData()
formData.append('email', CryptoJSAesJson.encrypt(email, aes))
formData.append('password', CryptoJSAesJson.encrypt(password, aes))
formData.append('remember', remember ? 1 : 0)
formData.append('captcha', reCaptchaToken.current)
await axios
.post('/signin', formData)
.then(({ data: response }) => {
const { success, data } = response
if (!success) {
loginExpiredCallbackHandler()
reCaptchaInstance.current.reset()
if (data.constructor.name === 'Object') {
Object.entries(data).forEach(([key, value]) => {
if (key in getValues()) {
setError(key, {
type: 'manual',
message: Array.isArray(value) ? value[0] : value
})
}
})
return
}
dispatch(addNotification({ style: 'danger', msg: data }))
return
}
const url = data.redirect.split('.com')[1]
reCaptchaInstance.current.reset()
loginExpiredCallbackHandler()
reset()
dispatch(login())
isMobile ? navigate('/apps-navigation') : navigate(url)
})
.catch((err) => {
console.log(err)
reCaptchaInstance.current.reset()
loginExpiredCallbackHandler()
setValue('password', '')
dispatch(
addNotification({
style: 'danger',
msg: 'Disculpe, ha ocurrido un error'
})
)
})
.finally(() => setIsLoading(false))
}
)
const loginVerifyCallbackHandler = (response) => {
reCaptchaToken.current = response
setIsVerified(true)
}
const loginExpiredCallbackHandler = () => {
reCaptchaToken.current = ''
setIsVerified(false)
}
const handleOnRecaptchaLoad = () => {
reCaptchaToken.current = ''
}
const getRedirectUrl = async (endpoint) => {
try {
const res = await axios.get(endpoint)
if (res.data && res.data.data) {
window.location.href = res.data.data
}
} catch (error) {
console.log('>>: error > ', error)
}
}
useEffect(() => {
reCaptchaInstance.current?.reset()
}, [])
return (
<Form onSubmit={onSubmitHandler}>
{isLoading && <Spinner absolute />}
<Typography variant='h3'>Entrar</Typography>
<Input
type='email'
name='email'
icon={<Mail />}
placeholder='Correo electrónico'
rules={{
required: 'Este campo es requerido',
pattern: {
value: /^[\w-.]+@([\w-]+\.)+[\w-]{2,}$/i,
message: 'Debe ser una dirección de correo electrónico valida'
},
maxLength: {
value: 64,
message: 'Debe ser menor a 64 caracteres'
}
}}
control={control}
error={errors.email?.message}
/>
<Input
type='password'
name='password'
icon={<Lock />}
placeholder='Clave'
control={control}
rules={{
required: 'Este campo es requerido',
pattern: {
value:
/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$^x%x*-]).{6,16}$/i,
message:
'Debe contener entre 6 y 16 caracteres, incluida una letra mayúscula, un número y un carácter especial #?!@$^%*-'
}
}}
error={errors.password?.message}
/>
<CheckboxInput control={control} name='remember' label='Recuerdame' />
{site_key && (
<Recaptcha
sitekey={site_key}
verifyCallback={loginVerifyCallbackHandler}
verifyCallbackName='loginVerifyCallbackHandler'
expiredCallback={loginExpiredCallbackHandler}
expiredCallbackName='loginExpiredCallbackHandler'
ref={reCaptchaInstance}
render='explicit'
onloadCallback={handleOnRecaptchaLoad}
hl='es'
/>
)}
<div className='links'>
<Link to='/forgot-password'>¿Has olvidado tu contraseña?</Link>
<Link to='/signup'>¿No tienes cuenta?</Link>
</div>
<Button color='secondary' type='submit' disabled={!isVerified}>
Entrar
</Button>
{access_usign_social_networks === 'y' && (
<>
<h4>Entrar usando su red social</h4>
<ul>
{rrssOptions.map(({ label, icon: Icon, href }) => (
<li key={label}>
<SocialButton onClick={() => getRedirectUrl(href)}>
<Icon />
{`Iniciar sesión con ${label}`}
</SocialButton>
</li>
))}
</ul>
</>
)}
</Form>
)
}
export default Login