481 lines
22 KiB
TypeScript
481 lines
22 KiB
TypeScript
"use client";
|
|
import { useSessionStore, useSessionTokenStore } from "@store/Sesion.Store";
|
|
import { ApiError } from "@models/Server.Error.model";
|
|
import { ISession } from "@models/Session.model";
|
|
import EvangelizeBanner from "@components/EvangelizeBanner/EvangelizeBanner";
|
|
import {
|
|
login,
|
|
loginAndVerificate,
|
|
recoveryAccountWithCode,
|
|
sendRecoveryCode,
|
|
} from "@services/Session.Login";
|
|
import Checkbox from "@mui/material/Checkbox";
|
|
import Textbox from "@components/Textbox/Textbox";
|
|
import Button from "@components/Button/Button";
|
|
import ButtonGoogle from "./LoginGoogle";
|
|
import { GoogleOAuthProvider } from "@react-oauth/google";
|
|
import { useEffect, useState } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import * as Yup from "yup";
|
|
import { useAlert } from "@store/Alert.Store";
|
|
import Link from "next/link";
|
|
import AnimatedContainer from "@components/AnimatedConainer/AnimatedContainer";
|
|
import { LOGIN_ACTIONS, useLoginActionStore } from "@core/Store/LoginAction.Store";
|
|
import HeaderConfProvider from "../../HeaderConfProvider/HeaderConfProvider";
|
|
import { EVENT_TYPES, useEventHandlerStore } from "@core/Store/EventHandler.Store";
|
|
import { ScrollToTop } from "@core/app/components/ScrollTop";
|
|
import { useNavigation } from "@core/app/hooks/goto";
|
|
|
|
interface LoginProps {
|
|
verification?: boolean;
|
|
recovery?: boolean;
|
|
recoveryCode?: boolean;
|
|
}
|
|
export default function Login(props: LoginProps) {
|
|
const { verification = false, recovery = false, recoveryCode = false } = props;
|
|
const router = useRouter();
|
|
const loginAction = useLoginActionStore();
|
|
const SessionInfo = useSessionStore();
|
|
const SessionToken = useSessionTokenStore();
|
|
const alert = useAlert();
|
|
const eventHandler = useEventHandlerStore();
|
|
|
|
const [email, setEmail] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [verificationCode, setVerificationCode] = useState("");
|
|
const [checkReadTerms, setCheckReadTerms] = useState(false);
|
|
|
|
const clientId = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || "";
|
|
|
|
const { goTo } = useNavigation();
|
|
|
|
const createSession = (userSession: ISession, msg: string) => {
|
|
SessionInfo.setUser(userSession);
|
|
SessionToken.setToken(userSession.userToken);
|
|
SessionInfo.setLoginState("success");
|
|
alert.showSuccess(msg);
|
|
manageLoginActions(userSession);
|
|
};
|
|
|
|
const manageLoginActions = (session: ISession = SessionInfo) => {
|
|
if (loginAction.action !== LOGIN_ACTIONS.NONE) {
|
|
goTo(loginAction.url);
|
|
loginAction.clear();
|
|
} else {
|
|
const hasPlan = Boolean(session.subscription?.plan?.id);
|
|
const hasOrganization = Object.keys(session.organizationSubscriptions || {}).length > 0;
|
|
|
|
if (hasPlan && hasOrganization) {
|
|
goTo("/landing/dashboard");
|
|
return;
|
|
}
|
|
|
|
goTo("/landing/my-appointments");
|
|
}
|
|
};
|
|
|
|
const clearSession = (msg: string) => {
|
|
SessionInfo.clear();
|
|
SessionToken.setToken("");
|
|
alert.showError(msg);
|
|
SessionInfo.setLoginState("error");
|
|
};
|
|
|
|
const verificateLogin = () => {
|
|
const schema = Yup.object().shape({
|
|
verificationCode: Yup.string()
|
|
.length(6, "El código de verificacion debe tener 6 digitos")
|
|
.required("El código de verificacion es obligatorio."),
|
|
password: Yup.string()
|
|
.min(8, "La contraseña debe tener al menos 8 caracteres.")
|
|
.required("El campo de contraseña es obligatorio."),
|
|
email: Yup.string()
|
|
.email("Debe ingresar un correo electrónico válido.")
|
|
.required("El campo de correo electrónico es obligatorio."),
|
|
});
|
|
|
|
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
|
schema
|
|
.validate({ email, password, verificationCode }, { abortEarly: true, strict: true })
|
|
.then(() => {
|
|
SessionInfo.setLoginState("started");
|
|
loginAndVerificate(email, password, verificationCode)
|
|
.then((userSession: ISession) => {
|
|
createSession(
|
|
userSession,
|
|
"Registro compleatado. Bienvenido a turnosXpress."
|
|
);
|
|
})
|
|
.catch((error) => {
|
|
clearSession(error.format());
|
|
})
|
|
.finally(() => {
|
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
|
});
|
|
})
|
|
.catch((error) => {
|
|
const e = error as Yup.ValidationError;
|
|
clearSession("Ha ocurrido un error. Por favor intentelo nuevamente. " + e.message);
|
|
})
|
|
.finally(() => {
|
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
|
});
|
|
};
|
|
|
|
const sendRecoveryMail = () => {
|
|
const schema = Yup.object().shape({
|
|
email: Yup.string()
|
|
.email("Debe ingresar un correo electrónico válido.")
|
|
.required("El campo de correo electrónico es obligatorio."),
|
|
});
|
|
|
|
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
|
schema
|
|
.validate({ email }, { abortEarly: true, strict: true })
|
|
.then(() => {
|
|
SessionInfo.setLoginState("started");
|
|
sendRecoveryCode(email)
|
|
.then(() => {
|
|
alert.showSuccess(
|
|
"Se ha enviado un correo de recuperación a la cuenta indicada."
|
|
);
|
|
setTimeout(() => {
|
|
router.push("/landing/recover-account/verify");
|
|
}, 1000);
|
|
})
|
|
.catch((error) => {
|
|
clearSession(error.format());
|
|
})
|
|
.finally(() => {
|
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
|
});
|
|
})
|
|
.catch((error) => {
|
|
const e = error as Yup.ValidationError;
|
|
clearSession(e.message);
|
|
})
|
|
.finally(() => {
|
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
|
});
|
|
};
|
|
|
|
const recoveryAccount = () => {
|
|
const schema = Yup.object().shape({
|
|
email: Yup.string()
|
|
.email("Debe ingresar un correo electrónico válido.")
|
|
.required("El campo de correo electrónico es obligatorio."),
|
|
verificationCode: Yup.string()
|
|
.length(6, "El código de verificación debe tener 6 digitos")
|
|
.required("El código de verificacion es obligatorio."),
|
|
password: Yup.string()
|
|
.min(8, "La contraseña debe tener al menos 8 caracteres.")
|
|
.required("El campo de contraseña es obligatorio."),
|
|
});
|
|
|
|
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
|
schema
|
|
.validate({ email, verificationCode, password }, { abortEarly: true, strict: true })
|
|
.then(() => {
|
|
recoveryAccountWithCode(email, password, verificationCode)
|
|
.then(() => {
|
|
alert.showSuccess("Se ha cambiado la contraseña de la cuenta indicada.");
|
|
setTimeout(() => {
|
|
goTo("/landing/login");
|
|
}, 1000);
|
|
})
|
|
.catch((error) => {
|
|
clearSession(error.format());
|
|
})
|
|
.finally(() => {
|
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
|
});
|
|
})
|
|
.catch((error) => {
|
|
const e = error as Yup.ValidationError;
|
|
clearSession(e.message);
|
|
})
|
|
.finally(() => {
|
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
|
});
|
|
};
|
|
|
|
const iniciarSesion = () => {
|
|
const schema = Yup.object().shape({
|
|
email: Yup.string()
|
|
.email("Debe ingresar un correo electrónico válido.")
|
|
.required("El campo de correo electrónico es obligatorio."),
|
|
password: Yup.string()
|
|
.min(8, "La contraseña debe tener al menos 8 caracteres.")
|
|
.required("El campo de contraseña es obligatorio."),
|
|
});
|
|
|
|
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
|
|
|
schema
|
|
.validate({ email, password }, { abortEarly: false })
|
|
.then(() => {
|
|
SessionInfo.setLoginState("started");
|
|
login(email, password)
|
|
.then((userSession: ISession) => {
|
|
createSession(userSession, "Has iniciado sesión correctamente!");
|
|
})
|
|
.catch((error: ApiError) => {
|
|
clearSession(error.format());
|
|
})
|
|
.finally(() => {
|
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
|
});
|
|
})
|
|
.catch((error) => {
|
|
let errorDesc = "";
|
|
if (error instanceof Yup.ValidationError) {
|
|
const e: Yup.ValidationError = error as Yup.ValidationError;
|
|
errorDesc = e.errors.reduce((prev, curr) => prev + " " + curr, "");
|
|
} else {
|
|
errorDesc = "Ha ocurrido un error. Por favor intentelo nuevamente.";
|
|
}
|
|
clearSession(errorDesc);
|
|
})
|
|
.finally(() => {
|
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
|
});
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (SessionInfo.loged) {
|
|
manageLoginActions();
|
|
}
|
|
}, [SessionInfo.loged]);
|
|
|
|
return (
|
|
<AnimatedContainer
|
|
color="#aeaeae"
|
|
minSize={150}
|
|
maxSize={500}
|
|
items={10}
|
|
style={{
|
|
minHeight: "100vh",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
background:
|
|
"linear-gradient(180deg, var(--wine-darkest) 0%, var(--wine-dark) 100%)",
|
|
}}
|
|
>
|
|
<ScrollToTop />
|
|
<div className="homeCentered">
|
|
<HeaderConfProvider />
|
|
<GoogleOAuthProvider clientId={clientId}>
|
|
<div
|
|
style={{
|
|
paddingLeft: "20px",
|
|
paddingRight: "20px",
|
|
translate: "0px -30px",
|
|
}}
|
|
>
|
|
<div className="card">
|
|
<div
|
|
style={{
|
|
textAlign: "center",
|
|
paddingBottom: "30px",
|
|
paddingTop: "20px",
|
|
position: "relative",
|
|
}}
|
|
>
|
|
{verification && (
|
|
<>
|
|
<h1 className="homeTitleHeader">Finalizar registro</h1>
|
|
<p>
|
|
Hemos enviado un correo electronico a tu cuenta con el
|
|
código de verificación para completar el registro.{" "}
|
|
<strong>Por favor revisa tu bandeja de entrada.</strong>
|
|
</p>
|
|
</>
|
|
)}
|
|
{recovery && (
|
|
<>
|
|
<h1 className="homeTitleHeader">Reestablecer clave</h1>
|
|
<p>
|
|
Te enviaremos un correo electrónico a la dirección
|
|
registrada con tu cuenta. Asegúrate de proporcionarnos
|
|
el mismo correo con el que te registraste.{" "}
|
|
<strong>
|
|
Revisa tu bandeja de entrada y, si no lo encuentras,
|
|
también la carpeta de spam. Luego, sigue las
|
|
instrucciones.
|
|
</strong>
|
|
</p>
|
|
</>
|
|
)}
|
|
{recoveryCode && (
|
|
<>
|
|
<h1 className="homeTitleHeader">Recuperar el acceso</h1>
|
|
<p>
|
|
Hemos enviado un correo electrónico a tu cuenta con el
|
|
código de verificación para completar el proceso de
|
|
recuperación.{" "}
|
|
<strong>
|
|
Ingresa tu email, la nueva clave y el código de
|
|
verificación que te enviamos.
|
|
</strong>
|
|
</p>
|
|
</>
|
|
)}
|
|
{!verification && !recovery && !recoveryCode && (
|
|
<h1 className="homeTitleHeader">Ingresar</h1>
|
|
)}
|
|
<Textbox
|
|
name="name"
|
|
placeholder="Email"
|
|
type="text"
|
|
value={email}
|
|
width="100%"
|
|
onChange={(e) => {
|
|
setEmail(e.target.value);
|
|
}}
|
|
onKeyUp={(e) => {
|
|
if (!verification && !recovery && !recoveryCode) {
|
|
if (e.key === "Enter") {
|
|
document.getElementById("password")?.focus();
|
|
}
|
|
}
|
|
}}
|
|
/>
|
|
{!recovery && (
|
|
<Textbox
|
|
name="password"
|
|
placeholder="Clave"
|
|
type="password"
|
|
value={password}
|
|
width="100%"
|
|
onChange={(e) => {
|
|
setPassword(e.target.value);
|
|
}}
|
|
onKeyUp={(e) => {
|
|
if (!verification && !recovery && !recoveryCode) {
|
|
if (e.key === "Enter") {
|
|
iniciarSesion();
|
|
}
|
|
}
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
{(verification || recoveryCode) && (
|
|
<Textbox
|
|
placeholder="Código de verificaion"
|
|
type="text"
|
|
value={verificationCode}
|
|
width="100%"
|
|
onChange={(e) => {
|
|
setVerificationCode(e.target.value);
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
{verification && (
|
|
<Button
|
|
name="btnLogin"
|
|
text="Verificar"
|
|
width="100%"
|
|
onClick={verificateLogin}
|
|
style={{ marginTop: "20px" }}
|
|
type="submit"
|
|
/>
|
|
)}
|
|
|
|
{recovery && (
|
|
<Button
|
|
name="btnLogin"
|
|
text="Enviar email"
|
|
width="100%"
|
|
onClick={sendRecoveryMail}
|
|
style={{ marginTop: "20px" }}
|
|
type="submit"
|
|
/>
|
|
)}
|
|
|
|
{recoveryCode && (
|
|
<Button
|
|
name="btnLogin"
|
|
text="Cambiar clave"
|
|
width="100%"
|
|
onClick={recoveryAccount}
|
|
style={{ marginTop: "20px" }}
|
|
type="submit"
|
|
/>
|
|
)}
|
|
|
|
{!verification && !recovery && !recoveryCode && (
|
|
<Button
|
|
name="btnLogin"
|
|
text="Ingresar"
|
|
width="100%"
|
|
onClick={iniciarSesion}
|
|
style={{ marginTop: "20px" }}
|
|
type="submit"
|
|
/>
|
|
)}
|
|
|
|
{!verification && !recovery && !recoveryCode && (
|
|
<div>
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
flexDirection: "row",
|
|
alignItems: "flex-start",
|
|
justifyContent: "flex-start",
|
|
}}
|
|
>
|
|
<Checkbox
|
|
checked={checkReadTerms}
|
|
onClick={() => setCheckReadTerms(!checkReadTerms)}
|
|
/>
|
|
<div style={{ marginTop: "8px" }}>
|
|
Declaro que acepto los siguientes
|
|
<Link href="/landing/terms">
|
|
Términos y condiciones
|
|
</Link>{" "}
|
|
y{" "}
|
|
<Link href="/landing/privacy">
|
|
Políticas de privacidad
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
<ButtonGoogle termsReaded={checkReadTerms} />
|
|
</div>
|
|
)}
|
|
{!recoveryCode && (
|
|
<p style={{ marginTop: "20px" }}>
|
|
No tienes una cuenta?
|
|
<Link href="/landing/signup">Registrate!</Link>
|
|
</p>
|
|
)}
|
|
|
|
{!recovery && !recoveryCode && (
|
|
<Link
|
|
href="/landing/recover-account"
|
|
style={{ display: "block", marginTop: "10px" }}
|
|
>
|
|
Olvide mi clave!
|
|
</Link>
|
|
)}
|
|
{recovery && !recoveryCode && (
|
|
<Link
|
|
href="/landing/recover-account/verify"
|
|
style={{ display: "block", marginTop: "10px" }}
|
|
>
|
|
Ya tengo el código de verificación!
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</GoogleOAuthProvider>
|
|
</div>
|
|
<EvangelizeBanner variant="popup" delay={4000} />
|
|
</AnimatedContainer>
|
|
);
|
|
}
|