Proyectos de Subversion LeadersLinked - SPA

Rev

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