front-hub/src/pages/auth/Signup.tsx

209 lines
7.9 KiB
TypeScript
Raw Normal View History

2023-05-13 14:13:57 +00:00
import { Box, Dialog, IconButton, Link, Typography, useMediaQuery, useTheme } from "@mui/material";
import { useLocation, useNavigate } from "react-router-dom";
2022-11-29 12:21:40 +00:00
import { useFormik } from "formik";
import CloseIcon from "@mui/icons-material/Close";
import CustomButton from "@components/CustomButton";
import InputTextfield from "@components/InputTextfield";
import PenaLogo from "@components/PenaLogo";
2023-05-17 11:20:11 +00:00
import { enqueueSnackbar } from "notistack";
2023-05-13 14:13:57 +00:00
import { Link as RouterLink } from "react-router-dom";
import { object, ref, string } from "yup";
2023-05-19 09:44:18 +00:00
import { useEffect, useState } from "react";
2023-05-17 11:20:11 +00:00
import { RegisterRequest, RegisterResponse } from "@root/model/auth";
2023-05-19 09:44:18 +00:00
import { setUserId, useUserStore } from "@root/stores/user";
2023-06-06 13:13:58 +00:00
import { getMessageFromFetchError } from "@frontend/kitui";
2023-06-11 10:18:37 +00:00
import { makeRequest } from "@frontend/kitui";
2023-06-16 19:04:59 +00:00
import { cardShadow } from "@root/utils/themes/shadow";
import PasswordInput from "@root/components/passwordInput";
2023-05-13 14:13:57 +00:00
2022-11-19 20:31:42 +00:00
2022-11-29 12:21:40 +00:00
interface Values {
2023-05-29 09:56:00 +00:00
login: string;
2023-05-13 14:13:57 +00:00
password: string;
repeatPassword: string;
2022-11-29 12:21:40 +00:00
}
2023-05-13 14:13:57 +00:00
const initialValues: Values = {
2023-05-29 09:56:00 +00:00
login: "",
2023-05-13 14:13:57 +00:00
password: "",
repeatPassword: "",
};
const validationSchema = object({
2023-05-29 09:56:00 +00:00
login: string().required("Поле обязательно"),
2023-05-17 11:20:11 +00:00
password: string().min(8, "Минимум 8 символов").matches(/^[.,:;-_+\d\w]+$/, "Некорректные символы").required("Поле обязательно"),
2023-05-13 14:13:57 +00:00
repeatPassword: string().oneOf([ref("password"), undefined], "Пароли не совпадают"),
});
2022-11-29 12:21:40 +00:00
2023-05-13 14:13:57 +00:00
export default function SignupDialog() {
2023-05-14 11:38:03 +00:00
const [isDialogOpen, setIsDialogOpen] = useState<boolean>(true);
2023-05-19 09:44:18 +00:00
const user = useUserStore(state => state.user);
2023-05-13 14:13:57 +00:00
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const navigate = useNavigate();
const location = useLocation();
const formik = useFormik<Values>({
initialValues,
validationSchema,
2023-05-17 11:20:11 +00:00
onSubmit: (values, formikHelpers) => {
makeRequest<RegisterRequest, RegisterResponse>({
2023-05-13 14:13:57 +00:00
url: "https://hub.pena.digital/auth/register",
body: {
2023-06-01 15:17:34 +00:00
login: values.login.trim(),
password: values.password.trim(),
phoneNumber: "+7",
2023-05-13 14:13:57 +00:00
},
2023-05-17 11:20:11 +00:00
useToken: false,
withCredentials: true,
}).then(result => {
2023-05-19 09:44:18 +00:00
setUserId(result._id);
2023-05-17 11:20:11 +00:00
}).catch((error: any) => {
const errorMessage = getMessageFromFetchError(error);
if (errorMessage) enqueueSnackbar(errorMessage);
2023-05-17 11:20:11 +00:00
}).finally(() => {
formikHelpers.setSubmitting(false);
});
2023-05-13 14:13:57 +00:00
},
});
2022-11-19 20:31:42 +00:00
2023-05-19 09:44:18 +00:00
useEffect(function redirectIfSignedIn() {
if (user) navigate("/tariffs", { replace: true });
}, [navigate, user]);
2023-05-13 14:13:57 +00:00
function handleClose() {
2023-05-14 11:38:03 +00:00
setIsDialogOpen(false);
setTimeout(() => navigate("/"), theme.transitions.duration.leavingScreen);
2023-05-13 14:13:57 +00:00
}
2022-12-11 10:25:32 +00:00
2023-05-13 14:13:57 +00:00
return (
<Dialog
2023-05-14 11:38:03 +00:00
open={isDialogOpen}
2023-05-13 14:13:57 +00:00
onClose={handleClose}
PaperProps={{
sx: {
width: "600px",
2023-06-01 15:17:34 +00:00
maxWidth: "600px",
2023-05-13 14:13:57 +00:00
}
}}
slotProps={{
backdrop: {
style: {
backgroundColor: "rgb(0 0 0 / 0.7)",
}
}
}}
>
2023-05-13 14:13:57 +00:00
<Box
component="form"
onSubmit={formik.handleSubmit}
noValidate
sx={{
position: "relative",
backgroundColor: "white",
display: "flex",
alignItems: "center",
flexDirection: "column",
p: upMd ? "50px" : "18px",
pb: upMd ? "40px" : "30px",
gap: "15px",
borderRadius: "12px",
2023-06-16 19:04:59 +00:00
boxShadow: cardShadow,
2023-05-13 14:13:57 +00:00
}}
>
<IconButton
onClick={handleClose}
sx={{
position: "absolute",
right: "7px",
top: "7px",
}}
>
<CloseIcon sx={{ transform: "scale(1.5)" }} />
</IconButton>
<Box sx={{ mt: upMd ? undefined : "62px" }}>
<PenaLogo width={upMd ? 233 : 196} />
</Box>
<Typography
sx={{
color: theme.palette.grey3.main,
mt: "5px",
mb: upMd ? "35px" : "33px",
}}
>
Регистрация
</Typography>
<InputTextfield
TextfieldProps={{
2023-05-29 09:56:00 +00:00
value: formik.values.login,
placeholder: "username",
2023-05-13 14:13:57 +00:00
onBlur: formik.handleBlur,
2023-05-29 09:56:00 +00:00
error: formik.touched.login && Boolean(formik.errors.login),
helperText: formik.touched.login && formik.errors.login,
2023-05-13 14:13:57 +00:00
}}
onChange={formik.handleChange}
color="#F2F3F7"
2023-05-29 09:56:00 +00:00
id="login"
label="Логин"
2023-05-13 14:13:57 +00:00
gap={upMd ? "10px" : "10px"}
/>
<PasswordInput
2023-05-13 14:13:57 +00:00
TextfieldProps={{
value: formik.values.password,
placeholder: "Не менее 8 символов",
onBlur: formik.handleBlur,
error: formik.touched.password && Boolean(formik.errors.password),
helperText: formik.touched.password && formik.errors.password,
autoComplete: "new-password"
2023-05-13 14:13:57 +00:00
}}
onChange={formik.handleChange}
color="#F2F3F7"
id="password"
label="Пароль"
gap={upMd ? "10px" : "10px"}
/>
<PasswordInput
2023-05-13 14:13:57 +00:00
TextfieldProps={{
value: formik.values.repeatPassword,
placeholder: "Не менее 8 символов",
onBlur: formik.handleBlur,
error: formik.touched.repeatPassword && Boolean(formik.errors.repeatPassword),
helperText: formik.touched.repeatPassword && formik.errors.repeatPassword,
autoComplete: "new-password"
2023-05-13 14:13:57 +00:00
}}
onChange={formik.handleChange}
color="#F2F3F7"
id="repeatPassword"
label="Повторить пароль"
gap={upMd ? "10px" : "10px"}
/>
<CustomButton
fullWidth
variant="contained"
sx={{
backgroundColor: theme.palette.brightPurple.main,
textColor: "white",
width: "100%",
py: "12px",
mt: upMd ? undefined : "10px",
}}
type="submit"
disabled={formik.isSubmitting}
>
Зарегистрироваться
</CustomButton>
<Link
component={RouterLink}
to="/signin"
state={{ backgroundLocation: location.state.backgroundLocation }}
sx={{
color: theme.palette.brightPurple.main,
mt: "auto",
}}
>
Вход в личный кабинет
</Link>
</Box>
</Dialog>
);
}