100 lines
2.7 KiB
TypeScript

import axios from "axios";
import { Form, Formik, FormikHelpers } from "formik";
import { useContext } from "react";
import { useLocation, useNavigate } from "react-router";
import * as yup from "yup";
import { AuthContext } from "../AuthContext";
import EmailField from "../components/EmailField";
import FormActions from "../components/FormActions";
import PasswordField from "../components/PasswordField";
import Title from "../components/Title";
import { ToastContext } from "../ToastContext";
import { useMutation } from "../query";
interface IForm {
email: string;
password: string;
}
const useLogin = () => {
const location = useLocation();
const navigate = useNavigate();
const { addToast } = useContext(ToastContext);
const { setAuthenticated } = useContext(AuthContext);
const { mutateAsync: login } = useMutation(
async (data: IForm) => await axios.post("/sessions/", data),
);
return async (data: IForm, { setFieldError }: FormikHelpers<IForm>) => {
try {
await login(data);
setAuthenticated(true);
navigate((location.state as any)?.from ?? "/");
} catch (error: any) {
if (error.response?.status === 401) {
setFieldError("email", "Invalid credentials");
setFieldError("password", "Invalid credentials");
} else {
addToast("Try again", "error");
}
}
};
};
const validationSchema = yup.object({
email: yup.string().email("Email invalid").required("Required"),
password: yup.string().required("Required"),
});
const Login = () => {
const onSubmit = useLogin();
const location = useLocation();
return (
<>
<Title title="Login" />
<Formik<IForm>
initialValues={{
email: (location.state as any)?.email ?? "",
password: "",
}}
onSubmit={onSubmit}
validationSchema={validationSchema}
>
{({ dirty, isSubmitting, values }) => (
<Form>
<EmailField fullWidth label="Email" name="email" required />
<PasswordField
autoComplete="password"
fullWidth
label="Password"
name="password"
required
/>
<FormActions
disabled={!dirty}
isSubmitting={isSubmitting}
label="Login"
links={[
{
label: "Reset password",
to: "/forgotten-password/",
state: { email: values.email },
},
{
label: "Register",
to: "/register/",
state: { email: values.email },
},
]}
/>
</Form>
)}
</Formik>
</>
);
};
export default Login;