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%",
@ -37,11 +90,11 @@ export default function Signup() {
gap: "15px", gap: "15px",
borderRadius: "12px", borderRadius: "12px",
boxShadow: `0px 100px 309px rgba(210, 208, 225, 0.24), boxShadow: `0px 100px 309px rgba(210, 208, 225, 0.24),
0px 41.7776px 129.093px rgba(210, 208, 225, 0.172525), 0px 41.7776px 129.093px rgba(210, 208, 225, 0.172525),
0px 22.3363px 69.0192px rgba(210, 208, 225, 0.143066), 0px 22.3363px 69.0192px rgba(210, 208, 225, 0.143066),
0px 12.5216px 38.6916px rgba(210, 208, 225, 0.12), 0px 12.5216px 38.6916px rgba(210, 208, 225, 0.12),
0px 6.6501px 20.5488px rgba(210, 208, 225, 0.0969343), 0px 6.6501px 20.5488px rgba(210, 208, 225, 0.0969343),
0px 2.76726px 8.55082px rgba(210, 208, 225, 0.0674749)`, 0px 2.76726px 8.55082px rgba(210, 208, 225, 0.0674749)`,
}} }}
> >
<IconButton <IconButton
@ -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="#"