Rev 3410 | Rev 3432 | 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 } from "react-router-dom";
import { useForm } from "react-hook-form";
import { useDispatch, useSelector } from "react-redux";
import { styled, Typography } from "@mui/material";
import { Mail, Lock, Person, CheckCircleOutline } from "@mui/icons-material";
import Recaptcha from "react-recaptcha";
import { axios } from "@utils";
import { useFetchHelper } from "@hooks";
import { addNotification } from "@store/notification/notification.actions";
import CryptoJSAesJson from "@utils/crypto-js/cryptojs-aes-format";
import Input from "@components/UI/inputs/Input";
import Button from "@components/UI/buttons/Buttons";
import Select from "@components/UI/inputs/Select";
import Spinner from "@components/UI/Spinner";
import Form from "@components/common/form";
import SwitchInput from "@components/UI/SwitchInput";
import CheckboxInput from "@components/UI/inputs/Checkbox";
const StyledCheck = styled("div")`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 0.5rem;
p {
text-align: center;
}
`;
const StyledSpinnerContainer = styled("div")`
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.4);
display: flex;
justify-content: center;
align-items: center;
z-index: 300;
`;
const Signup = () => {
const [registered, setRegistered] = useState(false);
const [loading, setloading] = useState(false);
const [isAdult, setIsAdult] = useState(false);
const [isVerified, setIsVerified] = useState(false);
const reCaptchaInstance = useRef(null);
const reCaptchaToken = useRef("");
const dispatch = useDispatch();
const { site_key, aes } = useSelector(({ auth }) => auth);
const { data: timezones } = useFetchHelper("timezones");
const {
control,
handleSubmit,
setError,
watch,
formState: { errors },
} = useForm({
mode: "all",
});
const signupVerifyCallbackHandler = (response) => {
if (!response) return;
reCaptchaToken.current = response;
setIsVerified(true);
};
const signupExpiredCallbackHandler = () => {
reCaptchaToken.current = "";
setIsVerified(false);
};
const handleOnRecaptchaLoad = () => {
reCaptchaToken.current = "";
};
const onSubmitHandler = handleSubmit(
async ({
email,
first_name,
last_name,
password,
confirmation,
terms_and_conditions,
}) => {
setloading(true);
const formData = new FormData();
formData.append("first_name", first_name);
formData.append("last_name", last_name);
formData.append("email", CryptoJSAesJson.encrypt(email, aes));
formData.append("password", CryptoJSAesJson.encrypt(password, aes));
formData.append(
"confirmation",
CryptoJSAesJson.encrypt(confirmation, aes)
);
formData.append("terms_and_conditions", terms_and_conditions ? 1 : 0);
formData.append("captcha", reCaptchaToken.current);
formData.append("is_adult", isAdult ? "y" : "n");
await axios
.post("/signup", formData)
.then(({ data }) => {
if (!data.success) {
if (typeof data.data !== "string") {
Object.entries(data.data).forEach(([key, value]) => {
setError(key, {
type: "manual",
message: Array.isArray(value) ? value[0] : value,
});
});
return;
}
dispatch(addNotification({ style: "danger", msg: data.data }));
reCaptchaInstance.current.reset();
signupVerifyCallbackHandler();
return;
}
reCaptchaInstance.current.reset();
signupExpiredCallbackHandler();
setRegistered(true);
})
.catch((err) => {
console.log(`Error: ${err}`);
dispatch(
addNotification({
style: "danger",
msg: "Disculpe, ha ocurrido un error",
})
);
})
.finally(() => setloading(false));
}
);
useEffect(() => {
reCaptchaInstance.current?.reset();
}, []);
if (registered) {
return (
<StyledCheck>
<CheckCircleOutline sx={{ color: "#7FFF00", fontSize: "3rem" }} />
<Typography>
Se ha registrado correctamente. Por favor, active la cuenta desde su
correo
</Typography>
<Link to="/signin">
<button className="btn btn-primary">Entrar</button>
</Link>
</StyledCheck>
);
}
return (
<Form onSubmit={onSubmitHandler}>
<Typography variant="h3">Registrarse</Typography>
<Input
type="email"
name="email"
placeholder="Correo electrónico"
icon={<Mail />}
control={control}
rules={{
required: "Este campo es requerido",
pattern: {
value: /^[\w-.]+@([\w-]+\.)+[\w-]{2,}$/i,
message: "Debe ser una dirección de correo electrónico valida",
},
}}
error={errors.email?.message}
/>
<Input
type="text"
name="first_name"
icon={<Person />}
placeholder="Nombre"
control={control}
rules={{
required: "Este campo es requerido",
maxLength: {
value: 64,
message: "Limite de carateres superior al permitido",
},
}}
error={errors.first_name?.message}
/>
<Input
type="text"
name="last_name"
icon={<Person />}
placeholder="Apellido"
control={control}
rules={{
required: "Este campo es requerido",
maxLength: {
value: 64,
message: "Limite de carateres superior al permitido",
},
}}
error={errors.last_name?.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}
/>
<Input
type="password"
name="confirmation"
icon={<Lock />}
placeholder="Confirme su clave"
control={control}
rules={{
required: "Este campo es requerido",
validate: (v) =>
v === watch("password") ||
"Disculpe, las claves tienen que coincidir",
}}
error={errors.confirmation?.message}
/>
<Select
label="Zona horaria"
name="timezone"
control={control}
rules={{ required: "Este campo es requerido" }}
error={errors.timezone?.message}
options={Object.entries(timezones).map(([key, value]) => ({
name: key,
value,
}))}
/>
<SwitchInput
label="Eres mayor de 18"
setValue={(value) => setIsAdult(value)}
/>
<CheckboxInput
name="terms_and_conditions"
control={control}
label="Si, acepto los Términos y Condiciones."
rules={{ required: "Este campo es requerido" }}
error={errors.terms_and_conditions?.message}
/>
<Recaptcha
sitekey={site_key}
verifyCallback={signupVerifyCallbackHandler}
verifyCallbackName="signupVerifyCallbackHandler"
expiredCallback={signupExpiredCallbackHandler}
expiredCallbackName="signupExpiredCallbackHandler"
ref={reCaptchaInstance}
render="explicit"
onloadCallback={handleOnRecaptchaLoad}
hl="es"
/>
<div className="links">
<Link to="/signin">¿Ya tienes cuenta?</Link>
</div>
<Button color="secondary" type="submit" disabled={!isVerified}>
Registrarse
</Button>
{loading && (
<StyledSpinnerContainer>
<Spinner />
</StyledSpinnerContainer>
)}
</Form>
);
};
export default Signup;