Merge branch 'dev' into 'main'

поменял лого , обновил навигацию стрелок , обновил модалки (добавил ссылку на...

See merge request frontend/squiz!78
This commit is contained in:
Nastya 2023-12-17 23:30:08 +00:00
commit 2fcd6df97b
21 changed files with 1359 additions and 1084 deletions

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": "",
};

@ -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 <Box
sx={{ sx={{
position: "absolute", position: "absolute",
overflow: "hidden", overflow: "auto",
top: "50%", top: "50%",
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
@ -44,6 +44,7 @@ export const BranchingQuestionsModal = ({
borderRadius: "12px", borderRadius: "12px",
boxShadow: 24, boxShadow: 24,
padding: "30px 0", padding: "30px 0",
height: "80vh"
}} }}
> >
<Box sx={{ margin: "0 auto", maxWidth: "350px" }}> <Box sx={{ margin: "0 auto", maxWidth: "350px" }}>

@ -232,6 +232,7 @@ export default function ButtonsOptions({
// myFunc(question); // myFunc(question);
}} }}
sx={{ sx={{
display: quiz.config.type === "form" ? "none" : "flex",
backgroundColor: backgroundColor:
switchState === value switchState === value
? theme.palette.brightPurple.main ? theme.palette.brightPurple.main

@ -259,6 +259,7 @@ export default function ButtonsOptionsAndPict({
updateDesireToOpenABranchingModal(question.content.id); updateDesireToOpenABranchingModal(question.content.id);
}} }}
sx={{ sx={{
display: quiz.config.type === "form" ? "none" : "flex",
height: "30px", height: "30px",
maxWidth: "103px", maxWidth: "103px",
minWidth: isIconMobile ? "30px" : "64px", minWidth: isIconMobile ? "30px" : "64px",

@ -70,7 +70,7 @@ export default function QuestionsPage() {
sx={{ sx={{
position: "fixed", position: "fixed",
left: isMobile ? "20px" : "250px", left: isMobile ? "20px" : "250px",
bottom: isMobile ? "140px" : "20px", bottom: "140px",
}} }}
data-cy="create-question" data-cy="create-question"
> >

@ -1,12 +1,13 @@
import { Box, Typography } from "@mui/material"; import { Box, Typography } from "@mui/material";
export const ApologyPage = (message: string) => { export const ApologyPage = ({message}:{message: string}) => {
return ( return (
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "center" justifyContent: "center",
height: "100vh"
}} }}
> >
<Typography <Typography

@ -1,16 +1,14 @@
import { useState, useEffect } from "react"; 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 { useQuizViewStore } from "@root/quizView";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { useQuestionsStore } from "@root/questions/store"; import { useQuestionsStore } from "@root/questions/store";
import type { import type { AnyTypedQuizQuestion, QuizQuestionBase } from "../../model/questionTypes/shared";
AnyTypedQuizQuestion,
QuizQuestionBase,
} from "../../model/questionTypes/shared";
import { getQuestionByContentId } from "@root/questions/actions"; import { getQuestionByContentId } from "@root/questions/actions";
import { enqueueSnackbar } from "notistack"; import { enqueueSnackbar } from "notistack";
import { NameplateLogo } from "@icons/NameplateLogo";
type FooterProps = { type FooterProps = {
setCurrentQuestion: (step: AnyTypedQuizQuestion) => void; setCurrentQuestion: (step: AnyTypedQuizQuestion) => void;
@ -19,22 +17,14 @@ type FooterProps = {
setShowResultForm: (show: boolean) => void; setShowResultForm: (show: boolean) => void;
}; };
export const Footer = ({ export const Footer = ({ setCurrentQuestion, question, setShowContactForm, setShowResultForm }: FooterProps) => {
setCurrentQuestion, const [disablePreviousButton, setDisablePreviousButton] = useState<boolean>(false);
question,
setShowContactForm,
setShowResultForm,
}: FooterProps) => {
const [disablePreviousButton, setDisablePreviousButton] =
useState<boolean>(false);
const [disableNextButton, setDisableNextButton] = useState<boolean>(false); const [disableNextButton, setDisableNextButton] = useState<boolean>(false);
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const questions = useQuestionsStore().questions as AnyTypedQuizQuestion[]; const questions = useQuestionsStore().questions as AnyTypedQuizQuestion[];
const theme = useTheme(); const theme = useTheme();
const linear = !questions.find( const linear = !questions.find(({ content }) => content.rule.parentId === "root");
({ content }) => content.rule.parentId === "root"
);
useEffect(() => { useEffect(() => {
// Логика для аргумента disabled у кнопки "Назад" // Логика для аргумента disabled у кнопки "Назад"
@ -57,9 +47,7 @@ export const Footer = ({
} }
// Логика для аргумента disabled у кнопки "Далее" // Логика для аргумента disabled у кнопки "Далее"
const answer = answers.find( const answer = answers.find(({ questionId }) => questionId === question.content.id);
({ questionId }) => questionId === question.content.id
);
if ("required" in question.content && question.content.required && answer) { if ("required" in question.content && question.content.required && answer) {
setDisableNextButton(false); setDisableNextButton(false);
@ -67,11 +55,7 @@ export const Footer = ({
return; return;
} }
if ( if ("required" in question.content && question.content.required && !answer) {
"required" in question.content &&
question.content.required &&
!answer
) {
setDisableNextButton(true); setDisableNextButton(true);
return; return;
@ -85,9 +69,7 @@ export const Footer = ({
if (nextQuestionId) { if (nextQuestionId) {
setDisableNextButton(false); setDisableNextButton(false);
} else { } else {
const nextQuestion = getQuestionByContentId( const nextQuestion = getQuestionByContentId(question.content.rule.default);
question.content.rule.default
);
if (nextQuestion?.type) { if (nextQuestion?.type) {
setDisableNextButton(false); setDisableNextButton(false);
@ -95,9 +77,8 @@ export const Footer = ({
} }
}, [question, answers]); }, [question, answers]);
const showResult = nextQuestion => { const showResult = (nextQuestion) => {
console.log(nextQuestion);
console.log(nextQuestion)
if (nextQuestion && quiz?.config.resultInfo.when === "before") { if (nextQuestion && quiz?.config.resultInfo.when === "before") {
setShowResultForm(true); setShowResultForm(true);
@ -108,19 +89,14 @@ export const Footer = ({
const getNextQuestionId = () => { const getNextQuestionId = () => {
if (answers.length) { if (answers.length) {
const answer = answers.find( const answer = answers.find(({ questionId }) => questionId === question.content.id);
({ questionId }) => questionId === question.content.id
);
let readyBeNextQuestion = ""; let readyBeNextQuestion = "";
(question as QuizQuestionBase).content.rule.main.forEach( (question as QuizQuestionBase).content.rule.main.forEach(({ next, rules }) => {
({ next, rules }) => {
let longerArray = Math.max( let longerArray = Math.max(
rules[0].answers.length, rules[0].answers.length,
answer?.answer && Array.isArray(answer?.answer) answer?.answer && Array.isArray(answer?.answer) ? answer?.answer.length : [answer?.answer].length
? answer?.answer.length
: [answer?.answer].length
); );
for ( for (
@ -129,11 +105,7 @@ export const Footer = ({
i++ // Цикл по всем эле­мен­там бОльшего массива i++ // Цикл по всем эле­мен­там бОльшего массива
) { ) {
if (Array.isArray(answer?.answer)) { if (Array.isArray(answer?.answer)) {
if ( if (answer?.answer.find((item) => String(item === rules[0].answers[i]))) {
answer?.answer.find((item) =>
String(item === rules[0].answers[i])
)
) {
readyBeNextQuestion = next; // Ес­ли хоть один эле­мент от­ли­ча­ет­ся, мас­си­вы не рав­ны readyBeNextQuestion = next; // Ес­ли хоть один эле­мент от­ли­ча­ет­ся, мас­си­вы не рав­ны
} }
@ -144,8 +116,7 @@ export const Footer = ({
readyBeNextQuestion = next; // Ес­ли хоть один эле­мент от­ли­ча­ет­ся, мас­си­вы не рав­ны readyBeNextQuestion = next; // Ес­ли хоть один эле­мент от­ли­ча­ет­ся, мас­си­вы не рав­ны
} }
} }
} });
);
return readyBeNextQuestion; return readyBeNextQuestion;
} }
@ -181,12 +152,14 @@ export const Footer = ({
const questionIndex = questions.findIndex(({ id }) => id === question.id); const questionIndex = questions.findIndex(({ id }) => id === question.id);
const nextQuestion = questions[questionIndex + 1]; const nextQuestion = questions[questionIndex + 1];
console.log(nextQuestion) console.log("questionIndex ", questionIndex);
console.log(nextQuestion);
console.log(questions);
if (nextQuestion && nextQuestion.type !== "result") { if (nextQuestion && nextQuestion.type !== "result") {
console.log("следующий вопрос результирующий ", (nextQuestion.type === "result")) console.log("следующий вопрос результирующий ", nextQuestion.type === "result");
setCurrentQuestion(nextQuestion); setCurrentQuestion(nextQuestion);
} else { } else {
console.log("следующий вопрос результирующий ", (nextQuestion.type === "result")) console.log("следующий вопрос результирующий ", nextQuestion.type === "result");
showResult(nextQuestion); showResult(nextQuestion);
} }
@ -205,9 +178,7 @@ export const Footer = ({
enqueueSnackbar("не могу получить последующий вопрос"); enqueueSnackbar("не могу получить последующий вопрос");
} }
} else { } else {
const nextQuestion = getQuestionByContentId( const nextQuestion = getQuestionByContentId(question.content.rule.default);
question.content.rule.default
);
if (nextQuestion?.type && nextQuestion.type !== "result") { if (nextQuestion?.type && nextQuestion.type !== "result") {
setCurrentQuestion(nextQuestion); setCurrentQuestion(nextQuestion);
} else { } else {
@ -219,10 +190,25 @@ export const Footer = ({
return ( return (
<Box <Box
sx={{ sx={{
position: "relative",
padding: "15px 0", padding: "15px 0",
borderTop: `1px solid ${theme.palette.grey[400]}`, 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 <Box
sx={{ sx={{
width: "100%", width: "100%",

@ -198,9 +198,14 @@ export default function SigninDialog() {
}} }}
> >
<Typography sx={{ color: "#7E2AEA", textAlign: "center" }}>Вы еще не присоединились?</Typography> <Typography sx={{ color: "#7E2AEA", textAlign: "center" }}>Вы еще не присоединились?</Typography>
<Box sx={{ display: "flex", alignItems: "center", gap: "4px" }}>
<Link component={RouterLink} to="/signup" sx={{ color: "#7E2AEA" }}> <Link component={RouterLink} to="/signup" sx={{ color: "#7E2AEA" }}>
Регистрация Регистрация
</Link> </Link>
<Link component={RouterLink} to="/restore" sx={{ color: "#7E2AEA" }}>
Забыли пароль
</Link>
</Box>
</Box> </Box>
</Box> </Box>
</Dialog> </Dialog>

@ -200,6 +200,7 @@ export default function SignupDialog() {
> >
Зарегистрироваться Зарегистрироваться
</Button> </Button>
<Link <Link
component={RouterLink} component={RouterLink}
to="/signin" to="/signin"
@ -211,6 +212,9 @@ export default function SignupDialog() {
> >
Вход в личный кабинет Вход в личный кабинет
</Link> </Link>
<Link component={RouterLink} to="/restore" sx={{ color: "#7E2AEA" }}>
Забыли пароль
</Link>
</Box> </Box>
</Dialog> </Dialog>
); );

@ -3,6 +3,7 @@ import SectionWrapper from "@ui_kit/SectionWrapper";
import ComplexNavText from "./ComplexNavText"; import ComplexNavText from "./ComplexNavText";
import { createQuiz } from "@root/quizes/actions"; import { createQuiz } from "@root/quizes/actions";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { resetEditConfig } from "@root/quizes/actions";
export default function FirstQuiz() { export default function FirstQuiz() {
@ -29,7 +30,10 @@ export default function FirstQuiz() {
<Button <Button
variant="contained" variant="contained"
data-cy="create-quiz" data-cy="create-quiz"
onClick={() => createQuiz(navigate)} onClick={() => {
resetEditConfig()
createQuiz(navigate)
}}
> >
Создать + Создать +
</Button> </Button>

@ -4,6 +4,7 @@ import { useQuizes } from "@root/quizes/hooks";
import SectionWrapper from "@ui_kit/SectionWrapper"; import SectionWrapper from "@ui_kit/SectionWrapper";
import React from "react"; import React from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { resetEditConfig } from "@root/quizes/actions";
import ComplexNavText from "./ComplexNavText"; import ComplexNavText from "./ComplexNavText";
import FirstQuiz from "./FirstQuiz"; import FirstQuiz from "./FirstQuiz";
import QuizCard from "./QuizCard"; import QuizCard from "./QuizCard";
@ -42,7 +43,10 @@ export default function MyQuizzesFull({ outerContainerSx: sx, children }: Props)
padding: isMobile ? "10px" : "10px 47px", padding: isMobile ? "10px" : "10px 47px",
minWidth: "44px", minWidth: "44px",
}} }}
onClick={() => createQuiz(navigate)} onClick={() => {
resetEditConfig();
createQuiz(navigate)
}}
data-cy="create-quiz" data-cy="create-quiz"
> >
{isMobile ? "+" : "Создать +"} {isMobile ? "+" : "Создать +"}

@ -4,20 +4,10 @@ import LinkIcon from "@icons/LinkIcon";
import PencilIcon from "@icons/PencilIcon"; import PencilIcon from "@icons/PencilIcon";
import { Quiz } from "@model/quiz/quiz"; import { Quiz } from "@model/quiz/quiz";
import MoreHorizIcon from "@mui/icons-material/MoreHoriz"; import MoreHorizIcon from "@mui/icons-material/MoreHoriz";
import { import { Box, Button, IconButton, Typography, useMediaQuery, useTheme, Popover } from "@mui/material";
Box,
Button,
IconButton,
Typography,
useMediaQuery,
useTheme,
Popover,
} from "@mui/material";
import { deleteQuiz, setEditQuizId } from "@root/quizes/actions"; import { deleteQuiz, setEditQuizId } from "@root/quizes/actions";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
interface Props { interface Props {
quiz: Quiz; quiz: Quiz;
openCount?: number; openCount?: number;
@ -25,12 +15,7 @@ interface Props {
conversionPercent?: number; conversionPercent?: number;
} }
export default function QuizCard({ export default function QuizCard({ quiz, openCount = 0, applicationCount = 0, conversionPercent = 0 }: Props) {
quiz,
openCount = 0,
applicationCount = 0,
conversionPercent = 0,
}: Props) {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600)); const isMobile = useMediaQuery(theme.breakpoints.down(600));
const navigate = useNavigate(); const navigate = useNavigate();
@ -71,9 +56,7 @@ export default function QuizCard({
}} }}
> >
<LinkIcon bgcolor="#EEE4FC" color={theme.palette.brightPurple.main} /> <LinkIcon bgcolor="#EEE4FC" color={theme.palette.brightPurple.main} />
<Typography color={theme.palette.grey3.main}> <Typography color={theme.palette.grey3.main}>быстрая ссылка ...</Typography>
быстрая ссылка ...
</Typography>
</Box> </Box>
<Box <Box
sx={{ sx={{

@ -9,12 +9,14 @@ import {
Button, Button,
Container, Container,
FormControl, FormControl,
IconButton, Switch, IconButton,
TextField, Typography, Switch,
TextField,
Typography,
useMediaQuery, useMediaQuery,
useTheme, useTheme,
} from "@mui/material"; } 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 { useCurrentQuiz } from "@root/quizes/hooks";
import { useQuizStore } from "@root/quizes/store"; import { useQuizStore } from "@root/quizes/store";
import CustomAvatar from "@ui_kit/Header/Avatar"; import CustomAvatar from "@ui_kit/Header/Avatar";
@ -25,7 +27,7 @@ import Stepper from "@ui_kit/Stepper";
import SwitchStepPages from "@ui_kit/switchStepPages"; import SwitchStepPages from "@ui_kit/switchStepPages";
import { isAxiosError } from "axios"; import { isAxiosError } from "axios";
import { enqueueSnackbar } from "notistack"; import { enqueueSnackbar } from "notistack";
import { useEffect, useState } from "react"; import React, { useEffect, useLayoutEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import useSWR from "swr"; import useSWR from "swr";
import { SidebarMobile } from "./Sidebar/SidebarMobile"; import { SidebarMobile } from "./Sidebar/SidebarMobile";
@ -37,8 +39,7 @@ import { useQuizes } from "@root/quizes/hooks";
import { questionApi } from "@api/question"; import { questionApi } from "@api/question";
import { useUiTools } from "@root/uiTools/store"; import { useUiTools } from "@root/uiTools/store";
import Logotip from "../Landing/images/icons/QuizLogo";
export default function EditPage() { export default function EditPage() {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
@ -46,34 +47,37 @@ export default function EditPage() {
useEffect(() => { useEffect(() => {
const getData = async () => { const getData = async () => {
const quizes = await quizApi.getList() const quizes = await quizApi.getList();
setQuizes(quizes) setQuizes(quizes);
const questions = await questionApi.getList({ quiz_id: editQuizId }) const questions = await questionApi.getList({ quiz_id: editQuizId });
setQuestions(questions) setQuestions(questions);
};
getData();
}, []);
} const { openBranchingPanel } = useUiTools();
getData()
}, [])
const { openBranchingPanel } = useUiTools()
const theme = useTheme(); const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
const currentStep = useQuizStore(state => state.currentStep); const currentStep = useQuizStore((state) => state.currentStep);
const isTablet = useMediaQuery(theme.breakpoints.down(1000)); const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const isMobile = useMediaQuery(theme.breakpoints.down(660)); const isMobile = useMediaQuery(theme.breakpoints.down(660));
const [mobileSidebar, setMobileSidebar] = useState<boolean>(false); const [mobileSidebar, setMobileSidebar] = useState<boolean>(false);
const quizConfig = quiz?.config; const quizConfig = quiz?.config;
const disableTest = quiz === undefined ? true : (quiz.config.type === null)
useEffect(() => { useEffect(() => {
if (editQuizId === null) navigate("/list"); if (editQuizId === null) navigate("/list");
}, [navigate, editQuizId]); }, [navigate, editQuizId]);
useEffect(() => () => { useEffect(
() => () => {
resetEditConfig(); resetEditConfig();
cleanQuestions(); cleanQuestions();
}, []); },
[]
);
console.log(currentStep)
return ( return (
<> <>
@ -93,11 +97,7 @@ export default function EditPage() {
}} }}
> >
<Link to="/" style={{ display: "flex" }}> <Link to="/" style={{ display: "flex" }}>
{isMobile ? ( {isMobile ? <PenaLogoIcon style={{ fontSize: "39px", color: "white" }} /> : <PenaLogo width={124} />}
<PenaLogoIcon style={{ fontSize: "39px", color: "white" }} />
) : (
<PenaLogo width={124} />
)}
</Link> </Link>
<Box <Box
sx={{ sx={{
@ -106,9 +106,11 @@ export default function EditPage() {
ml: "37px", ml: "37px",
}} }}
> >
<IconButton sx={{ p: "6px" }} onClick={decrementCurrentStep}> <Link to="/list">
<IconButton sx={{ p: "6px" }}>
<BackArrowIcon /> <BackArrowIcon />
</IconButton> </IconButton>
</Link>
<FormControl fullWidth variant="standard"> <FormControl fullWidth variant="standard">
<TextField <TextField
fullWidth fullWidth
@ -184,18 +186,6 @@ export default function EditPage() {
gap: "15px", 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 <CustomAvatar
sx={{ sx={{
ml: "11px", ml: "11px",
@ -219,14 +209,14 @@ export default function EditPage() {
sx={{ sx={{
background: theme.palette.background.default, background: theme.palette.background.default,
width: "100%", width: "100%",
padding: isMobile ? "16px 16px 140px 16px" : "25px", padding: isMobile ? "16px 16px 140px 16px" : "25px 25px 140px 25px",
height: "calc(100vh - 80px)", height: "calc(100vh - 80px)",
overflow: "auto", overflow: "auto",
boxSizing: "border-box", boxSizing: "border-box",
}} }}
> >
{/* Выбор текущей страницы редактирования чего-либо находится здесь */} {/* Выбор текущей страницы редактирования чего-либо находится здесь */}
{quizConfig && {quizConfig && (
<> <>
<Stepper activeStep={currentStep} /> <Stepper activeStep={currentStep} />
<SwitchStepPages <SwitchStepPages
@ -236,23 +226,23 @@ export default function EditPage() {
quizStartPageType={quizConfig.startpageType} quizStartPageType={quizConfig.startpageType}
/> />
</> </>
} )}
</Box> </Box>
{isTablet &&
<Box <Box
sx={{ sx={{
position: "absolute", position: "absolute",
left: 0, left: 0,
bottom: 0, bottom: 0,
width: "100%", width: "100%",
padding: isMobile ? "20px 16px" : "20px 40px", padding: isMobile ? "20px 16px" : "20px 40px 20px 250px",
display: "flex", display: "flex",
justifyContent: "flex-end", justifyContent: "flex-start",
alignItems: "center",
gap: "15px", gap: "15px",
background: "#FFF", background: "#FFF",
}} }}
> >
{[1, 2].includes(currentStep) && !openBranchingPanel && ( {[1].includes(currentStep) && !openBranchingPanel && quizConfig.type !== "form" && (
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -266,9 +256,7 @@ export default function EditPage() {
> >
<Switch <Switch
checked={openBranchingPanel} checked={openBranchingPanel}
onChange={ onChange={(e) => updateOpenBranchingPanel(e.target.checked)}
(e) => updateOpenBranchingPanel(e.target.checked)
}
sx={{ sx={{
width: 50, width: 50,
height: 30, height: 30,
@ -288,10 +276,7 @@ export default function EditPage() {
"&.Mui-disabled + .MuiSwitch-track": { opacity: 0.5 }, "&.Mui-disabled + .MuiSwitch-track": { opacity: 0.5 },
}, },
"&.Mui-disabled .MuiSwitch-thumb": { "&.Mui-disabled .MuiSwitch-thumb": {
color: color: theme.palette.mode === "light" ? theme.palette.grey[100] : theme.palette.grey[600],
theme.palette.mode === "light"
? theme.palette.grey[100]
: theme.palette.grey[600],
}, },
"&.Mui-disabled + .MuiSwitch-track": { "&.Mui-disabled + .MuiSwitch-track": {
opacity: theme.palette.mode === "light" ? 0.7 : 0.3, opacity: theme.palette.mode === "light" ? 0.7 : 0.3,
@ -304,8 +289,7 @@ export default function EditPage() {
}, },
"& .MuiSwitch-track": { "& .MuiSwitch-track": {
borderRadius: 13, borderRadius: 13,
backgroundColor: backgroundColor: theme.palette.mode === "light" ? "#E9E9EA" : "#39393D",
theme.palette.mode === "light" ? "#E9E9EA" : "#39393D",
opacity: 1, opacity: 1,
transition: theme.transitions.create(["background-color"], { transition: theme.transitions.create(["background-color"], {
duration: 500, duration: 500,
@ -314,12 +298,24 @@ export default function EditPage() {
}} }}
/> />
<Box> <Box>
<Typography sx={{ fontWeight: "bold", color: "#4D4D4D" }}> <Typography sx={{ fontWeight: "bold", color: "#4D4D4D" }}>Логика ветвления</Typography>
Логика ветвления
</Typography>
</Box> </Box>
</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" }}> <a href={`/view`} target="_blank" rel="noreferrer" style={{ textDecoration: "none" }}>
<Button <Button
variant="contained" variant="contained"
@ -327,16 +323,33 @@ export default function EditPage() {
fontSize: "14px", fontSize: "14px",
lineHeight: "18px", lineHeight: "18px",
height: "34px", height: "34px",
minWidth: "130px" minWidth: "130px",
}} }}
> >
Опубликовать Тестовый просмотр
</Button> </Button>
</a> </a>
)}
</Box> <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> </Box>
</> </>
); );

@ -51,10 +51,6 @@ export const Restore: FC = () => {
} }
return ( return (
<Box>
<Button sx={{ width: "200px", height: "200px", background: "red" }} onClick={() => setIsDialogOpen(true)}>
open
</Button>
<Dialog <Dialog
open={isDialogOpen} open={isDialogOpen}
onClose={handleClose} onClose={handleClose}
@ -184,6 +180,5 @@ export const Restore: FC = () => {
</Button> </Button>
</Box> </Box>
</Dialog> </Dialog>
</Box>
); );
}; };

@ -92,16 +92,6 @@ export default function Header() {
gap: "15px", gap: "15px",
}} }}
> >
<Button
variant="contained"
sx={{
fontSize: "14px",
lineHeight: "18px",
height: "34px",
}}
>
Опубликовать
</Button>
<CustomAvatar <CustomAvatar
sx={{ ml: "11px", backgroundColor: theme.palette.orange.main, height: "36px", width: "36px" }} 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 { Box, Container, IconButton, Typography, useTheme, useMediaQuery } from "@mui/material";
import NavMenuItem from "./NavMenuItem"; import NavMenuItem from "./NavMenuItem";
import PenaLogo from "../PenaLogo"; import Logotip from "../../pages/Landing/images/icons/QuizLogo";
import WalletIcon from "@icons/WalletIcon"; import WalletIcon from "@icons/WalletIcon";
import CustomAvatar from "./Avatar"; import CustomAvatar from "./Avatar";
import { Burger } from "@icons/Burger"; import { Burger } from "@icons/Burger";
@ -53,7 +53,7 @@ export default function HeaderFull() {
/> />
)} )}
<Link to="/"> <Link to="/">
<PenaLogo width={124} /> <Logotip width={124} />
</Link> </Link>
{!isTablet && ( {!isTablet && (
<Box <Box

@ -5,11 +5,12 @@ interface Props {
icon: any; icon: any;
text: string; text: string;
isActive?: boolean; isActive?: boolean;
disabled?: boolean;
isCollapsed: boolean; isCollapsed: boolean;
onClick: () => void; 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(); const theme = useTheme();
return ( return (
@ -22,6 +23,7 @@ export default function MenuItem({ icon, text, isActive = false, isCollapsed, on
> >
<ListItemButton <ListItemButton
onClick={onClick} onClick={onClick}
disabled={disabled}
sx={{ sx={{
py: "4px", py: "4px",
gap: "14px", gap: "14px",

@ -249,20 +249,9 @@ export const CropModal: FC<Props> = ({ isOpen, imageBlob, originalImageUrl, setC
marginTop: "40px", marginTop: "40px",
width: "100%", width: "100%",
display: "flex", display: "flex",
}}> gap: "10px",
<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> >
<Button <Button
onClick={handleLoadOriginalImage} onClick={handleLoadOriginalImage}
disableRipple disableRipple
@ -273,8 +262,6 @@ export const CropModal: FC<Props> = ({ isOpen, imageBlob, originalImageUrl, setC
color: "#7E2AEA", color: "#7E2AEA",
borderRadius: "8px", borderRadius: "8px",
border: "1px solid #7E2AEA", border: "1px solid #7E2AEA",
marginRight: "10px",
ml: "auto",
}} }}
> >
Загрузить оригинал Загрузить оригинал
@ -282,18 +269,38 @@ export const CropModal: FC<Props> = ({ isOpen, imageBlob, originalImageUrl, setC
<Button <Button
onClick={handleCropClick} onClick={handleCropClick}
disableRipple disableRipple
variant="contained" disabled={!completedCrop}
disabled={!completedCrop?.width || !completedCrop?.height}
sx={{ sx={{
padding: "10px 20px", padding: "10px 20px",
borderRadius: "8px", borderRadius: "8px",
background: theme.palette.brightPurple.main, background: theme.palette.brightPurple.main,
fontSize: "18px", 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>
<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>
</Box> </Box>
</Modal> </Modal>

@ -15,6 +15,7 @@ import { setCurrentStep } from "@root/quizes/actions";
import { useQuizStore } from "@root/quizes/store"; import { useQuizStore } from "@root/quizes/store";
import { useState } from "react"; import { useState } from "react";
import MenuItem from "./MenuItem"; import MenuItem from "./MenuItem";
import {useCurrentQuiz} from "@root/quizes/hooks";
const quizSettingsMenuItems = [ const quizSettingsMenuItems = [
@ -28,6 +29,8 @@ export default function Sidebar() {
const theme = useTheme(); const theme = useTheme();
const [isMenuCollapsed, setIsMenuCollapsed] = useState(false); const [isMenuCollapsed, setIsMenuCollapsed] = useState(false);
const currentStep = useQuizStore(state => state.currentStep); const currentStep = useQuizStore(state => state.currentStep);
const quiz = useCurrentQuiz();
const handleMenuCollapseToggle = () => setIsMenuCollapsed((prev) => !prev); const handleMenuCollapseToggle = () => setIsMenuCollapsed((prev) => !prev);
@ -94,6 +97,7 @@ export default function Sidebar() {
text={menuItem.sidebarText} text={menuItem.sidebarText}
isCollapsed={isMenuCollapsed} isCollapsed={isMenuCollapsed}
isActive={currentStep === index} isActive={currentStep === index}
disabled={index===0 ? false : quiz===undefined ? true : (quiz?.config.type === null)}
icon={ icon={
<Icon <Icon
color={ color={