WIP 1step integrations, integrations modal

This commit is contained in:
aleksandr-raw 2024-04-05 14:48:10 +04:00
parent 5434d0cafc
commit 137fa317da
11 changed files with 536 additions and 15 deletions

@ -0,0 +1,164 @@
import { Box, Button, Typography, useTheme } from "@mui/material";
import { FC } from "react";
import { object, string } from "yup";
import InputTextfield from "@ui_kit/InputTextfield";
import PasswordInput from "@ui_kit/passwordInput";
import { useFormik } from "formik";
import ArrowLeft from "@icons/questionsPage/arrowLeft";
type IntegrationStep1Props = {
handleNextStep: () => void;
};
interface Values {
login: string;
password: string;
}
const initialValues: Values = {
login: "",
password: "",
};
const validationSchema = object({
login: string().required("Поле обязательно"),
password: string().required("Поле обязательно").min(8, "Минимум 8 символов"),
});
export const IntegrationStep1: FC<IntegrationStep1Props> = ({
handleNextStep,
}) => {
const theme = useTheme();
const formik = useFormik<Values>({
initialValues,
validationSchema,
onSubmit: async (values, formikHelpers) => {
const loginTrimmed = values.login.trim();
const passwordTrimmed = values.password.trim();
try {
// Simulate a network request
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log("Simulated network request completed");
handleNextStep();
} catch (error) {
console.error("Errr");
formikHelpers.setSubmitting(false);
formikHelpers.setErrors({ submit: error.message });
}
},
});
return (
<Box
component="form"
onSubmit={formik.handleSubmit}
noValidate
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Box
sx={{
marginTop: "68px",
width: "500px",
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<InputTextfield
TextfieldProps={{
value: formik.values.login,
placeholder: "+7 900 000 00 00 или username@penahaub.com",
onBlur: formik.handleBlur,
error: formik.touched.login && Boolean(formik.errors.login),
helperText: formik.touched.login && formik.errors.login,
"data-cy": "login",
}}
onChange={formik.handleChange}
color="#F2F3F7"
id="login"
label="Телефон или E-mail"
gap="10px"
/>
<PasswordInput
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,
type: "password",
"data-cy": "password",
}}
onChange={formik.handleChange}
color="#F2F3F7"
id="password"
label="Пароль"
gap="10px"
/>
</Box>
<Box sx={{ marginTop: "30px", width: "500px" }}>
<Typography
sx={{
fontSize: "16px",
fontWeight: "400",
color: "#9A9AAF",
lineHeight: "1",
}}
>
Инструкция
</Typography>
<Typography
sx={{
marginTop: "12px",
fontSize: "18px",
fontWeight: "400",
color: "#4D4D4D",
lineHeight: "1",
}}
>
Повседневная практика показывает, что постоянный количественный рост и
сфера нашей активности способствует подготовки и реализации систем
массового участия
</Typography>
</Box>
<Box
sx={{
display: "flex",
gap: "10px",
marginTop: "auto",
marginLeft: "auto",
}}
>
<Button
variant="outlined"
sx={{ padding: "10px 20px", borderRadius: "8px", height: "44px" }}
data-cy="back-button"
disabled
>
<ArrowLeft color={theme.palette.grey2.main} />
</Button>
<Button
variant="contained"
type="submit"
disabled={formik.isSubmitting}
sx={{
height: "44px",
padding: "10px 20px",
borderRadius: "8px",
background: theme.palette.brightPurple.main,
fontSize: "18px",
}}
data-cy="signin"
>
Войти
</Button>
</Box>
</Box>
);
};

@ -0,0 +1,38 @@
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { FC } from "react";
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
type IntegrationStep2Props = {
handlePrevStep: () => void;
handleNextStep: () => void;
};
export const IntegrationStep2: FC<IntegrationStep2Props> = ({
handlePrevStep,
handleNextStep,
}) => {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Typography
sx={{ color: "#4D4D4D", mt: "5px", mb: upMd ? "10px" : "33px" }}
>
step 2
</Typography>
<StepButtonsBlock
handleNextStep={handleNextStep}
handlePrevStep={handlePrevStep}
/>
</Box>
);
};

@ -0,0 +1,38 @@
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { FC } from "react";
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
type IntegrationStep3Props = {
handlePrevStep: () => void;
handleNextStep: () => void;
};
export const IntegrationStep3: FC<IntegrationStep3Props> = ({
handlePrevStep,
handleNextStep,
}) => {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Typography
sx={{ color: "#4D4D4D", mt: "5px", mb: upMd ? "10px" : "33px" }}
>
step 3
</Typography>
<StepButtonsBlock
handleNextStep={handleNextStep}
handlePrevStep={handlePrevStep}
/>
</Box>
);
};

