Proyectos de Subversion LeadersLinked - SPA

Rev

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