Merge branch 'dev' into 'main'
поменял лого , обновил навигацию стрелок , обновил модалки (добавил ссылку на... See merge request frontend/squiz!78
This commit is contained in:
commit
2fcd6df97b
45
src/api/quizRelase.ts
Normal file
45
src/api/quizRelase.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { CreateQuestionRequest } from "model/question/create";
|
||||
import { RawQuestion } from "model/question/question";
|
||||
import { GetQuestionListRequest, GetQuestionListResponse } from "@model/question/getList";
|
||||
import { EditQuestionRequest, EditQuestionResponse } from "@model/question/edit";
|
||||
import { DeleteQuestionRequest, DeleteQuestionResponse } from "@model/question/delete";
|
||||
import { CopyQuestionRequest, CopyQuestionResponse } from "@model/question/copy";
|
||||
|
||||
|
||||
const baseUrl = process.env.NODE_ENV === "production" ? "/squiz" : "https://squiz.pena.digital";
|
||||
|
||||
function get(quizId: string) {
|
||||
return makeRequest<any>({
|
||||
url: `${baseUrl}/question/copy`,
|
||||
body: { id: questionId, quiz_id: quizId },
|
||||
method: "POST",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function quizRelase(quizId: string, status: "start"|"stop") {
|
||||
return makeRequest<any>({
|
||||
url: `https://squiz.pena.digital/answer/quiz/get`,
|
||||
body: {
|
||||
quiz_id: quizId,
|
||||
limit: 100,
|
||||
page: 0,
|
||||
need_config: true,
|
||||
|
||||
},
|
||||
method: "POST",
|
||||
});
|
||||
}
|
||||
|
||||
export const relaseApi = {
|
||||
relase: quizRelase,
|
||||
get: quizRelase,
|
||||
};
|
||||
|
||||
|
||||
const defaultGetQuestionListBody: GetQuestionListRequest = {
|
||||
"limit": 100,
|
||||
"offset": 0,
|
||||
"type": "",
|
||||
};
|
18
src/assets/icons/NameplateLogo.tsx
Normal file
18
src/assets/icons/NameplateLogo.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import { FC, SVGProps } from "react";
|
||||
|
||||
export const NameplateLogo: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||
<svg {...props} height="1em" viewBox="0 0 89 81" fill="none">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M34.5604 0.0885217C24.3105 -1.09878 17.239 9.91147 10.6615 17.8703C4.88905 24.8549 0.590996 32.7441 0.0917664 41.7955C-0.439369 51.4255 1.3075 61.4545 7.86805 68.5172C14.6258 75.7923 24.7486 80.3889 34.5604 78.9028C43.5576 77.54 47.5388 67.6598 54.2372 61.4939C61.5105 54.799 75.061 51.6851 74.8731 41.7955C74.6848 31.8908 60.3836 29.952 53.5024 22.8328C46.3747 15.4585 44.7425 1.26797 34.5604 0.0885217Z"
|
||||
fill="#7E2AEA"
|
||||
/>
|
||||
<circle cx="60.0543" cy="75.1555" r="5.65583" fill="#7E2AEA" />
|
||||
<circle cx="54.4046" cy="12.3947" r="2.1546" fill="#7E2AEA" />
|
||||
<path
|
||||
d="M88.866 39.4685C88.2378 33.3607 85.3643 27.7037 80.8025 23.594C76.2408 19.4843 70.3156 17.2146 64.1757 17.2248C63.3039 17.2252 62.4328 17.2708 61.5658 17.3614C55.4608 18.0025 49.8093 20.8814 45.7015 25.443C41.5937 30.0046 39.3205 35.9256 39.3203 42.0642V42.0642V77.549H49.9658V62.468C54.128 65.3636 59.0787 66.9119 64.1491 66.9036C65.0208 66.9033 65.8919 66.8577 66.759 66.767C70.0031 66.426 73.1483 65.4494 76.0151 63.8929C78.8818 62.3364 81.4138 60.2305 83.4667 57.6955C85.5195 55.1604 87.0529 52.2458 87.9793 49.1181C88.9058 45.9904 89.2071 42.7109 88.866 39.4667V39.4685ZM75.1937 51.0011C74.0243 52.4537 72.5783 53.6599 70.9395 54.5498C69.3007 55.4397 67.5017 55.9956 65.6465 56.1854C65.149 56.2371 64.6492 56.2631 64.1491 56.2635C60.9296 56.2605 57.8068 55.1631 55.2932 53.1515C52.7796 51.1398 51.0245 48.3334 50.3161 45.1929C49.6077 42.0523 49.988 38.7642 51.3945 35.8683C52.8011 32.9723 55.1504 30.6406 58.0568 29.2558C60.9632 27.871 64.2541 27.5154 67.3892 28.2473C70.5244 28.9793 73.3176 30.7553 75.3103 33.284C77.303 35.8126 78.3769 38.9436 78.3558 42.1629C78.3346 45.3823 77.2196 48.4989 75.1937 51.0011Z"
|
||||
fill="#151515"
|
||||
/>
|
||||
</svg>
|
||||
);
|
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@ export const BranchingQuestionsModal = ({
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
overflow: "hidden",
|
||||
overflow: "auto",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
@ -44,6 +44,7 @@ export const BranchingQuestionsModal = ({
|
||||
borderRadius: "12px",
|
||||
boxShadow: 24,
|
||||
padding: "30px 0",
|
||||
height: "80vh"
|
||||
}}
|
||||
>
|
||||
<Box sx={{ margin: "0 auto", maxWidth: "350px" }}>
|
||||
|
@ -232,6 +232,7 @@ export default function ButtonsOptions({
|
||||
// myFunc(question);
|
||||
}}
|
||||
sx={{
|
||||
display: quiz.config.type === "form" ? "none" : "flex",
|
||||
backgroundColor:
|
||||
switchState === value
|
||||
? theme.palette.brightPurple.main
|
||||
|
@ -259,6 +259,7 @@ export default function ButtonsOptionsAndPict({
|
||||
updateDesireToOpenABranchingModal(question.content.id);
|
||||
}}
|
||||
sx={{
|
||||
display: quiz.config.type === "form" ? "none" : "flex",
|
||||
height: "30px",
|
||||
maxWidth: "103px",
|
||||
minWidth: isIconMobile ? "30px" : "64px",
|
||||
|
@ -70,7 +70,7 @@ export default function QuestionsPage() {
|
||||
sx={{
|
||||
position: "fixed",
|
||||
left: isMobile ? "20px" : "250px",
|
||||
bottom: isMobile ? "140px" : "20px",
|
||||
bottom: "140px",
|
||||
}}
|
||||
data-cy="create-question"
|
||||
>
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { Box, Typography } from "@mui/material";
|
||||
|
||||
export const ApologyPage = (message: string) => {
|
||||
export const ApologyPage = ({message}:{message: string}) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center"
|
||||
justifyContent: "center",
|
||||
height: "100vh"
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
|
@ -1,16 +1,14 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Box, Button, useTheme } from "@mui/material";
|
||||
import { Box, Button, Typography, useTheme } from "@mui/material";
|
||||
|
||||
import { useQuizViewStore } from "@root/quizView";
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||
import { useQuestionsStore } from "@root/questions/store";
|
||||
|
||||
import type {
|
||||
AnyTypedQuizQuestion,
|
||||
QuizQuestionBase,
|
||||
} from "../../model/questionTypes/shared";
|
||||
import type { AnyTypedQuizQuestion, QuizQuestionBase } from "../../model/questionTypes/shared";
|
||||
import { getQuestionByContentId } from "@root/questions/actions";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { NameplateLogo } from "@icons/NameplateLogo";
|
||||
|
||||
type FooterProps = {
|
||||
setCurrentQuestion: (step: AnyTypedQuizQuestion) => void;
|
||||
@ -19,22 +17,14 @@ type FooterProps = {
|
||||
setShowResultForm: (show: boolean) => void;
|
||||
};
|
||||
|
||||
export const Footer = ({
|
||||
setCurrentQuestion,
|
||||
question,
|
||||
setShowContactForm,
|
||||
setShowResultForm,
|
||||
}: FooterProps) => {
|
||||
const [disablePreviousButton, setDisablePreviousButton] =
|
||||
useState<boolean>(false);
|
||||
export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setShowResultForm }: FooterProps) => {
|
||||
const [disablePreviousButton, setDisablePreviousButton] = useState<boolean>(false);
|
||||
const [disableNextButton, setDisableNextButton] = useState<boolean>(false);
|
||||
const quiz = useCurrentQuiz();
|
||||
const { answers } = useQuizViewStore();
|
||||
const questions = useQuestionsStore().questions as AnyTypedQuizQuestion[];
|
||||
const theme = useTheme();
|
||||
const linear = !questions.find(
|
||||
({ content }) => content.rule.parentId === "root"
|
||||
);
|
||||
const linear = !questions.find(({ content }) => content.rule.parentId === "root");
|
||||
|
||||
useEffect(() => {
|
||||
// Логика для аргумента disabled у кнопки "Назад"
|
||||
@ -57,9 +47,7 @@ export const Footer = ({
|
||||
}
|
||||
|
||||
// Логика для аргумента disabled у кнопки "Далее"
|
||||
const answer = answers.find(
|
||||
({ questionId }) => questionId === question.content.id
|
||||
);
|
||||
const answer = answers.find(({ questionId }) => questionId === question.content.id);
|
||||
|
||||
if ("required" in question.content && question.content.required && answer) {
|
||||
setDisableNextButton(false);
|
||||
@ -67,11 +55,7 @@ export const Footer = ({
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
"required" in question.content &&
|
||||
question.content.required &&
|
||||
!answer
|
||||
) {
|
||||
if ("required" in question.content && question.content.required && !answer) {
|
||||
setDisableNextButton(true);
|
||||
|
||||
return;
|
||||
@ -85,9 +69,7 @@ export const Footer = ({
|
||||
if (nextQuestionId) {
|
||||
setDisableNextButton(false);
|
||||
} else {
|
||||
const nextQuestion = getQuestionByContentId(
|
||||
question.content.rule.default
|
||||
);
|
||||
const nextQuestion = getQuestionByContentId(question.content.rule.default);
|
||||
|
||||
if (nextQuestion?.type) {
|
||||
setDisableNextButton(false);
|
||||
@ -95,9 +77,8 @@ export const Footer = ({
|
||||
}
|
||||
}, [question, answers]);
|
||||
|
||||
const showResult = nextQuestion => {
|
||||
|
||||
console.log(nextQuestion)
|
||||
const showResult = (nextQuestion) => {
|
||||
console.log(nextQuestion);
|
||||
|
||||
if (nextQuestion && quiz?.config.resultInfo.when === "before") {
|
||||
setShowResultForm(true);
|
||||
@ -108,44 +89,34 @@ export const Footer = ({
|
||||
|
||||
const getNextQuestionId = () => {
|
||||
if (answers.length) {
|
||||
const answer = answers.find(
|
||||
({ questionId }) => questionId === question.content.id
|
||||
);
|
||||
const answer = answers.find(({ questionId }) => questionId === question.content.id);
|
||||
|
||||
let readyBeNextQuestion = "";
|
||||
|
||||
(question as QuizQuestionBase).content.rule.main.forEach(
|
||||
({ next, rules }) => {
|
||||
let longerArray = Math.max(
|
||||
rules[0].answers.length,
|
||||
answer?.answer && Array.isArray(answer?.answer)
|
||||
? answer?.answer.length
|
||||
: [answer?.answer].length
|
||||
);
|
||||
(question as QuizQuestionBase).content.rule.main.forEach(({ next, rules }) => {
|
||||
let longerArray = Math.max(
|
||||
rules[0].answers.length,
|
||||
answer?.answer && Array.isArray(answer?.answer) ? answer?.answer.length : [answer?.answer].length
|
||||
);
|
||||
|
||||
for (
|
||||
var i = 0;
|
||||
i < longerArray;
|
||||
i++ // Цикл по всем элементам бОльшего массива
|
||||
) {
|
||||
if (Array.isArray(answer?.answer)) {
|
||||
if (
|
||||
answer?.answer.find((item) =>
|
||||
String(item === rules[0].answers[i])
|
||||
)
|
||||
) {
|
||||
readyBeNextQuestion = next; // Если хоть один элемент отличается, массивы не равны
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (String(rules[0].answers[i]) === answer?.answer) {
|
||||
for (
|
||||
var i = 0;
|
||||
i < longerArray;
|
||||
i++ // Цикл по всем элементам бОльшего массива
|
||||
) {
|
||||
if (Array.isArray(answer?.answer)) {
|
||||
if (answer?.answer.find((item) => String(item === rules[0].answers[i]))) {
|
||||
readyBeNextQuestion = next; // Если хоть один элемент отличается, массивы не равны
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (String(rules[0].answers[i]) === answer?.answer) {
|
||||
readyBeNextQuestion = next; // Если хоть один элемент отличается, массивы не равны
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
return readyBeNextQuestion;
|
||||
}
|
||||
@ -181,12 +152,14 @@ export const Footer = ({
|
||||
const questionIndex = questions.findIndex(({ id }) => id === question.id);
|
||||
const nextQuestion = questions[questionIndex + 1];
|
||||
|
||||
console.log(nextQuestion)
|
||||
console.log("questionIndex ", questionIndex);
|
||||
console.log(nextQuestion);
|
||||
console.log(questions);
|
||||
if (nextQuestion && nextQuestion.type !== "result") {
|
||||
console.log("следующий вопрос результирующий ", (nextQuestion.type === "result"))
|
||||
console.log("следующий вопрос результирующий ", nextQuestion.type === "result");
|
||||
setCurrentQuestion(nextQuestion);
|
||||
} else {
|
||||
console.log("следующий вопрос результирующий ", (nextQuestion.type === "result"))
|
||||
console.log("следующий вопрос результирующий ", nextQuestion.type === "result");
|
||||
showResult(nextQuestion);
|
||||
}
|
||||
|
||||
@ -205,9 +178,7 @@ export const Footer = ({
|
||||
enqueueSnackbar("не могу получить последующий вопрос");
|
||||
}
|
||||
} else {
|
||||
const nextQuestion = getQuestionByContentId(
|
||||
question.content.rule.default
|
||||
);
|
||||
const nextQuestion = getQuestionByContentId(question.content.rule.default);
|
||||
if (nextQuestion?.type && nextQuestion.type !== "result") {
|
||||
setCurrentQuestion(nextQuestion);
|
||||
} else {
|
||||
@ -219,10 +190,25 @@ export const Footer = ({
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: "relative",
|
||||
padding: "15px 0",
|
||||
borderTop: `1px solid ${theme.palette.grey[400]}`,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
position: "absolute",
|
||||
top: "-45px",
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
gap: "8px",
|
||||
}}
|
||||
>
|
||||
<NameplateLogo style={{ fontSize: "34px" }} />
|
||||
<Typography sx={{ fontSize: "20px", color: "#4D4D4D", whiteSpace: "nowrap" }}>Сделано на PenaQuiz</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
|
@ -198,9 +198,14 @@ export default function SigninDialog() {
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ color: "#7E2AEA", textAlign: "center" }}>Вы еще не присоединились?</Typography>
|
||||
<Link component={RouterLink} to="/signup" sx={{ color: "#7E2AEA" }}>
|
||||
Регистрация
|
||||
</Link>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
||||
<Link component={RouterLink} to="/signup" sx={{ color: "#7E2AEA" }}>
|
||||
Регистрация
|
||||
</Link>
|
||||
<Link component={RouterLink} to="/restore" sx={{ color: "#7E2AEA" }}>
|
||||
Забыли пароль
|
||||
</Link>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Dialog>
|
||||
|
@ -200,6 +200,7 @@ export default function SignupDialog() {
|
||||
>
|
||||
Зарегистрироваться
|
||||
</Button>
|
||||
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to="/signin"
|
||||
@ -211,6 +212,9 @@ export default function SignupDialog() {
|
||||
>
|
||||
Вход в личный кабинет
|
||||
</Link>
|
||||
<Link component={RouterLink} to="/restore" sx={{ color: "#7E2AEA" }}>
|
||||
Забыли пароль
|
||||
</Link>
|
||||
</Box>
|
||||
</Dialog>
|
||||
);
|
||||
|
@ -3,6 +3,7 @@ import SectionWrapper from "@ui_kit/SectionWrapper";
|
||||
import ComplexNavText from "./ComplexNavText";
|
||||
import { createQuiz } from "@root/quizes/actions";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { resetEditConfig } from "@root/quizes/actions";
|
||||
|
||||
|
||||
export default function FirstQuiz() {
|
||||
@ -29,7 +30,10 @@ export default function FirstQuiz() {
|
||||
<Button
|
||||
variant="contained"
|
||||
data-cy="create-quiz"
|
||||
onClick={() => createQuiz(navigate)}
|
||||
onClick={() => {
|
||||
resetEditConfig()
|
||||
createQuiz(navigate)
|
||||
}}
|
||||
>
|
||||
Создать +
|
||||
</Button>
|
||||
|
@ -4,6 +4,7 @@ import { useQuizes } from "@root/quizes/hooks";
|
||||
import SectionWrapper from "@ui_kit/SectionWrapper";
|
||||
import React from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { resetEditConfig } from "@root/quizes/actions";
|
||||
import ComplexNavText from "./ComplexNavText";
|
||||
import FirstQuiz from "./FirstQuiz";
|
||||
import QuizCard from "./QuizCard";
|
||||
@ -42,7 +43,10 @@ export default function MyQuizzesFull({ outerContainerSx: sx, children }: Props)
|
||||
padding: isMobile ? "10px" : "10px 47px",
|
||||
minWidth: "44px",
|
||||
}}
|
||||
onClick={() => createQuiz(navigate)}
|
||||
onClick={() => {
|
||||
resetEditConfig();
|
||||
createQuiz(navigate)
|
||||
}}
|
||||
data-cy="create-quiz"
|
||||
>
|
||||
{isMobile ? "+" : "Создать +"}
|
||||
|
@ -4,159 +4,142 @@ import LinkIcon from "@icons/LinkIcon";
|
||||
import PencilIcon from "@icons/PencilIcon";
|
||||
import { Quiz } from "@model/quiz/quiz";
|
||||
import MoreHorizIcon from "@mui/icons-material/MoreHoriz";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
IconButton,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
Popover,
|
||||
|
||||
} from "@mui/material";
|
||||
import { Box, Button, IconButton, Typography, useMediaQuery, useTheme, Popover } from "@mui/material";
|
||||
import { deleteQuiz, setEditQuizId } from "@root/quizes/actions";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
|
||||
interface Props {
|
||||
quiz: Quiz;
|
||||
openCount?: number;
|
||||
applicationCount?: number;
|
||||
conversionPercent?: number;
|
||||
quiz: Quiz;
|
||||
openCount?: number;
|
||||
applicationCount?: number;
|
||||
conversionPercent?: number;
|
||||
}
|
||||
|
||||
export default function QuizCard({
|
||||
quiz,
|
||||
openCount = 0,
|
||||
applicationCount = 0,
|
||||
conversionPercent = 0,
|
||||
}: Props) {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
||||
const navigate = useNavigate();
|
||||
export default function QuizCard({ quiz, openCount = 0, applicationCount = 0, conversionPercent = 0 }: Props) {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
||||
const navigate = useNavigate();
|
||||
const [subMenuOpen, setSubMenuOpen] = useState<boolean>(false);
|
||||
const subMenuRef = useRef<HTMLButtonElement | null>(null);
|
||||
|
||||
function handleEditClick() {
|
||||
setEditQuizId(quiz.backendId);
|
||||
navigate("/edit");
|
||||
}
|
||||
function handleEditClick() {
|
||||
setEditQuizId(quiz.backendId);
|
||||
navigate("/edit");
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
backgroundColor: "white",
|
||||
width: "560px",
|
||||
height: "280px",
|
||||
p: "20px",
|
||||
borderRadius: "12px",
|
||||
boxSizing: "border-box",
|
||||
boxShadow: `0px 100px 309px rgba(210, 208, 225, 0.24),
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
backgroundColor: "white",
|
||||
width: "560px",
|
||||
height: "280px",
|
||||
p: "20px",
|
||||
borderRadius: "12px",
|
||||
boxSizing: "border-box",
|
||||
boxShadow: `0px 100px 309px rgba(210, 208, 225, 0.24),
|
||||
0px 41.7776px 129.093px rgba(210, 208, 225, 0.172525),
|
||||
0px 22.3363px 69.0192px rgba(210, 208, 225, 0.143066),
|
||||
0px 12.5216px 38.6916px rgba(210, 208, 225, 0.12),
|
||||
0px 6.6501px 20.5488px rgba(210, 208, 225, 0.0969343),
|
||||
0px 2.76726px 8.55082px rgba(210, 208, 225, 0.0674749)`,
|
||||
}}
|
||||
}}
|
||||
>
|
||||
<Typography variant="h5">{quiz.name}</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
mt: "10px",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
<LinkIcon bgcolor="#EEE4FC" color={theme.palette.brightPurple.main} />
|
||||
<Typography color={theme.palette.grey3.main}>быстрая ссылка ...</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
mt: "32px",
|
||||
mr: "22px",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flex: "1 1 0" }}>
|
||||
<Typography variant="h5">{openCount}</Typography>
|
||||
<Typography color={theme.palette.grey3.main}>Открытий</Typography>
|
||||
</Box>
|
||||
<Box sx={{ flex: "1 1 0" }}>
|
||||
<Typography variant="h5">{applicationCount}</Typography>
|
||||
<Typography color={theme.palette.grey3.main}>Заявок</Typography>
|
||||
</Box>
|
||||
<Box sx={{ flex: "1 1 0" }}>
|
||||
<Typography variant="h5">{conversionPercent} %</Typography>
|
||||
<Typography color={theme.palette.grey3.main}>Конверсия</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mt: "auto",
|
||||
display: "flex",
|
||||
gap: isMobile ? "10px" : "20px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
padding: "10px 39px",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h5">{quiz.name}</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
mt: "10px",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
<LinkIcon bgcolor="#EEE4FC" color={theme.palette.brightPurple.main} />
|
||||
<Typography color={theme.palette.grey3.main}>
|
||||
быстрая ссылка ...
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
mt: "32px",
|
||||
mr: "22px",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flex: "1 1 0" }}>
|
||||
<Typography variant="h5">{openCount}</Typography>
|
||||
<Typography color={theme.palette.grey3.main}>Открытий</Typography>
|
||||
</Box>
|
||||
<Box sx={{ flex: "1 1 0" }}>
|
||||
<Typography variant="h5">{applicationCount}</Typography>
|
||||
<Typography color={theme.palette.grey3.main}>Заявок</Typography>
|
||||
</Box>
|
||||
<Box sx={{ flex: "1 1 0" }}>
|
||||
<Typography variant="h5">{conversionPercent} %</Typography>
|
||||
<Typography color={theme.palette.grey3.main}>Конверсия</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
mt: "auto",
|
||||
display: "flex",
|
||||
gap: isMobile ? "10px" : "20px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
padding: "10px 39px",
|
||||
}}
|
||||
>
|
||||
Заявки
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<PencilIcon />}
|
||||
onClick={handleEditClick}
|
||||
sx={{
|
||||
padding: isMobile ? "10px" : "10px 20px",
|
||||
minWidth: "unset",
|
||||
color: theme.palette.brightPurple.main,
|
||||
"& .MuiButton-startIcon": {
|
||||
marginRight: isMobile ? 0 : "4px",
|
||||
marginLeft: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{isMobile ? "" : "Редактировать"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<ChartIcon />}
|
||||
sx={{
|
||||
minWidth: "46px",
|
||||
padding: "10px 10px",
|
||||
"& .MuiButton-startIcon": {
|
||||
mr: 0,
|
||||
ml: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<IconButton
|
||||
ref={subMenuRef}
|
||||
sx={{
|
||||
color: theme.palette.brightPurple.main,
|
||||
ml: "auto",
|
||||
}}
|
||||
onClick={() => setSubMenuOpen(true)}
|
||||
data-cy="delete-quiz"
|
||||
>
|
||||
<MoreHorizIcon sx={{ transform: "scale(1.75)" }} />
|
||||
</IconButton>
|
||||
<Popover
|
||||
open={subMenuOpen}
|
||||
anchorEl={subMenuRef.current}
|
||||
onClose={() => setSubMenuOpen(false)}
|
||||
anchorOrigin={{ vertical: "top", horizontal: "right" }}
|
||||
>
|
||||
<Box onClick={() => setSubMenuOpen(false)}>
|
||||
{/* <Button
|
||||
Заявки
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<PencilIcon />}
|
||||
onClick={handleEditClick}
|
||||
sx={{
|
||||
padding: isMobile ? "10px" : "10px 20px",
|
||||
minWidth: "unset",
|
||||
color: theme.palette.brightPurple.main,
|
||||
"& .MuiButton-startIcon": {
|
||||
marginRight: isMobile ? 0 : "4px",
|
||||
marginLeft: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{isMobile ? "" : "Редактировать"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<ChartIcon />}
|
||||
sx={{
|
||||
minWidth: "46px",
|
||||
padding: "10px 10px",
|
||||
"& .MuiButton-startIcon": {
|
||||
mr: 0,
|
||||
ml: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<IconButton
|
||||
ref={subMenuRef}
|
||||
sx={{
|
||||
color: theme.palette.brightPurple.main,
|
||||
ml: "auto",
|
||||
}}
|
||||
onClick={() => setSubMenuOpen(true)}
|
||||
data-cy="delete-quiz"
|
||||
>
|
||||
<MoreHorizIcon sx={{ transform: "scale(1.75)" }} />
|
||||
</IconButton>
|
||||
<Popover
|
||||
open={subMenuOpen}
|
||||
anchorEl={subMenuRef.current}
|
||||
onClose={() => setSubMenuOpen(false)}
|
||||
anchorOrigin={{ vertical: "top", horizontal: "right" }}
|
||||
>
|
||||
<Box onClick={() => setSubMenuOpen(false)}>
|
||||
{/* <Button
|
||||
sx={{
|
||||
display: "block",
|
||||
width: "100%",
|
||||
@ -166,19 +149,19 @@ export default function QuizCard({
|
||||
>
|
||||
Копировать
|
||||
</Button> */}
|
||||
<Button
|
||||
sx={{
|
||||
display: "block",
|
||||
width: "100%",
|
||||
padding: "15px 30px",
|
||||
}}
|
||||
onClick={() => deleteQuiz(quiz.id)}
|
||||
>
|
||||
Удалить
|
||||
</Button>
|
||||
</Box>
|
||||
</Popover>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
<Button
|
||||
sx={{
|
||||
display: "block",
|
||||
width: "100%",
|
||||
padding: "15px 30px",
|
||||
}}
|
||||
onClick={() => deleteQuiz(quiz.id)}
|
||||
>
|
||||
Удалить
|
||||
</Button>
|
||||
</Box>
|
||||
</Popover>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -5,16 +5,18 @@ 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,
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
FormControl,
|
||||
IconButton,
|
||||
Switch,
|
||||
TextField,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { decrementCurrentStep, resetEditConfig, setQuizes } from "@root/quizes/actions";
|
||||
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";
|
||||
@ -25,7 +27,7 @@ import Stepper from "@ui_kit/Stepper";
|
||||
import SwitchStepPages from "@ui_kit/switchStepPages";
|
||||
import { isAxiosError } from "axios";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { useEffect, useState } from "react";
|
||||
import React, { useEffect, useLayoutEffect, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import useSWR from "swr";
|
||||
import { SidebarMobile } from "./Sidebar/SidebarMobile";
|
||||
@ -37,307 +39,318 @@ import { useQuizes } from "@root/quizes/hooks";
|
||||
import { questionApi } from "@api/question";
|
||||
import { useUiTools } from "@root/uiTools/store";
|
||||
|
||||
|
||||
|
||||
import Logotip from "../Landing/images/icons/QuizLogo";
|
||||
|
||||
export default function EditPage() {
|
||||
const quiz = useCurrentQuiz();
|
||||
const { editQuizId } = useQuizStore();
|
||||
const quiz = useCurrentQuiz();
|
||||
const { editQuizId } = useQuizStore();
|
||||
|
||||
useEffect(() => {
|
||||
const getData = async () => {
|
||||
const quizes = await quizApi.getList()
|
||||
setQuizes(quizes)
|
||||
useEffect(() => {
|
||||
const getData = async () => {
|
||||
const quizes = await quizApi.getList();
|
||||
setQuizes(quizes);
|
||||
|
||||
const questions = await questionApi.getList({ quiz_id: editQuizId })
|
||||
setQuestions(questions)
|
||||
const questions = await questionApi.getList({ quiz_id: editQuizId });
|
||||
setQuestions(questions);
|
||||
};
|
||||
getData();
|
||||
}, []);
|
||||
|
||||
}
|
||||
getData()
|
||||
}, [])
|
||||
const { openBranchingPanel } = 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)
|
||||
|
||||
const { openBranchingPanel } = 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;
|
||||
useEffect(() => {
|
||||
if (editQuizId === null) navigate("/list");
|
||||
}, [navigate, editQuizId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editQuizId === null) navigate("/list");
|
||||
}, [navigate, editQuizId]);
|
||||
useEffect(
|
||||
() => () => {
|
||||
resetEditConfig();
|
||||
cleanQuestions();
|
||||
},
|
||||
[]
|
||||
);
|
||||
console.log(currentStep)
|
||||
|
||||
useEffect(() => () => {
|
||||
resetEditConfig();
|
||||
cleanQuestions();
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{/*хедер*/}
|
||||
<Container
|
||||
component="nav"
|
||||
maxWidth={false}
|
||||
disableGutters
|
||||
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 ? <PenaLogoIcon style={{ fontSize: "39px", color: "white" }} /> : <PenaLogo 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" }}
|
||||
/>
|
||||
) : (
|
||||
<CustomAvatar
|
||||
sx={{
|
||||
px: "16px",
|
||||
display: "flex",
|
||||
height: isMobile ? "51px" : "80px",
|
||||
alignItems: "center",
|
||||
bgcolor: isMobile ? "#333647" : "white",
|
||||
borderBottom: "1px solid #E3E3E3",
|
||||
zIndex: theme.zIndex.drawer + 1,
|
||||
ml: "11px",
|
||||
backgroundColor: theme.palette.orange.main,
|
||||
height: "36px",
|
||||
width: "36px",
|
||||
}}
|
||||
>
|
||||
<Link to="/" style={{ display: "flex" }}>
|
||||
{isMobile ? (
|
||||
<PenaLogoIcon style={{ fontSize: "39px", color: "white" }} />
|
||||
) : (
|
||||
<PenaLogo width={124} />
|
||||
)}
|
||||
</Link>
|
||||
<Box
|
||||
sx={{
|
||||
display: isMobile ? "none" : "flex",
|
||||
alignItems: "center",
|
||||
ml: "37px",
|
||||
}}
|
||||
>
|
||||
<IconButton sx={{ p: "6px" }} onClick={decrementCurrentStep}>
|
||||
<BackArrowIcon />
|
||||
</IconButton>
|
||||
<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" }}
|
||||
/>
|
||||
) : (
|
||||
<CustomAvatar
|
||||
sx={{
|
||||
ml: "11px",
|
||||
backgroundColor: theme.palette.orange.main,
|
||||
height: "36px",
|
||||
width: "36px",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</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",
|
||||
}}
|
||||
>
|
||||
<a href={`/view`} target="_blank" rel="noreferrer" style={{ textDecoration: "none" }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
lineHeight: "18px",
|
||||
height: "34px",
|
||||
}}
|
||||
>
|
||||
Опубликовать
|
||||
</Button>
|
||||
</a>
|
||||
<CustomAvatar
|
||||
sx={{
|
||||
ml: "11px",
|
||||
backgroundColor: theme.palette.orange.main,
|
||||
height: "36px",
|
||||
width: "36px",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Container>
|
||||
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
) : (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: isMobile ? "block" : "flex",
|
||||
}}
|
||||
sx={{
|
||||
display: "flex",
|
||||
gap: "30px",
|
||||
overflow: "hidden",
|
||||
ml: "20px",
|
||||
}}
|
||||
>
|
||||
{isMobile ? <SidebarMobile open={mobileSidebar} /> : <Sidebar />}
|
||||
<Box
|
||||
sx={{
|
||||
background: theme.palette.background.default,
|
||||
width: "100%",
|
||||
padding: isMobile ? "16px 16px 140px 16px" : "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>
|
||||
{isTablet &&
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
width: "100%",
|
||||
padding: isMobile ? "20px 16px" : "20px 40px",
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
gap: "15px",
|
||||
background: "#FFF",
|
||||
}}
|
||||
>
|
||||
{[1, 2].includes(currentStep) && !openBranchingPanel && (
|
||||
<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>
|
||||
)}
|
||||
<a href={`/view`} target="_blank" rel="noreferrer" style={{ textDecoration: "none" }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
lineHeight: "18px",
|
||||
height: "34px",
|
||||
minWidth: "130px"
|
||||
}}
|
||||
>
|
||||
Опубликовать
|
||||
</Button>
|
||||
</a>
|
||||
|
||||
</Box>
|
||||
}
|
||||
|
||||
<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",
|
||||
}}
|
||||
/>
|
||||
</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>
|
||||
)}
|
||||
{disableTest ? (
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
lineHeight: "18px",
|
||||
height: "34px",
|
||||
minWidth: "130px",
|
||||
}}
|
||||
>
|
||||
Тестовый просмотр
|
||||
</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={() => {
|
||||
updateQuiz(
|
||||
quiz?.id, (state) => {
|
||||
state.status = quiz?.status === "start" ? "stop" : "start"
|
||||
}
|
||||
)
|
||||
}}
|
||||
>{quiz?.status === "start" ? "Стоп" : "Старт"}</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -51,139 +51,134 @@ export const Restore: FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Button sx={{ width: "200px", height: "200px", background: "red" }} onClick={() => setIsDialogOpen(true)}>
|
||||
open
|
||||
</Button>
|
||||
<Dialog
|
||||
open={isDialogOpen}
|
||||
onClose={handleClose}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
width: "600px",
|
||||
maxWidth: "600px",
|
||||
<Dialog
|
||||
open={isDialogOpen}
|
||||
onClose={handleClose}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
width: "600px",
|
||||
maxWidth: "600px",
|
||||
},
|
||||
}}
|
||||
slotProps={{
|
||||
backdrop: {
|
||||
style: {
|
||||
backgroundColor: "rgb(0 0 0 / 0.7)",
|
||||
},
|
||||
}}
|
||||
slotProps={{
|
||||
backdrop: {
|
||||
style: {
|
||||
backgroundColor: "rgb(0 0 0 / 0.7)",
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<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",
|
||||
boxShadow: "0px 15px 80px rgb(210 208 225 / 70%)",
|
||||
"& .MuiFormHelperText-root.Mui-error, & .MuiFormHelperText-root.Mui-error.MuiFormHelperText-filled": {
|
||||
position: "absolute",
|
||||
top: "46px",
|
||||
margin: "0",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
component="form"
|
||||
onSubmit={formik.handleSubmit}
|
||||
noValidate
|
||||
<IconButton
|
||||
onClick={handleClose}
|
||||
sx={{
|
||||
position: "relative",
|
||||
backgroundColor: "white",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
flexDirection: "column",
|
||||
p: upMd ? "50px" : "18px",
|
||||
pb: upMd ? "40px" : "30px",
|
||||
gap: "15px",
|
||||
borderRadius: "12px",
|
||||
boxShadow: "0px 15px 80px rgb(210 208 225 / 70%)",
|
||||
"& .MuiFormHelperText-root.Mui-error, & .MuiFormHelperText-root.Mui-error.MuiFormHelperText-filled": {
|
||||
position: "absolute",
|
||||
top: "46px",
|
||||
margin: "0",
|
||||
},
|
||||
position: "absolute",
|
||||
right: "7px",
|
||||
top: "7px",
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
onClick={handleClose}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
right: "7px",
|
||||
top: "7px",
|
||||
}}
|
||||
>
|
||||
<CloseIcon sx={{ transform: "scale(1.5)" }} />
|
||||
</IconButton>
|
||||
<Box sx={{ mt: upMd ? undefined : "62px" }}>
|
||||
<Logotip width={upMd ? 233 : 196} />
|
||||
</Box>
|
||||
<Typography
|
||||
sx={{
|
||||
color: "#4D4D4D",
|
||||
mt: "5px",
|
||||
mb: upMd ? "30px" : "33px",
|
||||
}}
|
||||
>
|
||||
Восстановление пароля
|
||||
</Typography>
|
||||
<InputTextfield
|
||||
TextfieldProps={{
|
||||
value: formik.values.email,
|
||||
placeholder: "username",
|
||||
onBlur: formik.handleBlur,
|
||||
error: formik.touched.email && Boolean(formik.errors.email),
|
||||
helperText: formik.touched.email && formik.errors.email,
|
||||
"data-cy": "username",
|
||||
}}
|
||||
onChange={formik.handleChange}
|
||||
color="#F2F3F7"
|
||||
id="email"
|
||||
label="Email"
|
||||
gap={upMd ? "10px" : "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,
|
||||
autoComplete: "new-password",
|
||||
"data-cy": "password",
|
||||
}}
|
||||
onChange={formik.handleChange}
|
||||
color="#F2F3F7"
|
||||
id="password"
|
||||
label="Пароль"
|
||||
gap={upMd ? "10px" : "10px"}
|
||||
/>
|
||||
<PasswordInput
|
||||
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",
|
||||
"data-cy": "repeat-password",
|
||||
}}
|
||||
onChange={formik.handleChange}
|
||||
color="#F2F3F7"
|
||||
id="repeatPassword"
|
||||
label="Повторить пароль"
|
||||
gap={upMd ? "10px" : "10px"}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
type="submit"
|
||||
disabled={formik.isSubmitting}
|
||||
sx={{
|
||||
py: "12px",
|
||||
"&:hover": {
|
||||
backgroundColor: "#581CA7",
|
||||
},
|
||||
"&:active": {
|
||||
color: "white",
|
||||
backgroundColor: "black",
|
||||
},
|
||||
}}
|
||||
data-cy="signup"
|
||||
>
|
||||
Восстановить
|
||||
</Button>
|
||||
<CloseIcon sx={{ transform: "scale(1.5)" }} />
|
||||
</IconButton>
|
||||
<Box sx={{ mt: upMd ? undefined : "62px" }}>
|
||||
<Logotip width={upMd ? 233 : 196} />
|
||||
</Box>
|
||||
</Dialog>
|
||||
</Box>
|
||||
<Typography
|
||||
sx={{
|
||||
color: "#4D4D4D",
|
||||
mt: "5px",
|
||||
mb: upMd ? "30px" : "33px",
|
||||
}}
|
||||
>
|
||||
Восстановление пароля
|
||||
</Typography>
|
||||
<InputTextfield
|
||||
TextfieldProps={{
|
||||
value: formik.values.email,
|
||||
placeholder: "username",
|
||||
onBlur: formik.handleBlur,
|
||||
error: formik.touched.email && Boolean(formik.errors.email),
|
||||
helperText: formik.touched.email && formik.errors.email,
|
||||
"data-cy": "username",
|
||||
}}
|
||||
onChange={formik.handleChange}
|
||||
color="#F2F3F7"
|
||||
id="email"
|
||||
label="Email"
|
||||
gap={upMd ? "10px" : "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,
|
||||
autoComplete: "new-password",
|
||||
"data-cy": "password",
|
||||
}}
|
||||
onChange={formik.handleChange}
|
||||
color="#F2F3F7"
|
||||
id="password"
|
||||
label="Пароль"
|
||||
gap={upMd ? "10px" : "10px"}
|
||||
/>
|
||||
<PasswordInput
|
||||
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",
|
||||
"data-cy": "repeat-password",
|
||||
}}
|
||||
onChange={formik.handleChange}
|
||||
color="#F2F3F7"
|
||||
id="repeatPassword"
|
||||
label="Повторить пароль"
|
||||
gap={upMd ? "10px" : "10px"}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
type="submit"
|
||||
disabled={formik.isSubmitting}
|
||||
sx={{
|
||||
py: "12px",
|
||||
"&:hover": {
|
||||
backgroundColor: "#581CA7",
|
||||
},
|
||||
"&:active": {
|
||||
color: "white",
|
||||
backgroundColor: "black",
|
||||
},
|
||||
}}
|
||||
data-cy="signup"
|
||||
>
|
||||
Восстановить
|
||||
</Button>
|
||||
</Box>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
@ -92,16 +92,6 @@ export default function Header() {
|
||||
gap: "15px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
lineHeight: "18px",
|
||||
height: "34px",
|
||||
}}
|
||||
>
|
||||
Опубликовать
|
||||
</Button>
|
||||
<CustomAvatar
|
||||
sx={{ ml: "11px", backgroundColor: theme.palette.orange.main, height: "36px", width: "36px" }}
|
||||
/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Box, Container, IconButton, Typography, useTheme, useMediaQuery } from "@mui/material";
|
||||
import NavMenuItem from "./NavMenuItem";
|
||||
import PenaLogo from "../PenaLogo";
|
||||
import Logotip from "../../pages/Landing/images/icons/QuizLogo";
|
||||
import WalletIcon from "@icons/WalletIcon";
|
||||
import CustomAvatar from "./Avatar";
|
||||
import { Burger } from "@icons/Burger";
|
||||
@ -53,7 +53,7 @@ export default function HeaderFull() {
|
||||
/>
|
||||
)}
|
||||
<Link to="/">
|
||||
<PenaLogo width={124} />
|
||||
<Logotip width={124} />
|
||||
</Link>
|
||||
{!isTablet && (
|
||||
<Box
|
||||
|
@ -5,11 +5,12 @@ interface Props {
|
||||
icon: any;
|
||||
text: string;
|
||||
isActive?: boolean;
|
||||
disabled?: boolean;
|
||||
isCollapsed: boolean;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export default function MenuItem({ icon, text, isActive = false, isCollapsed, onClick }: Props) {
|
||||
export default function MenuItem({ icon, text, isActive = false, isCollapsed, onClick, disabled = false }: Props) {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
@ -22,6 +23,7 @@ export default function MenuItem({ icon, text, isActive = false, isCollapsed, on
|
||||
>
|
||||
<ListItemButton
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
sx={{
|
||||
py: "4px",
|
||||
gap: "14px",
|
||||
|
@ -40,8 +40,8 @@ const styleSlider: SxProps<Theme> = {
|
||||
"&:focus, &:hover, &.Mui-active, &.Mui-focusVisible": {
|
||||
boxShadow: `0px 0px 0px 3px white,
|
||||
0px 4px 4px 3px #C3C8DD`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
interface Props {
|
||||
@ -249,20 +249,9 @@ export const CropModal: FC<Props> = ({ isOpen, imageBlob, originalImageUrl, setC
|
||||
marginTop: "40px",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
}}>
|
||||
<Button
|
||||
onClick={handleSaveClick}
|
||||
disableRipple
|
||||
data-cy="crop-modal-save-button"
|
||||
sx={{
|
||||
height: "48px",
|
||||
color: "#7E2AEA",
|
||||
borderRadius: "8px",
|
||||
border: "1px solid #7E2AEA",
|
||||
marginRight: "10px",
|
||||
px: "20px",
|
||||
}}
|
||||
>Сохранить</Button>
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
onClick={handleLoadOriginalImage}
|
||||
disableRipple
|
||||
@ -273,8 +262,6 @@ export const CropModal: FC<Props> = ({ isOpen, imageBlob, originalImageUrl, setC
|
||||
color: "#7E2AEA",
|
||||
borderRadius: "8px",
|
||||
border: "1px solid #7E2AEA",
|
||||
marginRight: "10px",
|
||||
ml: "auto",
|
||||
}}
|
||||
>
|
||||
Загрузить оригинал
|
||||
@ -282,18 +269,38 @@ export const CropModal: FC<Props> = ({ isOpen, imageBlob, originalImageUrl, setC
|
||||
<Button
|
||||
onClick={handleCropClick}
|
||||
disableRipple
|
||||
variant="contained"
|
||||
disabled={!completedCrop?.width || !completedCrop?.height}
|
||||
disabled={!completedCrop}
|
||||
sx={{
|
||||
padding: "10px 20px",
|
||||
borderRadius: "8px",
|
||||
background: theme.palette.brightPurple.main,
|
||||
fontSize: "18px",
|
||||
color: "#7E2AEA",
|
||||
border: `1px solid ${!completedCrop ? "rgba(0, 0, 0, 0.26)" : "#7E2AEA"}`,
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
>
|
||||
<CropIcon />
|
||||
<CropIcon color={!completedCrop ? "rgba(0, 0, 0, 0.26)" : "#7E2AEA"} />
|
||||
Обрезать
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={handleSaveClick}
|
||||
disableRipple
|
||||
variant="contained"
|
||||
data-cy="crop-modal-save-button"
|
||||
sx={{
|
||||
height: "48px",
|
||||
borderRadius: "8px",
|
||||
border: "1px solid #7E2AEA",
|
||||
marginRight: "10px",
|
||||
px: "20px",
|
||||
ml: "auto",
|
||||
}}
|
||||
>
|
||||
Сохранить
|
||||
</Button>
|
||||
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
|
@ -15,6 +15,7 @@ import { setCurrentStep } from "@root/quizes/actions";
|
||||
import { useQuizStore } from "@root/quizes/store";
|
||||
import { useState } from "react";
|
||||
import MenuItem from "./MenuItem";
|
||||
import {useCurrentQuiz} from "@root/quizes/hooks";
|
||||
|
||||
|
||||
const quizSettingsMenuItems = [
|
||||
@ -28,6 +29,8 @@ export default function Sidebar() {
|
||||
const theme = useTheme();
|
||||
const [isMenuCollapsed, setIsMenuCollapsed] = useState(false);
|
||||
const currentStep = useQuizStore(state => state.currentStep);
|
||||
const quiz = useCurrentQuiz();
|
||||
|
||||
|
||||
const handleMenuCollapseToggle = () => setIsMenuCollapsed((prev) => !prev);
|
||||
|
||||
@ -94,6 +97,7 @@ export default function Sidebar() {
|
||||
text={menuItem.sidebarText}
|
||||
isCollapsed={isMenuCollapsed}
|
||||
isActive={currentStep === index}
|
||||
disabled={index===0 ? false : quiz===undefined ? true : (quiz?.config.type === null)}
|
||||
icon={
|
||||
<Icon
|
||||
color={
|
||||
|
Loading…
Reference in New Issue
Block a user