@ -0,0 +1,38 @@
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { FC } from "react";
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
type IntegrationStep4Props = {
handlePrevStep: () => void;
handleNextStep: () => void;
};
export const IntegrationStep4: FC<IntegrationStep4Props> = ({
handlePrevStep,
handleNextStep,
}) => {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Typography
sx={{ color: "#4D4D4D", mt: "5px", mb: upMd ? "10px" : "33px" }}
>
step 4
</Typography>
<StepButtonsBlock
handleNextStep={handleNextStep}
handlePrevStep={handlePrevStep}
/>
</Box>
);
};

@ -0,0 +1,38 @@
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { FC } from "react";
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
type IntegrationStep5Props = {
handlePrevStep: () => void;
handleNextStep: () => void;
};
export const IntegrationStep5: FC<IntegrationStep5Props> = ({
handlePrevStep,
handleNextStep,
}) => {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Typography
sx={{ color: "#4D4D4D", mt: "5px", mb: upMd ? "10px" : "33px" }}
>
step 5
</Typography>
<StepButtonsBlock
handleNextStep={handleNextStep}
handlePrevStep={handlePrevStep}
/>
</Box>
);
};

@ -0,0 +1,31 @@
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { FC } from "react";
type IntegrationStep6Props = {
handlePrevStep: () => void;
};
export const IntegrationStep6: FC<IntegrationStep6Props> = ({
handlePrevStep,
}) => {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Typography
sx={{ color: "#4D4D4D", mt: "5px", mb: upMd ? "10px" : "33px" }}
>
step 6
</Typography>
</Box>
);
};

