frontPanel/src/pages/startPage/EditPage.tsx

444 lines
15 KiB
TypeScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { quizApi } from "@api/quiz";
import { LogoutButton } from "@ui_kit/LogoutButton";
import BackArrowIcon from "@icons/BackArrowIcon";
import { Burger } from "@icons/Burger";
import EyeIcon from "@icons/EyeIcon";
import { PenaLogoIcon } from "@icons/PenaLogoIcon";
import {
Box,
Button,
Container,
FormControl,
IconButton,
Switch,
TextField,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import { decrementCurrentStep, resetEditConfig, setQuizes, updateQuiz } from "@root/quizes/actions";
import { useCurrentQuiz } from "@root/quizes/hooks";
import { useQuizStore } from "@root/quizes/store";
import CustomAvatar from "@ui_kit/Header/Avatar";
import NavMenuItem from "@ui_kit/Header/NavMenuItem";
import PenaLogo from "@ui_kit/PenaLogo";
import Sidebar from "@ui_kit/Sidebar";
import Stepper from "@ui_kit/Stepper";
import SwitchStepPages from "@ui_kit/switchStepPages";
import { isAxiosError } from "axios";
import { enqueueSnackbar } from "notistack";
import React, { useEffect, useLayoutEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import useSWR from "swr";
import { useDebouncedCallback } from "use-debounce";
import { SidebarMobile } from "./Sidebar/SidebarMobile";
import { cleanQuestions, createResult, setQuestions } from "@root/questions/actions";
import { updateOpenBranchingPanel, updateCanCreatePublic, updateModalInfoWhyCantCreate } from "@root/uiTools/actions";
import { BranchingPanel } from "../Questions/BranchingPanel";
import { useQuestionsStore } from "@root/questions/store";
import { useQuizes } from "@root/quizes/hooks";
import { questionApi } from "@api/question";
import { useUiTools } from "@root/uiTools/store";
import Logotip from "../Landing/images/icons/QuizLogo";
import { clearUserData } from "@root/user";
import { clearAuthToken } from "@frontend/kitui";
import { logout } from "@api/auth";
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate";
import { type } from "os";
export default function EditPage() {
const quiz = useCurrentQuiz();
const { editQuizId } = useQuizStore();
const { questions } = useQuestionsStore();
useEffect(() => {
const getData = async () => {
const quizes = await quizApi.getList();
setQuizes(quizes);
const questions = await questionApi.getList({ quiz_id: editQuizId });
setQuestions(questions);
//Всегда должен существовать хоть 1 резулт - "line"
console.log(questions)
if (!questions?.find(q=>q.type === "result" && q.content.includes(':"line"') || q.content.includes(":'line'"))) createResult(quiz?.backendId, "line")
};
getData();
}, []);
const { openBranchingPanel, whyCantCreatePublic, canCreatePublic } = useUiTools();
const theme = useTheme();
const navigate = useNavigate();
const currentStep = useQuizStore((state) => state.currentStep);
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(660));
const [mobileSidebar, setMobileSidebar] = useState<boolean>(false);
const quizConfig = quiz?.config;
const disableTest = quiz === undefined ? true : (quiz.config.type === null)
useEffect(() => {
if (editQuizId === null) navigate("/list");
}, [navigate, editQuizId]);
useEffect(
() => {
return () => {
resetEditConfig();
cleanQuestions();
updateModalInfoWhyCantCreate(false)
}
},
[]
);
const updateQuestionHint = useDebouncedCallback((questions: AnyTypedQuizQuestion[]) => {
const problems: any = {}
questions.forEach((question) => {
//Если не участвует в ветвлении, или безтиповый, или резулт - он нам не интересен
if (question.type === null
|| question.type === "result"
|| question.content.rule.parentId.length === 0) return
//если есть дети, но нет дефолта - логическая ошибка. Так нельзя
if (question.content.rule.children.length > 0 && question.content.rule.default.length === 0) {
problems[question.content.id] = {
name: question.title,
problems: ["Не выбран дефолтный вопрос"]
}
}
})
useUiTools.setState({ whyCantCreatePublic: problems })
if (Object.keys(problems).length > 0) {
updateQuiz(quiz?.id, (state) => { state.status = "stop" })
updateCanCreatePublic(false)
} else {
updateCanCreatePublic(true)
}
}, 600);
useEffect(() => {
updateQuestionHint(questions)
}, [questions]);
async function handleLogoutClick() {
const [, logoutError] = await logout();
if (logoutError) {
return enqueueSnackbar(logoutError);
}
clearAuthToken();
clearUserData();
navigate("/");
}
console.log(questions)
if (!quizConfig) return <></>
return (
<>
{/*хедер*/}
<Container
component="nav"
maxWidth={false}
disableGutters
sx={{
px: "16px",
display: "flex",
height: isMobile ? "51px" : "80px",
alignItems: "center",
bgcolor: isMobile ? "#333647" : "white",
borderBottom: "1px solid #E3E3E3",
zIndex: theme.zIndex.drawer + 1,
}}
>
<Link to="/" style={{ display: "flex" }}>
{isMobile ? <Logotip width={100} /> : <Logotip width={124} />}
</Link>
<Box
sx={{
display: isMobile ? "none" : "flex",
alignItems: "center",
ml: "37px",
}}
>
<Link to="/list">
<IconButton sx={{ p: "6px" }}>
<BackArrowIcon />
</IconButton>
</Link>
<FormControl fullWidth variant="standard">
<TextField
fullWidth
id="project-name"
placeholder="Название проекта окно"
sx={{
width: "270px",
"& .MuiInputBase-root": {
height: "34px",
borderRadius: "8px",
p: 0,
},
}}
inputProps={{
sx: {
height: "20px",
borderRadius: "8px",
fontSize: "16px",
lineHeight: "20px",
p: "7px",
color: "black",
"&::placeholder": {
opacity: 1,
},
},
}}
/>
</FormControl>
</Box>
{isTablet ? (
<Box
sx={{
display: "flex",
ml: "auto",
}}
>
{isMobile ? (
<Burger
onClick={() => setMobileSidebar(!mobileSidebar)}
style={{ fontSize: "30px", color: "white", cursor: "pointer" }}
/>
) : (
<Box>
<CustomAvatar
sx={{
ml: "11px",
backgroundColor: theme.palette.orange.main,
height: "36px",
width: "36px",
}}
/>
</Box>
)}
</Box>
) : (
<>
<Box
sx={{
display: "flex",
gap: "30px",
overflow: "hidden",
ml: "20px",
}}
>
<NavMenuItem text="Редактировать" isActive />
<NavMenuItem text="Заявки" />
<NavMenuItem text="Аналитика" />
<NavMenuItem text="История" />
<NavMenuItem text="Помощь" />
</Box>
<Box
sx={{
display: "flex",
ml: "auto",
gap: "15px",
}}
>
<CustomAvatar
sx={{
ml: "11px",
backgroundColor: theme.palette.orange.main,
height: "36px",
width: "36px",
}}
/>
<LogoutButton onClick={handleLogoutClick} />
</Box>
</>
)}
</Container>
<Box
sx={{
display: isMobile ? "block" : "flex",
}}
>
{isMobile ? <SidebarMobile open={mobileSidebar} /> : <Sidebar />}
<Box
sx={{
background: theme.palette.background.default,
width: "100%",
padding: isMobile ? "16px 16px 140px 16px" : "25px 25px 140px 25px",
height: "calc(100vh - 80px)",
overflow: "auto",
boxSizing: "border-box",
}}
>
{/* Выбор текущей страницы редактирования чего-либо находится здесь */}
{quizConfig && (
<>
<Stepper activeStep={currentStep} />
<SwitchStepPages
activeStep={currentStep}
quizType={quizConfig.type}
quizResults={quizConfig.results}
quizStartPageType={quizConfig.startpageType}
/>
</>
)}
</Box>
<Box
sx={{
position: "absolute",
left: 0,
bottom: 0,
width: "100%",
padding: isMobile ? "20px 16px" : "20px 40px 20px 250px",
display: "flex",
justifyContent: "flex-start",
alignItems: "center",
gap: "15px",
background: "#FFF",
}}
>
{[1].includes(currentStep) && !openBranchingPanel && quizConfig.type !== "form" && (
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "15px",
padding: "18px",
background: "#fff",
borderRadius: "12px",
boxShadow: "0px 10px 30px #e7e7e7",
}}
>
<Switch
checked={openBranchingPanel}
onChange={(e) => updateOpenBranchingPanel(e.target.checked)}
sx={{
width: 50,
height: 30,
padding: 0,
"& .MuiSwitch-switchBase": {
padding: 0,
margin: "2px",
transitionDuration: "300ms",
"&.Mui-checked": {
transform: "translateX(20px)",
color: theme.palette.brightPurple.main,
"& + .MuiSwitch-track": {
backgroundColor: "#E8DCF9",
opacity: 1,
border: 0,
},
"&.Mui-disabled + .MuiSwitch-track": { opacity: 0.5 },
},
"&.Mui-disabled .MuiSwitch-thumb": {
color: theme.palette.mode === "light" ? theme.palette.grey[100] : theme.palette.grey[600],
},
"&.Mui-disabled + .MuiSwitch-track": {
opacity: theme.palette.mode === "light" ? 0.7 : 0.3,
},
},
"& .MuiSwitch-thumb": {
boxSizing: "border-box",
width: 25,
height: 25,
},
"& .MuiSwitch-track": {
borderRadius: 13,
backgroundColor: theme.palette.mode === "light" ? "#E9E9EA" : "#39393D",
opacity: 1,
transition: theme.transitions.create(["background-color"], {
duration: 500,
}),
},
}}
/>
<Box>
<Typography sx={{ fontWeight: "bold", color: "#4D4D4D" }}>Логика ветвления</Typography>
</Box>
</Box>
)}
{!canCreatePublic && quiz.config.type !== "form" ?
<Button
variant="contained"
// disabled
sx={{
fontSize: "14px",
lineHeight: "18px",
height: "34px",
minWidth: "130px",
}}
onClick={() => Object.keys(whyCantCreatePublic).length === 0 ? () => { } : updateModalInfoWhyCantCreate(true)}
>
Тестовый просмотр
</Button>
:
<a href={`/view`} target="_blank" rel="noreferrer" style={{ textDecoration: "none" }}>
<Button
variant="contained"
sx={{
fontSize: "14px",
lineHeight: "18px",
height: "34px",
minWidth: "130px",
}}
>
Тестовый просмотр
</Button>
</a>
}
<Button
variant="outlined"
sx={{
fontSize: "14px",
lineHeight: "18px",
height: "34px",
border: `1px solid ${theme.palette.brightPurple.main}`,
backgroundColor: quiz?.status === "start" ? theme.palette.brightPurple.main : "transparent",
color: quiz?.status === "start" ? "#FFFFFF" : theme.palette.brightPurple.main,
}}
onClick={
Object.keys(whyCantCreatePublic).length === 0 ?
() => updateQuiz(quiz?.id, (state) => {
state.status = quiz?.status === "start" ? "stop" : "start";
})
:
() => updateModalInfoWhyCantCreate(true)
}
>
{quiz?.status === "start" ? "Стоп" : "Старт"}
</Button>
{quiz?.status === "start" && <Box
component={Link}
sx={{
color: "#7e2aea",
fontSize: "14px"
}}
target="_blank" to={"https://hbpn.link/" + quiz.qid}>https://hbpn.link/{quiz.qid}
</Box>}
</Box>
</Box >
<ModalInfoWhyCantCreate />
</>
);
}