integrate formik, auth handlers

This commit is contained in:
nflnkr 2022-11-29 15:21:40 +03:00
parent 37703b773c
commit 3fab80847b
2 changed files with 184 additions and 37 deletions

@ -3,14 +3,55 @@ import CustomButton from "../components/CustomButton";
import InputTextfield from "../components/InputTextfield"; import InputTextfield from "../components/InputTextfield";
import PenaLogo from "../components/PenaLogo"; import PenaLogo from "../components/PenaLogo";
import CloseIcon from "@mui/icons-material/Close"; import CloseIcon from "@mui/icons-material/Close";
import { useState } from "react"; import { authHandler } from "../utils/api/authenticationHandler";
import { useNavigate } from "react-router-dom";
import { useFormik } from "formik";
interface Values {
email: string;
password: string;
}
// TODO
function validate(values: Values) {
const errors = {} as any;
if (!values.email) {
errors.email = "Required";
} else if (!/^[\w-]{3,25}$/i.test(values.email)) {
errors.email = "Invalid username";
}
if (!values.password) {
errors.password = "Required";
} else if (!/^[\w-]{8,25}$/i.test(values.password)) {
errors.password = "Invalid password";
}
return errors;
}
export default function Signin() { export default function Signin() {
const [login, setLogin] = useState<string>("");
const [password, setPassword] = useState<string>("");
const theme = useTheme(); const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md")); const upMd = useMediaQuery(theme.breakpoints.up("md"));
const navigate = useNavigate();
const formik = useFormik<Values>({
initialValues: {
email: "",
password: "",
},
validate,
onSubmit: async (values: Values) => {
const result = await authHandler.login({
email: values.email,
password: values.password,
});
if (result instanceof Error) {
console.log("TODO handle login error");
return;
}
console.log("TODO handle login success feedback");
navigate("/");
}
});
return ( return (
<Box <Box
@ -22,6 +63,9 @@ export default function Signin() {
}} }}
> >
<Box <Box
component="form"
onSubmit={formik.handleSubmit}
noValidate
sx={{ sx={{
position: "relative", position: "relative",
width: upMd ? "600px" : "100%", width: upMd ? "600px" : "100%",
@ -62,20 +106,31 @@ export default function Signin() {
}} }}
>Вход в личный кабинет</Typography> >Вход в личный кабинет</Typography>
<InputTextfield <InputTextfield
value={login} TextfieldProps={{
onChange={e => setLogin(e.target.value)} value: formik.values.email,
placeholder: "+7 900 000 00 00 или username@penahub.com",
onBlur: formik.handleBlur,
error: formik.touched.email && Boolean(formik.errors.email),
helperText: formik.touched.email && formik.errors.email,
}}
onChange={formik.handleChange}
id="email"
label="Телефон или E-mail" label="Телефон или E-mail"
placeholder="+7 900 000 00 00 или username@penahub.com" gap={upMd ? "15px" : "10px"}
id="login"
gap={upMd ? "15px" : "12px"}
/> />
<InputTextfield <InputTextfield
value={password} TextfieldProps={{
onChange={e => setPassword(e.target.value)} value: formik.values.password,
label="Пароль" placeholder: "Не менее 8 символов",
placeholder="Не менее 8 символов" onBlur: formik.handleBlur,
error: formik.touched.password && Boolean(formik.errors.password),
helperText: formik.touched.password && formik.errors.password,
type: "password",
}}
onChange={formik.handleChange}
id="password" id="password"
gap={upMd ? "15px" : "12px"} label="Пароль"
gap={upMd ? "15px" : "10px"}
/> />
<CustomButton <CustomButton
fullWidth fullWidth
@ -87,6 +142,8 @@ export default function Signin() {
mt: upMd ? undefined : "10px", mt: upMd ? undefined : "10px",
}} }}
py="12px" py="12px"
type="submit"
disabled={formik.isSubmitting}
>Войти</CustomButton> >Войти</CustomButton>
<Link href="#" <Link href="#"
sx={{ sx={{

@ -3,16 +3,66 @@ import CustomButton from "../components/CustomButton";
import InputTextfield from "../components/InputTextfield"; import InputTextfield from "../components/InputTextfield";
import PenaLogo from "../components/PenaLogo"; import PenaLogo from "../components/PenaLogo";
import CloseIcon from "@mui/icons-material/Close"; import CloseIcon from "@mui/icons-material/Close";
import { useState } from "react"; import { authHandler } from "../utils/api/authenticationHandler";
import { useNavigate } from "react-router-dom";
import { useFormik } from "formik";
interface Values {
login: string;
email: string;
phoneNumber: string;
password: string;
repeatPassword: string;
}
// TODO
function validate(values: Values) {
const errors = {} as any;
if (!values.login) {
errors.login = "Required";
} else if (!/^[\w-]{3,25}$/i.test(values.login)) {
errors.login = "Invalid username";
}
if (!values.password) {
errors.password = "Required";
} else if (!/^[\w-]{8,25}$/i.test(values.password)) {
errors.password = "Invalid password";
}
if (values.password !== values.repeatPassword) {
errors.repeatPassword = "Passwords do not match";
}
return errors;
}
export default function Signup() { export default function Signup() {
const [email, setEmail] = useState<string>("");
const [phonenumber, setPhonenumber] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [repeatPassword, setRepeatPassword] = useState<string>("");
const theme = useTheme(); const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md")); const upMd = useMediaQuery(theme.breakpoints.up("md"));
const navigate = useNavigate();
const formik = useFormik<Values>({
initialValues: {
login: "",
email: "",
phoneNumber: "",
password: "",
repeatPassword: "",
},
validate,
onSubmit: async (values: Values) => {
const result = await authHandler.register({
email: values.email,
login: values.login,
password: values.password,
phoneNumber: values.phoneNumber,
});
if (result instanceof Error) {
console.log("TODO handle register error");
return;
}
console.log("TODO handle register success feedback");
navigate("/signin");
}
});
return ( return (
<Box <Box
@ -24,6 +74,9 @@ export default function Signup() {
}} }}
> >
<Box <Box
component="form"
onSubmit={formik.handleSubmit}
noValidate
sx={{ sx={{
position: "relative", position: "relative",
width: upMd ? "600px" : "100%", width: upMd ? "600px" : "100%",
@ -65,35 +118,70 @@ export default function Signup() {
}} }}
>Регистрация</Typography> >Регистрация</Typography>
<InputTextfield <InputTextfield
value={email} TextfieldProps={{
onChange={e => setEmail(e.target.value)} value: formik.values.login,
placeholder: "username",
onBlur: formik.handleBlur,
error: formik.touched.login && Boolean(formik.errors.login),
helperText: formik.touched.login && formik.errors.login,
}}
onChange={formik.handleChange}
id="login"
label="Login"
gap={upMd ? "15px" : "10px"}
/>
<InputTextfield
TextfieldProps={{
value: formik.values.email,
placeholder: "username@penahub.com",
onBlur: formik.handleBlur,
error: formik.touched.email && Boolean(formik.errors.email),
helperText: formik.touched.email && formik.errors.email,
}}
onChange={formik.handleChange}
id="email" id="email"
label="E-mail" label="E-mail"
placeholder="username@penahub.com"
gap={upMd ? "15px" : "10px"} gap={upMd ? "15px" : "10px"}
/> />
<InputTextfield <InputTextfield
value={phonenumber} TextfieldProps={{
onChange={e => setPhonenumber(e.target.value)} value: formik.values.phoneNumber,
id="phonenumber" placeholder: "+7 900 000 00 00",
onBlur: formik.handleBlur,
error: formik.touched.phoneNumber && Boolean(formik.errors.phoneNumber),
helperText: formik.touched.phoneNumber && formik.errors.phoneNumber,
}}
onChange={formik.handleChange}
id="phoneNumber"
label="Телефон" label="Телефон"
placeholder="+7 900 000 00 00"
gap={upMd ? "15px" : "10px"} gap={upMd ? "15px" : "10px"}
/> />
<InputTextfield <InputTextfield
value={password} TextfieldProps={{
onChange={e => setPassword(e.target.value)} value: formik.values.password,
placeholder: "Не менее 8 символов",
onBlur: formik.handleBlur,
error: formik.touched.password && Boolean(formik.errors.password),
helperText: formik.touched.password && formik.errors.password,
type: "password",
}}
onChange={formik.handleChange}
id="password" id="password"
label="Пароль" label="Пароль"
placeholder="Не менее 8 символов"
gap={upMd ? "15px" : "10px"} gap={upMd ? "15px" : "10px"}
/> />
<InputTextfield <InputTextfield
value={repeatPassword} TextfieldProps={{
onChange={e => setRepeatPassword(e.target.value)} value: formik.values.repeatPassword,
id="repeat-password" placeholder: "Не менее 8 символов",
onBlur: formik.handleBlur,
error: formik.touched.repeatPassword && Boolean(formik.errors.repeatPassword),
helperText: formik.touched.repeatPassword && formik.errors.repeatPassword,
type: "password",
}}
onChange={formik.handleChange}
id="repeatPassword"
label="Повторить пароль" label="Повторить пароль"
placeholder="Не менее 8 символов"
gap={upMd ? "15px" : "10px"} gap={upMd ? "15px" : "10px"}
/> />
<CustomButton <CustomButton
@ -106,6 +194,8 @@ export default function Signup() {
mt: upMd ? undefined : "10px", mt: upMd ? undefined : "10px",
}} }}
py="12px" py="12px"
type="submit"
disabled={formik.isSubmitting}
>Войти</CustomButton> >Войти</CustomButton>
<Link <Link
href="#" href="#"