@ -1,38 +1,121 @@
import { Dialog, IconButton, useTheme } from "@mui/material";
import { FC } from "react";
import {
Dialog,
IconButton,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import { FC, useMemo, useState } from "react";
import Box from "@mui/material/Box";
import CloseIcon from "@mui/icons-material/Close";
import { IntegrationStep1 } from "./IntegrationStep1/IntegrationStep1";
import { IntegrationStep2 } from "./IntegrationStep2/IntegrationStep2";
import { IntegrationStep3 } from "./IntegrationStep3/IntegrationStep3";
import { IntegrationStep4 } from "./IntegrationStep4/IntegrationStep4";
import { IntegrationStep5 } from "./IntegrationStep5/IntegrationStep5";
import { IntegrationStep6 } from "./IntegrationStep6/IntegrationStep6";
type IntegrationsModalProps = {
isModalOpen: boolean;
setIsModalOpen: (value: boolean) => void;
handleCloseModal: () => void;
companyName: string | null;
};
export const IntegrationsModal: FC<IntegrationsModalProps> = ({
isModalOpen,
setIsModalOpen,
handleCloseModal,
companyName,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const [step, setStep] = useState<number>(0);
function handleClose() {
setIsModalOpen(false);
}
const handleNextStep = () => {
setStep((prevState) => prevState + 1);
};
const handlePrevStep = () => {
setStep((prevState) => prevState - 1);
};
const steps = useMemo(
() => [
{
title: "Авторизация в аккаунте",
component: <IntegrationStep1 handleNextStep={handleNextStep} />,
},
{
title: "Выбор воронки",
component: (
<IntegrationStep2
handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep}
/>
),
},
{
title: "Выбор этапа воронки",
component: (
<IntegrationStep3
handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep}
/>
),
},
{
title: "Сделка",
component: (
<IntegrationStep4
handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep}
/>
),
},
{
title: "Название шага",
component: (
<IntegrationStep5
handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep}
/>
),
},
{
title: "Добавление тегов",
component: <IntegrationStep6 handlePrevStep={handlePrevStep} />,
},
],
[],
);
return (
<Dialog
open={isModalOpen}
onClose={handleClose}
onClose={handleCloseModal}
fullWidth
fullScreen={isMobile}
PaperProps={{
sx: {
maxWidth: "920px",
maxHeight: "660px",
maxWidth: isTablet ? "100%" : "920px",
maxHeight: isTablet ? "100%" : "660px",
borderRadius: "12px",
},
}}
>
<Box
sx={{
height: "68px",
backgroundColor: theme.palette.background.default,
}}
>
<Typography
sx={{ fontSize: "24px", fontWeight: "500", padding: "20px" }}
>
Интеграция с {companyName ? companyName : "партнером"}
</Typography>
</Box>
<IconButton
onClick={handleClose}
onClick={handleCloseModal}
sx={{
width: "12px",
height: "12px",
@ -47,10 +130,37 @@ export const IntegrationsModal: FC<IntegrationsModalProps> = ({
</IconButton>
<Box
sx={{
display: "flex",
flexDirection: "column",
width: "920px",
height: "660px",
height: "600px",
padding: "15px 20px 15px",
flexGrow: 1, // Add this line
}}
></Box>
>
<Typography
sx={{
fontSize: "24px",
color: "#4D4D4D",
fontWeight: "500",
lineHeight: "1",
}}
>
{steps[step].title}
</Typography>
<Typography
sx={{
color: "#9A9AAF",
fontWeight: "400",
marginTop: "4px",
fontSize: "14px",
lineHeight: "1",
}}
>
Шаг {step + 1}
</Typography>
<Box sx={{ flexGrow: 1 }}>{steps[step].component}</Box>
</Box>
</Dialog>
);
};

@ -0,0 +1,48 @@
import { Box, Button, useTheme } from "@mui/material";
import ArrowLeft from "@icons/questionsPage/arrowLeft";
import { FC } from "react";
type StepButtonsBlockProps = {
handlePrevStep: () => void;
handleNextStep: () => void;
};
export const StepButtonsBlock: FC<StepButtonsBlockProps> = ({
handlePrevStep,
handleNextStep,
}) => {
const theme = useTheme();
return (
<Box
sx={{
display: "flex",
gap: "10px",
marginTop: "auto",
marginLeft: "auto",
}}
>
<Button
variant="outlined"
sx={{ padding: "10px 20px", borderRadius: "8px", height: "44px" }}
data-cy="back-button"
onClick={handlePrevStep}
>
<ArrowLeft color={theme.palette.brightPurple.main} />
</Button>
<Button
data-cy="next-step"
variant="contained"
sx={{
height: "44px",
padding: "10px 20px",
borderRadius: "8px",
background: theme.palette.brightPurple.main,
fontSize: "18px",
}}
onClick={handleNextStep}
>
Далее
</Button>
</Box>
);
};

@ -22,8 +22,8 @@ export const IntegrationsPage = ({
const theme = useTheme();
const navigate = useNavigate();
const isMobile = useMediaQuery(theme.breakpoints.down(660));
const [step, setStep] = useState<number>(0);
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const [companyName, setCompanyName] = useState<string | null>(null);
useEffect(() => {
if (editQuizId === null) navigate("/list");
@ -47,6 +47,14 @@ export const IntegrationsPage = ({
return (
<Skeleton sx={{ width: "100vw", height: "100vh", transform: "none" }} />
);
const handleCloseModal = () => {
setIsModalOpen(false);
setTimeout(() => {
setCompanyName(null);
}, 300);
};
return (
<>
<Box
@ -69,10 +77,12 @@ export const IntegrationsPage = ({
<PartnersBoard
partners={partnersMock}
setIsModalOpen={setIsModalOpen}
setCompanyName={setCompanyName}
/>
<IntegrationsModal
isModalOpen={isModalOpen}
setIsModalOpen={setIsModalOpen}
handleCloseModal={handleCloseModal}
companyName={companyName}
/>
</Box>
</>

@ -5,15 +5,18 @@ import { Partner } from "../PartnersBoard";
type PartnerItemProps = {
partner: Partner;
setIsModalOpen: (value: boolean) => void;
setCompanyName: (value: string) => void;
};
export const PartnerItem: FC<PartnerItemProps> = ({
partner,
setIsModalOpen,
setCompanyName,
}) => {
const theme = useTheme();
const handleClick = () => {
setCompanyName(partner.name);
setIsModalOpen(true);
};

@ -11,11 +11,13 @@ export type Partner = {
type PartnersBoardProps = {
partners: Partner[];
setIsModalOpen: (value: boolean) => void;
setCompanyName: (value: string) => void;
};
export const PartnersBoard: FC<PartnersBoardProps> = ({
partners,
setIsModalOpen,
setCompanyName,
}) => {
const theme = useTheme();
@ -60,6 +62,7 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
key={partner.name}
partner={partner}
setIsModalOpen={setIsModalOpen}
setCompanyName={setCompanyName}
/>
))}
</Box>