Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3156 | Rev 3230 | 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 } from 'react-router-dom'
3
import { useForm } from 'react-hook-form'
4
import { useDispatch, useSelector } from 'react-redux'
2865 stevensc 5
import { styled, Typography } from '@mui/material'
2630 stevensc 6
import { Mail, Lock, Person, CheckCircleOutline } from '@mui/icons-material'
7
import Recaptcha from 'react-recaptcha'
8
 
2865 stevensc 9
import { axios } from '@utils'
10
import { addNotification } from '@store/notification/notification.actions'
11
import CryptoJSAesJson from '@utils/crypto-js/cryptojs-aes-format'
2630 stevensc 12
 
2865 stevensc 13
import Input from '@components/UI/inputs/Input'
14
import Button from '@components/UI/buttons/Buttons'
15
import Spinner from '@components/UI/Spinner'
3199 stevensc 16
import Form from '@components/common/form'
2865 stevensc 17
import SwitchInput from '@components/UI/SwitchInput'
18
import CheckboxInput from '@components/UI/inputs/Checkbox'
2630 stevensc 19
 
2865 stevensc 20
const StyledCheck = styled('div')`
2630 stevensc 21
  display: flex;
22
  flex-direction: column;
23
  justify-content: center;
24
  align-items: center;
25
  gap: 0.5rem;
26
  p {
27
    text-align: center;
28
  }
29
`
2865 stevensc 30
const StyledSpinnerContainer = styled('div')`
2630 stevensc 31
  position: absolute;
32
  left: 0;
33
  top: 0;
34
  width: 100%;
35
  height: 100%;
36
  background: rgba(255, 255, 255, 0.4);
37
  display: flex;
38
  justify-content: center;
39
  align-items: center;
40
  z-index: 300;
41
`
42
 
43
const Signup = () => {
44
  const [registered, setRegistered] = useState(false)
45
  const [isLoading, setIsLoading] = useState(false)
46
  const [isAdult, setIsAdult] = useState(false)
47
  const [isVerified, setIsVerified] = useState(false)
48
  const reCaptchaInstance = useRef(null)
49
  const reCaptchaToken = useRef('')
50
  const dispatch = useDispatch()
51
  const { site_key, aes } = useSelector(({ auth }) => auth)
52
 
2802 stevensc 53
  const {
54
    control,
55
    handleSubmit,
56
    setError,
57
    watch,
58
    formState: { errors }
59
  } = useForm({
2630 stevensc 60
    mode: 'all'
61
  })
62
 
63
  const signupVerifyCallbackHandler = (response) => {
64
    if (!response) return
65
    reCaptchaToken.current = response
66
    setIsVerified(true)
67
  }
68
 
69
  const signupExpiredCallbackHandler = () => {
70
    reCaptchaToken.current = ''
71
    setIsVerified(false)
72
  }
73
 
74
  const handleOnRecaptchaLoad = () => {
75
    reCaptchaToken.current = ''
76
  }
77
 
78
  const onSubmitHandler = handleSubmit(
79
    async ({
80
      email,
81
      first_name,
82
      last_name,
83
      password,
84
      confirmation,
85
      terms_and_conditions
86
    }) => {
87
      setIsLoading(true)
88
      const formData = new FormData()
89
      formData.append('first_name', first_name)
90
      formData.append('last_name', last_name)
91
      formData.append('email', CryptoJSAesJson.encrypt(email, aes))
92
      formData.append('password', CryptoJSAesJson.encrypt(password, aes))
93
      formData.append(
94
        'confirmation',
95
        CryptoJSAesJson.encrypt(confirmation, aes)
96
      )
97
      formData.append('terms_and_conditions', terms_and_conditions ? 1 : 0)
98
 
99
      formData.append('captcha', reCaptchaToken.current)
100
      formData.append('is_adult', isAdult ? 'y' : 'n')
101
 
102
      await axios
103
        .post('/signup', formData)
104
        .then(({ data }) => {
105
          if (!data.success) {
106
            if (typeof data.data !== 'string') {
107
              Object.entries(data.data).forEach(([key, value]) => {
108
                setError(key, {
109
                  type: 'manual',
110
                  message: Array.isArray(value) ? value[0] : value
111
                })
112
              })
113
              return
114
            }
115
 
116
            dispatch(addNotification({ style: 'danger', msg: data.data }))
117
            reCaptchaInstance.current.reset()
118
            signupVerifyCallbackHandler()
119
            return
120
          }
121
 
122
          reCaptchaInstance.current.reset()
123
          signupExpiredCallbackHandler()
124
          setRegistered(true)
125
        })
126
        .catch((err) => {
127
          console.log(`Error: ${err}`)
128
          dispatch(
129
            addNotification({
130
              style: 'danger',
131
              msg: 'Disculpe, ha ocurrido un error'
132
            })
133
          )
134
        })
135
        .finally(() => setIsLoading(false))
136
    }
137
  )
138
 
139
  useEffect(() => {
140
    reCaptchaInstance.current?.reset()
141
  }, [])
142
 
143
  if (registered) {
144
    return (
145
      <StyledCheck>
146
        <CheckCircleOutline sx={{ color: '#7FFF00', fontSize: '3rem' }} />
147
 
2864 stevensc 148
        <Typography>
2630 stevensc 149
          Se ha registrado correctamente. Por favor, active la cuenta desde su
150
          correo
2864 stevensc 151
        </Typography>
2630 stevensc 152
 
153
        <Link to='/signin'>
154
          <button className='btn btn-primary'>Entrar</button>
155
        </Link>
156
      </StyledCheck>
157
    )
158
  }
159
 
160
  return (
3199 stevensc 161
    <Form onSubmit={onSubmitHandler}>
162
      <Typography variant='h3'>Registrarse</Typography>
2630 stevensc 163
 
164
      <Input
165
        type='email'
166
        name='email'
167
        placeholder='Correo electrónico'
2865 stevensc 168
        icon={<Mail />}
2630 stevensc 169
        control={control}
170
        rules={{
171
          required: 'Este campo es requerido',
172
          pattern: {
173
            value: /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/i,
174
            message: 'Debe ser una dirección de correo electrónico valida'
175
          }
176
        }}
177
        error={errors.email?.message}
178
      />
179
 
180
      <Input
181
        type='text'
182
        name='first_name'
2865 stevensc 183
        icon={<Person />}
2630 stevensc 184
        placeholder='Nombre'
185
        control={control}
186
        rules={{
187
          required: 'Este campo es requerido',
188
          maxLength: {
189
            value: 64,
190
            message: 'Limite de carateres superior al permitido'
191
          }
192
        }}
193
        error={errors.first_name?.message}
194
      />
195
 
196
      <Input
197
        type='text'
198
        name='last_name'
2865 stevensc 199
        icon={<Person />}
2630 stevensc 200
        placeholder='Apellido'
201
        control={control}
202
        rules={{
203
          required: 'Este campo es requerido',
204
          maxLength: {
205
            value: 64,
206
            message: 'Limite de carateres superior al permitido'
207
          }
208
        }}
209
        error={errors.last_name?.message}
210
      />
211
 
212
      <Input
213
        type='password'
214
        name='password'
2865 stevensc 215
        icon={<Lock />}
2630 stevensc 216
        placeholder='Clave'
217
        control={control}
218
        rules={{
219
          required: 'Este campo es requerido',
220
          pattern: {
221
            value:
222
              /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$^x%x*-]).{6,16}$/i,
223
            message:
224
              'Debe contener entre 6 y 16 caracteres, incluida una letra mayúscula, un número y un carácter especial #?!@$^%*-'
225
          }
226
        }}
227
        error={errors.password?.message}
228
      />
229
 
230
      <Input
231
        type='password'
232
        name='confirmation'
2865 stevensc 233
        icon={<Lock />}
2630 stevensc 234
        placeholder='Confirme su clave'
235
        control={control}
236
        rules={{
237
          required: 'Este campo es requerido',
238
          validate: (v) =>
239
            v === watch('password') ||
240
            'Disculpe, las claves tienen que coincidir'
241
        }}
242
        error={errors.confirmation?.message}
243
      />
244
 
245
      <SwitchInput
246
        label='Eres mayor de 18'
247
        setValue={(value) => setIsAdult(value)}
248
      />
249
 
2865 stevensc 250
      <CheckboxInput
2630 stevensc 251
        name='terms_and_conditions'
252
        control={control}
253
        label='Si, acepto los Términos y Condiciones.'
2865 stevensc 254
        rules={{ required: 'Este campo es requerido' }}
2630 stevensc 255
        error={errors.terms_and_conditions?.message}
256
      />
257
 
258
      <Recaptcha
259
        sitekey={site_key}
260
        verifyCallback={signupVerifyCallbackHandler}
261
        verifyCallbackName='signupVerifyCallbackHandler'
262
        expiredCallback={signupExpiredCallbackHandler}
263
        expiredCallbackName='signupExpiredCallbackHandler'
264
        ref={reCaptchaInstance}
265
        render='explicit'
266
        onloadCallback={handleOnRecaptchaLoad}
267
        hl='es'
268
      />
269
 
270
      <div className='links'>
271
        <Link to='/signin'>¿Ya tienes cuenta?</Link>
272
      </div>
273
 
3156 stevensc 274
      <Button color='secondary' type='submit' disabled={!isVerified}>
2630 stevensc 275
        Registrarse
276
      </Button>
277
 
278
      {isLoading && (
279
        <StyledSpinnerContainer>
280
          <Spinner />
281
        </StyledSpinnerContainer>
282
      )}
3199 stevensc 283
    </Form>
2630 stevensc 284
  )
285
}
286
 
287
export default Signup