diff --git a/src/model/questionTypes/shared.ts b/src/model/questionTypes/shared.ts
index fb1ed933..2d95ac3b 100644
--- a/src/model/questionTypes/shared.ts
+++ b/src/model/questionTypes/shared.ts
@@ -60,7 +60,6 @@ export interface QuizQuestionBase {
type?: QuestionType | null;
expanded: boolean;
openedModalSettings: boolean;
- required: boolean;
deleted: boolean;
deleteTimeoutId: number;
content: {
diff --git a/src/pages/Landing/Landing.tsx b/src/pages/Landing/Landing.tsx
index c4c94ed8..fc1ea03e 100644
--- a/src/pages/Landing/Landing.tsx
+++ b/src/pages/Landing/Landing.tsx
@@ -24,7 +24,7 @@ export default function Landing() {
-
+ {/* */}
diff --git a/src/pages/Questions/BranchingMap/CsComponent.tsx b/src/pages/Questions/BranchingMap/CsComponent.tsx
index 096939b8..2dd51e94 100644
--- a/src/pages/Questions/BranchingMap/CsComponent.tsx
+++ b/src/pages/Questions/BranchingMap/CsComponent.tsx
@@ -157,6 +157,12 @@ function CsComponent({
}, [modalQuestionTargetContentId])
const addNode = ({ parentNodeContentId, targetNodeContentId }: { parentNodeContentId: string, targetNodeContentId?: string }) => {
+
+
+ //запрещаем работу родителя-ребенка если это один и тот же вопрос
+ if (parentNodeContentId === targetNodeContentId) return
+
+
const cy = cyRef?.current
const parentNodeChildren = cy?.$('edge[source = "' + parentNodeContentId + '"]')?.length
//если есть инфо о выбранном вопросе из модалки - берём родителя из инфо модалки. Иначе из значения дропа
diff --git a/src/pages/Questions/DataOptions/settingData.tsx b/src/pages/Questions/DataOptions/settingData.tsx
index ebd53df8..59d9d20b 100644
--- a/src/pages/Questions/DataOptions/settingData.tsx
+++ b/src/pages/Questions/DataOptions/settingData.tsx
@@ -86,10 +86,10 @@ export default function SettingsData({ question }: SettingsDataProps) {
{
- updateQuestion(question.id, question => {
- question.required = !target.checked;
+ updateQuestion(question.id, question => {
+ question.content.required = !target.checked;
});
}}
/>
@@ -109,7 +109,7 @@ export default function SettingsData({ question }: SettingsDataProps) {
label={"Внутреннее название вопроса"}
checked={question.content.innerNameCheck}
handleChange={({ target }) => {
- updateQuestion(question.id, question => {
+ updateQuestion(question.id, question => {
question.content.innerNameCheck = target.checked;
question.content.innerName = target.checked ? question.content.innerName : "";
});
diff --git a/src/pages/Questions/DropDown/settingDropDown.tsx b/src/pages/Questions/DropDown/settingDropDown.tsx
index 895a27f1..1cffb25e 100644
--- a/src/pages/Questions/DropDown/settingDropDown.tsx
+++ b/src/pages/Questions/DropDown/settingDropDown.tsx
@@ -128,10 +128,10 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
{
- updateQuestion(question.id, question => {
- question.required = !e.target.checked;
+ updateQuestion(question.id, question => {
+ question.content.required = !e.target.checked;
});
}}
/>
@@ -141,7 +141,7 @@ export default function SettingDropDown({ question }: SettingDropDownProps) {
label={"Внутреннее название вопроса"}
checked={question.content.innerNameCheck}
handleChange={({ target }) => {
- updateQuestion(question.id, question => {
+ updateQuestion(question.id, question => {
question.content.innerNameCheck = target.checked;
question.content.innerName = target.checked ? question.content.innerName : "";
});
diff --git a/src/pages/Questions/Emoji/settingEmoji.tsx b/src/pages/Questions/Emoji/settingEmoji.tsx
index ec2753e9..ffc3cb22 100644
--- a/src/pages/Questions/Emoji/settingEmoji.tsx
+++ b/src/pages/Questions/Emoji/settingEmoji.tsx
@@ -85,11 +85,11 @@ export default function SettingEmoji({ question }: SettingEmojiProps) {
updateQuestion(question.id, question => {
+ checked={!question.content.required}
+ handleChange={({ target }) => updateQuestion(question.id, question => {
if (question.type !== "emoji") return;
- question.content.required = !e.target.checked;
+ question.content.required = !target.checked;
})}
/>
updateQuestion(question.id, question => {
+ handleChange={({ target }) => updateQuestion(question.id, question => {
question.content.innerNameCheck = target.checked;
question.content.innerName = target.checked ? question.content.innerName : "";
})}
diff --git a/src/pages/Questions/OptionsAndPicture/SettingOptionsAndPict.tsx b/src/pages/Questions/OptionsAndPicture/SettingOptionsAndPict.tsx
index 4f1bbe2b..76c4993d 100644
--- a/src/pages/Questions/OptionsAndPicture/SettingOptionsAndPict.tsx
+++ b/src/pages/Questions/OptionsAndPicture/SettingOptionsAndPict.tsx
@@ -111,11 +111,11 @@ export default function SettingOptionsAndPict({ question }: SettingOptionsAndPic
updateQuestion(question.id, question => {
+ checked={!question.content.required}
+ handleChange={({ target }) => updateQuestion(question.id, question => {
if (question.type !== "varimg") return;
- question.content.required = target.checked;
+ question.content.required = !target.checked;
})}
/>
@@ -126,7 +126,7 @@ export default function SettingOptionsAndPict({ question }: SettingOptionsAndPic
}}
label={"Внутреннее название вопроса"}
checked={question.content.innerNameCheck}
- handleChange={({ target }) => updateQuestion(question.id, question => {
+ handleChange={({ target }) => updateQuestion(question.id, question => {
question.content.innerNameCheck = target.checked;
question.content.innerName = "";
})}
diff --git a/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx b/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx
index f47b281b..40ae6b7d 100644
--- a/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx
+++ b/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx
@@ -211,11 +211,11 @@ export default function SettingOpytionsPict({ question }: SettingOpytionsPictPro
updateQuestion(question.id, question => {
+ checked={!question.content.required}
+ handleChange={({ target }) => updateQuestion(question.id, question => {
if (question.type !== "images") return;
- question.content.required = target.checked;
+ question.content.required = !target.checked;
})
}
/>
diff --git a/src/pages/Questions/OwnTextField/settingTextField.tsx b/src/pages/Questions/OwnTextField/settingTextField.tsx
index ad74ac37..4bc77e3c 100644
--- a/src/pages/Questions/OwnTextField/settingTextField.tsx
+++ b/src/pages/Questions/OwnTextField/settingTextField.tsx
@@ -169,10 +169,10 @@ export default function SettingTextField({
alignItems: isMobile ? "flex-end" : "center",
}}
label={"Необязательный вопрос"}
- checked={!question.required}
+ checked={!question.content.required}
handleChange={(e) => {
- updateQuestion(question.id, question => {
- question.required = !e.target.checked;
+ updateQuestion(question.id, question => {
+ question.content.required = !e.target.checked;
});
}}
/>
@@ -193,7 +193,7 @@ export default function SettingTextField({
label={"Внутреннее название вопроса"}
checked={question.content.innerNameCheck}
handleChange={({ target }) => {
- updateQuestion(question.id, question => {
+ updateQuestion(question.id, question => {
question.content.innerNameCheck = target.checked;
question.content.innerName = target.checked
? question.content.innerName
diff --git a/src/pages/Questions/RatingOptions/settingRating.tsx b/src/pages/Questions/RatingOptions/settingRating.tsx
index e42b0294..4c54921e 100644
--- a/src/pages/Questions/RatingOptions/settingRating.tsx
+++ b/src/pages/Questions/RatingOptions/settingRating.tsx
@@ -148,12 +148,12 @@ export default function SettingSlider({ question }: SettingSliderProps) {
{
- updateQuestion(question.id, question => {
+ updateQuestion(question.id, question => {
if (question.type !== "rating") return;
- question.required = !e.target.checked;
+ question.content.required = !e.target.checked;
});
}}
/>
diff --git a/src/pages/Questions/SliderOptions/settingSlider.tsx b/src/pages/Questions/SliderOptions/settingSlider.tsx
index c6aef2d1..4677c8fb 100644
--- a/src/pages/Questions/SliderOptions/settingSlider.tsx
+++ b/src/pages/Questions/SliderOptions/settingSlider.tsx
@@ -78,12 +78,12 @@ export default function SettingSlider({ question }: SettingSliderProps) {
{
- updateQuestion(question.id, question => {
+ updateQuestion(question.id, question => {
if (question.type !== "number") return;
- question.required = !e.target.checked;
+ question.content.required = !e.target.checked;
});
}}
/>
diff --git a/src/pages/Questions/UploadFile/settingUpload.tsx b/src/pages/Questions/UploadFile/settingUpload.tsx
index a7e4cdc2..8968ac4a 100644
--- a/src/pages/Questions/UploadFile/settingUpload.tsx
+++ b/src/pages/Questions/UploadFile/settingUpload.tsx
@@ -59,10 +59,10 @@ export default function SettingsUpload({ question }: SettingsUploadProps) {
mr: isMobile ? "0px" : "16px",
}}
label={"Необязательный вопрос"}
- checked={!question.required}
+ checked={!question.content.required}
handleChange={(e) => {
- updateQuestion(question.id, question => {
- question.required = !e.target.checked;
+ updateQuestion(question.id, question => {
+ question.content.required = !e.target.checked;
});
}}
/>
@@ -82,7 +82,7 @@ export default function SettingsUpload({ question }: SettingsUploadProps) {
label={"Внутреннее название вопроса"}
checked={question.content.innerNameCheck}
handleChange={({ target }) => {
- updateQuestion(question.id, question => {
+ updateQuestion(question.id, question => {
question.content.innerNameCheck = target.checked;
question.content.innerName = target.checked ? question.content.innerName : "";
});
diff --git a/src/pages/Questions/answerOptions/responseSettings.tsx b/src/pages/Questions/answerOptions/responseSettings.tsx
index 8ed5dd2e..8f4f50fe 100644
--- a/src/pages/Questions/answerOptions/responseSettings.tsx
+++ b/src/pages/Questions/answerOptions/responseSettings.tsx
@@ -1,9 +1,9 @@
import {
- Box,
- Tooltip,
- Typography,
- useMediaQuery,
- useTheme,
+ Box,
+ Tooltip,
+ Typography,
+ useMediaQuery,
+ useTheme,
} from "@mui/material";
import { setQuestionInnerName, updateQuestion } from "@root/questions/actions";
import CustomCheckbox from "@ui_kit/CustomCheckbox";
@@ -12,165 +12,166 @@ import { useDebouncedCallback } from "use-debounce";
import InfoIcon from "../../../assets/icons/InfoIcon";
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
-
interface Props {
- question: QuizQuestionVariant;
+ question: QuizQuestionVariant;
}
export default function ResponseSettings({ question }: Props) {
- const theme = useTheme();
- const isTablet = useMediaQuery(theme.breakpoints.down(900));
+ const theme = useTheme();
+ const isTablet = useMediaQuery(theme.breakpoints.down(900));
- const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
- const isMobile = useMediaQuery(theme.breakpoints.down(790));
+ const isFigmaTablte = useMediaQuery(theme.breakpoints.down(990));
+ const isMobile = useMediaQuery(theme.breakpoints.down(790));
- const updateQuestionInnerName = useDebouncedCallback((value) => {
- setQuestionInnerName(question.id, value);
- }, 200);
+ const updateQuestionInnerName = useDebouncedCallback((value) => {
+ setQuestionInnerName(question.id, value);
+ }, 200);
- return (
-
+
+
-
+ {
+ updateQuestion(question.id, (question) => {
+ if (!("largeCheck" in question.content)) return;
+
+ question.content.largeCheck = target.checked;
+ });
+ }}
+ />
+ {
+ updateQuestion(question.id, (question) => {
+ if (!("multi" in question.content)) return;
+
+ question.content.multi = target.checked;
+ });
+ }}
+ />
+ {
+ updateQuestion(question.id, (question) => {
+ if (!("own" in question.content)) return;
+
+ question.content.own = target.checked;
+ });
+ }}
+ />
+
+
+
+ Настройки вопросов
+
+ {
+ updateQuestion(question.id, (question) => {
+ question.content.required = !target.checked;
+ });
+ }}
+ />
+
+ {
+ updateQuestion(question.id, (question) => {
+ question.content.innerNameCheck = target.checked;
+ question.content.innerName = target.checked
+ ? question.content.innerName
+ : "";
+ });
+ }}
+ />
+ {isMobile && (
+
-
- Настройки ответов
-
- {
- updateQuestion(question.id, question => {
- if (!("largeCheck" in question.content)) return;
-
- question.content.largeCheck = target.checked;
- });
- }}
- />
- {
- updateQuestion(question.id, question => {
- if (!("multi" in question.content)) return;
-
- question.content.multi = target.checked;
- });
- }}
- />
- {
- updateQuestion(question.id, question => {
- if (!("own" in question.content)) return;
-
- question.content.own = target.checked;
- });
- }}
- />
-
-
-
- Настройки вопросов
-
- {
- updateQuestion(question.id, question => {
- question.required = !target.checked;
- });
- }}
- />
-
- {
- updateQuestion(question.id, question => {
- question.content.innerNameCheck = target.checked;
- question.content.innerName = target.checked ? question.content.innerName : "";
- });
- }}
- />
- {isMobile && (
-
-
-
-
-
- )}
-
- {question.content.innerNameCheck && (
- updateQuestionInnerName(target.value)}
- />
- )}
-
+
+
+
+
+ )}
- );
+ {question.content.innerNameCheck && (
+ updateQuestionInnerName(target.value)}
+ />
+ )}
+
+
+ );
}
diff --git a/src/pages/ViewPublicationPage/Footer.tsx b/src/pages/ViewPublicationPage/Footer.tsx
index ef121c43..8e473c18 100644
--- a/src/pages/ViewPublicationPage/Footer.tsx
+++ b/src/pages/ViewPublicationPage/Footer.tsx
@@ -3,17 +3,14 @@ import { Box, Button, useTheme } from "@mui/material";
import { useQuizViewStore } from "@root/quizView";
-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";
type FooterProps = {
questions: AnyTypedQuizQuestion[];
setCurrentQuestion: (step: AnyTypedQuizQuestion) => void;
- question: QuizQuestionBase;
+ question: AnyTypedQuizQuestion;
};
export const Footer = ({
@@ -21,9 +18,6 @@ export const Footer = ({
questions,
question,
}: FooterProps) => {
- const [disabledQuestionsId, setDisabledQuestionsId] = useState>(
- new Set()
- );
const [disablePreviousButton, setDisablePreviousButton] =
useState(false);
const [disableNextButton, setDisableNextButton] = useState(false);
@@ -58,11 +52,17 @@ export const Footer = ({
({ questionId }) => questionId === question.content.id
);
- if (question.required && answer?.changed) {
+ if ("required" in question.content && question.content.required && answer) {
setDisableNextButton(false);
+
+ return;
}
- if (question.required && !answer?.changed) {
+ if (
+ "required" in question.content &&
+ question.content.required &&
+ !answer
+ ) {
setDisableNextButton(true);
return;
@@ -103,7 +103,7 @@ export const Footer = ({
let readyBeNextQuestion = "";
- question.content.rule.main.forEach(({ next, rules }) => {
+ (question as QuizQuestionBase).content.rule.main.forEach(({ next, rules }) => {
let longerArray = Math.max(
rules[0].answers.length,
[answer?.answer].length
diff --git a/src/pages/ViewPublicationPage/StartPageViewPublication.tsx b/src/pages/ViewPublicationPage/StartPageViewPublication.tsx
index 9c6a731e..37beaf7f 100644
--- a/src/pages/ViewPublicationPage/StartPageViewPublication.tsx
+++ b/src/pages/ViewPublicationPage/StartPageViewPublication.tsx
@@ -1,142 +1,295 @@
import {
- Box,
- Button,
- Typography,
- useMediaQuery,
- useTheme,
+ Box,
+ Button,
+ ButtonBase,
+ Link,
+ Paper,
+ Typography,
+ useMediaQuery,
+ useTheme,
} from "@mui/material";
-import { useParams } from "react-router-dom";
+import { useCurrentQuiz } from "@root/quizes/hooks";
+import YoutubeEmbedIframe from "../../ui_kit/StartPagePreview/YoutubeEmbedIframe";
+import { QuizStartpageAlignType, QuizStartpageType } from "@model/quizSettings";
+import { notReachable } from "../../utils/notReachable";
+import { useUADevice } from "../../utils/hooks/useUADevice";
-
-import { useQuizes } from "@root/quizes/hooks";
-
-type StartPageViewPublicationProps = {
- setVisualStartPage: (bool: boolean) => void;
- showNextButton:boolean
-};
-
-export const StartPageViewPublication = ({
- setVisualStartPage,
- showNextButton
-}: StartPageViewPublicationProps) => {
- const quizId = Number(useParams().quizId);
- const { quizes } = useQuizes();
+export const StartPageViewPublication = () => {
+ console.log("startpage")
const theme = useTheme();
- const isTablet = useMediaQuery(theme.breakpoints.down(630));
- const quiz = quizes.find(({ backendId }) => quizId === backendId);
- const isMediaFileExist =
- quiz?.config.startpage.background.desktop ||
- quiz?.config.startpage.background.video;
+ const quiz = useCurrentQuiz();
+ const { isMobileDevice } = useUADevice();
+ console.log(quiz)
+
+ if (!quiz) return null;
+
+ const handleCopyNumber = () => {
+ navigator.clipboard.writeText(quiz.config.info.phonenumber);
+ };
+
+ const background = quiz.config.startpage.background.type === "image"
+ ? quiz.config.startpage.background.desktop
+ ? (
+
+ )
+ : null
+ : quiz.config.startpage.background.type === "video"
+ ? quiz.config.startpage.background.video
+ ? (
+
+ )
+ : null
+ : null;
return (
-
-
-
+
+
- {quiz?.config.startpage.background.mobile && (
-
- )}
-
- {quiz?.config.info.orgname}
-
-
-
-
- {quiz?.name}
-
-
- {quiz?.config.startpage.description}
-
-
-
-
-
-
-
- {quiz?.config.info.phonenumber}
-
-
- {quiz?.config.info.law}
-
-
-
- {!isTablet && isMediaFileExist && (
-
- {quiz?.config.startpage.background.mobile && (
-
- )}
- {quiz.config.startpage.background.type === "video" &&
- quiz.config.startpage.background.video && (
-
- )}
-
+
+ {quiz.config.info.orgname}
+
+
+
+
+ {quiz.config.info.site}
+
+
+ }
+ quizMainBlock={<>
+
+ {quiz.name}
+
+ {quiz.config.startpage.description}
+
+
+
+
+
+
+ {quiz.config.info.clickable ? (
+ isMobileDevice ? (
+
+
+ {quiz.config.info.phonenumber}
+
+
+ ) : (
+
+
+ {quiz.config.info.phonenumber}
+
+
+ )
+ ) : (
+
+ {quiz.config.info.phonenumber}
+
+ )}
+
+ {quiz.config.info.law}
+
+
+ >}
+ backgroundBlock={background}
+ startpageType={quiz.config.startpageType}
+ alignType={quiz.config.startpage.position}
+ />
+
);
+}
+
+function QuizPreviewLayoutByType({ quizHeaderBlock, quizMainBlock, backgroundBlock, startpageType, alignType }: {
+ quizHeaderBlock: JSX.Element;
+ quizMainBlock: JSX.Element;
+ backgroundBlock: JSX.Element | null;
+ startpageType: QuizStartpageType;
+ alignType: QuizStartpageAlignType;
+}) {
+ const theme = useTheme();
+ const isTablet = useMediaQuery(theme.breakpoints.down(630));
+
+ switch (startpageType) {
+ case null:
+ case "standard": {
+ return (
+
+
+ {quizHeaderBlock}
+ {quizMainBlock}
+
+
+ {backgroundBlock}
+
+
+ );
+ }
+ case "expanded": {
+ return (
+
+
+ {quizHeaderBlock}
+ {quizMainBlock}
+
+
+ {backgroundBlock}
+
+
+ );
+ }
+ case "centered": {
+ return (
+
+ {quizHeaderBlock}
+ {backgroundBlock &&
+
+ {backgroundBlock}
+
+ }
+ {quizMainBlock}
+
+ );
+ }
+ default: notReachable(startpageType);
+ }
+}
+
+const startpageAlignTypeToJustifyContent: Record = {
+ left: "start",
+ center: "center",
+ right: "end",
};
diff --git a/src/pages/ViewPublicationPage/index.tsx b/src/pages/ViewPublicationPage/index.tsx
index 38911b8f..66a521cc 100644
--- a/src/pages/ViewPublicationPage/index.tsx
+++ b/src/pages/ViewPublicationPage/index.tsx
@@ -5,11 +5,29 @@ import { StartPageViewPublication } from "./StartPageViewPublication";
import { Question } from "./Question";
import { useQuestions } from "@root/questions/hooks";
import { useCurrentQuiz } from "@root/quizes/hooks";
+import useSWR from "swr";
+import { quizApi } from "@api/quiz";
+import { setQuizes } from "@root/quizes/actions";
+import { isAxiosError } from "axios";
+import { devlog } from "@frontend/kitui";
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
+import { enqueueSnackbar } from "notistack";
export const ViewPage = () => {
+ useSWR("quizes", () => quizApi.getList(), {
+ onSuccess: setQuizes,
+ onError: error => {
+ const message = isAxiosError(error) ? (error.response?.data ?? "") : "";
+
+ devlog("Error getting quiz list", error);
+ enqueueSnackbar(`Не удалось получить квизы. ${message}`);
+ },
+});
+
+
const quiz = useCurrentQuiz();
+ console.log(quiz)
const { questions } = useQuestions();
const [visualStartPage, setVisualStartPage] = useState(
!quiz?.config.noStartPage
@@ -30,10 +48,7 @@ export const ViewPage = () => {
return (
{visualStartPage ? (
-
+
) : (
)}
diff --git a/src/pages/ViewPublicationPage/questions/Number.tsx b/src/pages/ViewPublicationPage/questions/Number.tsx
index c5a39293..590da466 100644
--- a/src/pages/ViewPublicationPage/questions/Number.tsx
+++ b/src/pages/ViewPublicationPage/questions/Number.tsx
@@ -57,8 +57,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
currentQuestion.content.id,
currentQuestion.content.chooseRange
? `${currentQuestion.content.start}—${max}`
- : String(currentQuestion.content.start),
- false
+ : String(currentQuestion.content.start)
);
setMinRange(String(currentQuestion.content.start));
diff --git a/src/pages/ViewPublicationPage/questions/Rating.tsx b/src/pages/ViewPublicationPage/questions/Rating.tsx
index 3ad5c674..b8565db8 100644
--- a/src/pages/ViewPublicationPage/questions/Rating.tsx
+++ b/src/pages/ViewPublicationPage/questions/Rating.tsx
@@ -7,6 +7,12 @@ import {
import { useQuizViewStore, updateAnswer } from "@root/quizView";
+import TropfyIcon from "@icons/questionsPage/tropfyIcon";
+import FlagIcon from "@icons/questionsPage/FlagIcon";
+import HeartIcon from "@icons/questionsPage/heartIcon";
+import LikeIcon from "@icons/questionsPage/likeIcon";
+import LightbulbIcon from "@icons/questionsPage/lightbulbIcon";
+import HashtagIcon from "@icons/questionsPage/hashtagIcon";
import StarIconMini from "@icons/questionsPage/StarIconMini";
import type { QuizQuestionRating } from "../../../model/questionTypes/rating";
@@ -15,6 +21,37 @@ type RatingProps = {
currentQuestion: QuizQuestionRating;
};
+const buttonRatingForm = [
+ {
+ name: "star",
+ icon: (color: string) => ,
+ },
+ {
+ name: "trophie",
+ icon: (color: string) => ,
+ },
+ {
+ name: "flag",
+ icon: (color: string) => ,
+ },
+ {
+ name: "heart",
+ icon: (color: string) => ,
+ },
+ {
+ name: "like",
+ icon: (color: string) => ,
+ },
+ {
+ name: "bubble",
+ icon: (color: string) => ,
+ },
+ {
+ name: "hashtag",
+ icon: (color: string) => ,
+ },
+];
+
export const Rating = ({ currentQuestion }: RatingProps) => {
const { answers } = useQuizViewStore();
const theme = useTheme();
@@ -22,54 +59,44 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
answers.find(
({ questionId }) => questionId === currentQuestion.content.id
) ?? {};
+ const form = buttonRatingForm.find(
+ ({ name }) => name === currentQuestion.content.form
+ );
return (
{currentQuestion.title}
-
- updateAnswer(currentQuestion.content.id, String(value))
- }
- sx={{ height: "50px", gap: "15px" }}
- max={currentQuestion.content.steps}
- icon={
-
- }
- emptyIcon={
-
- }
- />
+
+ {currentQuestion.content.ratingNegativeDescription}
+
-
- {currentQuestion.content.ratingNegativeDescription}
-
-
- {currentQuestion.content.ratingPositiveDescription}
-
+
+ updateAnswer(currentQuestion.content.id, String(value))
+ }
+ sx={{ height: "50px", gap: "15px" }}
+ max={currentQuestion.content.steps}
+ icon={form?.icon(theme.palette.brightPurple.main)}
+ emptyIcon={form?.icon(theme.palette.grey2.main)}
+ />
+
+ {currentQuestion.content.ratingPositiveDescription}
+
);
diff --git a/src/pages/ViewPublicationPage/questions/Variant.tsx b/src/pages/ViewPublicationPage/questions/Variant.tsx
index e8486b5a..12b3945b 100644
--- a/src/pages/ViewPublicationPage/questions/Variant.tsx
+++ b/src/pages/ViewPublicationPage/questions/Variant.tsx
@@ -1,3 +1,4 @@
+import { useEffect } from "react";
import {
Box,
Typography,
@@ -6,32 +7,56 @@ import {
FormControlLabel,
Radio,
Checkbox,
+ TextField,
useTheme,
} from "@mui/material";
-import { useQuizViewStore, updateAnswer, deleteAnswer } from "@root/quizView";
+import {
+ useQuizViewStore,
+ updateAnswer,
+ deleteAnswer,
+ updateOwnVariant,
+ deleteOwnVariant,
+} from "@root/quizView";
import RadioCheck from "@ui_kit/RadioCheck";
import RadioIcon from "@ui_kit/RadioIcon";
import { CheckboxIcon } from "@icons/Checkbox";
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
+import type { QuestionVariant } from "../../../model/questionTypes/shared";
type VariantProps = {
stepNumber: number;
currentQuestion: QuizQuestionVariant;
};
+type VariantItemProps = {
+ currentQuestion: QuizQuestionVariant;
+ variant: QuestionVariant;
+ answer: string | string[] | undefined;
+ index: number;
+ own?: boolean;
+};
+
export const Variant = ({ currentQuestion }: VariantProps) => {
- const { answers } = useQuizViewStore();
- const theme = useTheme();
+ const { answers, ownVariants } = useQuizViewStore();
const { answer } =
answers.find(
({ questionId }) => questionId === currentQuestion.content.id
) ?? {};
+ const ownVariant = ownVariants.find(
+ (variant) => variant.contentId === currentQuestion.content.id
+ );
const Group = currentQuestion.content.multi ? FormGroup : RadioGroup;
+ useEffect(() => {
+ if (!ownVariant) {
+ updateOwnVariant(currentQuestion.content.id, "");
+ }
+ }, []);
+
return (
{currentQuestion.title}
@@ -60,58 +85,23 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
}}
>
{currentQuestion.content.variants.map((variant, index) => (
- }
- icon={}
- />
- ) : (
- } icon={} />
- )
- }
- label={variant.answer}
- onClick={(event) => {
- event.preventDefault();
- const variantId = currentQuestion.content.variants[index].id;
-
- if (currentQuestion.content.multi) {
- const currentAnswer =
- typeof answer !== "string" ? answer || [] : [];
-
- updateAnswer(
- currentQuestion.content.id,
- currentAnswer?.includes(variantId)
- ? currentAnswer?.filter((item) => item !== variantId)
- : [...currentAnswer, variantId]
- );
-
- return;
- }
-
- updateAnswer(currentQuestion.content.id, variantId);
-
- if (answer === variantId) {
- deleteAnswer(currentQuestion.content.id);
- }
- }}
+ currentQuestion={currentQuestion}
+ variant={variant}
+ answer={answer}
+ index={index}
/>
))}
+ {currentQuestion.content.own && ownVariant && (
+
+ )}
{currentQuestion.content.back && (
@@ -127,3 +117,66 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
);
};
+
+const VariantItem = ({
+ currentQuestion,
+ variant,
+ answer,
+ index,
+ own = false,
+}: VariantItemProps) => {
+ const theme = useTheme();
+
+ return (
+ }
+ icon={}
+ />
+ ) : (
+ } icon={} />
+ )
+ }
+ label={own ? : variant.answer}
+ onClick={(event) => {
+ event.preventDefault();
+ const variantId = currentQuestion.content.variants[index].id;
+
+ if (currentQuestion.content.multi) {
+ const currentAnswer = typeof answer !== "string" ? answer || [] : [];
+
+ updateAnswer(
+ currentQuestion.content.id,
+ currentAnswer.includes(variantId)
+ ? currentAnswer?.filter((item) => item !== variantId)
+ : [...currentAnswer, variantId]
+ );
+
+ return;
+ }
+
+ updateAnswer(currentQuestion.content.id, variantId);
+
+ if (answer === variantId) {
+ deleteAnswer(currentQuestion.content.id);
+ }
+ }}
+ />
+ );
+};
diff --git a/src/pages/startPage/StartPageSettings.tsx b/src/pages/startPage/StartPageSettings.tsx
index cf279d3c..fa64b178 100755
--- a/src/pages/startPage/StartPageSettings.tsx
+++ b/src/pages/startPage/StartPageSettings.tsx
@@ -331,74 +331,7 @@ export default function StartPageSettings() {
-
- }
- checkedIcon={}
- />
- }
- label="мобильная версия"
- sx={{
- color: theme.palette.brightPurple.main,
- textDecorationLine: "underline",
- textDecorationColor: theme.palette.brightPurple.main,
- ml: "-9px",
- userSelect: "none",
- "& .css-14o5ia4-MuiTypography-root": {
- fontSize: "16px"
- }
- }}
- onClick={() => {
- MobileVersionHC(!mobileVersion);
- }}
- />
- {mobileVersion ? (
-
-
- Изображение для мобильной версии
-
- {
- uploadQuizImage(quiz.id, file, (quiz, url) => {
- quiz.config.startpage.background.mobile = url;
- quiz.config.startpage.background.originalMobile = url;
- });
- }}
- onImageSaveClick={file => {
- uploadQuizImage(quiz.id, file, (quiz, url) => {
- quiz.config.startpage.background.mobile = url;
- });
- }}
- onDeleteClick={() => {
- updateQuiz(quiz.id, quiz => {
- quiz.config.startpage.background.mobile = null;
- });
- }}
- />
-
- ) : (
- <>>
- )}
-
+
-
- Настройки видео
-
- updateQuiz(quiz.id, quiz => {
- quiz.config.startpage.background.cycle = e.target.checked;
- })}
- />
-
- Изображение для мобильной версии
-
- {
- uploadQuizImage(quiz.id, file, (quiz, url) => {
- quiz.config.startpage.background.mobile = url;
- quiz.config.startpage.background.originalMobile = url;
- });
- }}
- onImageSaveClick={file => {
- uploadQuizImage(quiz.id, file, (quiz, url) => {
- quiz.config.startpage.background.mobile = url;
- });
- }}
- onDeleteClick={() => {
- updateQuiz(quiz.id, quiz => {
- quiz.config.startpage.background.mobile = null;
- });
- }}
- />
+
-
- Расположение элементов
-
{designType !== "centered" &&
-
- updateQuiz(quiz.id, quiz => {
- quiz.config.startpage.position = "left";
- })}
- isActive={quiz.config.startpage.position === "left"}
- Icon={AlignLeftIcon}
- />
- updateQuiz(quiz.id, quiz => {
- quiz.config.startpage.position = "center";
- })}
- isActive={quiz.config.startpage.position === "center"}
- Icon={AlignCenterIcon}
- sx={{ display: designType === "standard" ? "none" : "flex" }}
- />
- updateQuiz(quiz.id, quiz => {
- quiz.config.startpage.position = "right";
- })}
- isActive={quiz.config.startpage.position === "right"}
- Icon={AlignRightIcon}
- />
-
+ <>
+
+ Расположение элементов
+
+
+ updateQuiz(quiz.id, quiz => {
+ quiz.config.startpage.position = "left";
+ })}
+ isActive={quiz.config.startpage.position === "left"}
+ Icon={AlignLeftIcon}
+ />
+ updateQuiz(quiz.id, quiz => {
+ quiz.config.startpage.position = "center";
+ })}
+ isActive={quiz.config.startpage.position === "center"}
+ Icon={AlignCenterIcon}
+ sx={{ display: designType === "standard" ? "none" : "flex" }}
+ />
+ updateQuiz(quiz.id, quiz => {
+ quiz.config.startpage.position = "right";
+ })}
+ isActive={quiz.config.startpage.position === "right"}
+ Icon={AlignRightIcon}
+ />
+
+ >
+
}
{(isTablet || !isSmallMonitor) && (
<>
diff --git a/src/stores/questions/actions.ts b/src/stores/questions/actions.ts
index 4b287057..b853445b 100644
--- a/src/stores/questions/actions.ts
+++ b/src/stores/questions/actions.ts
@@ -176,9 +176,9 @@ const REQUEST_DEBOUNCE = 200;
const requestQueue = new RequestQueue();
let requestTimeoutId: ReturnType;
-export const updateQuestion = (
+export const updateQuestion = (
questionId: string,
- updateFn: (question: AnyTypedQuizQuestion) => void,
+ updateFn: (question: T) => void,
skipQueue = false,
) => {
setProducedState(state => {
@@ -186,7 +186,7 @@ export const updateQuestion = (
if (!question) return;
if (question.type === null) throw new Error("Cannot update untyped question, use 'updateUntypedQuestion' instead");
- updateFn(question);
+ updateFn(question as T);
}, {
type: "updateQuestion",
questionId,
diff --git a/src/stores/quizView.ts b/src/stores/quizView.ts
index ae68a8fe..523579a0 100644
--- a/src/stores/quizView.ts
+++ b/src/stores/quizView.ts
@@ -1,21 +1,28 @@
import { create } from "zustand";
import { devtools } from "zustand/middleware";
+import type { QuestionVariant } from "../model/questionTypes/shared";
+
type Answer = {
questionId: string;
answer: string | string[];
- // Поле отвечающее за первое изменение ответа, нужно для галочки "Необязательный вопрос"
- changed: boolean;
+};
+
+type OwnVariant = {
+ contentId: string;
+ variant: QuestionVariant;
};
interface QuizViewStore {
answers: Answer[];
+ ownVariants: OwnVariant[];
}
export const useQuizViewStore = create()(
devtools(
(set, get) => ({
answers: [],
+ ownVariants: [],
}),
{
name: "quizView",
@@ -23,20 +30,16 @@ export const useQuizViewStore = create()(
)
);
-export const updateAnswer = (
- questionId: string,
- answer: string | string[],
- changed = true
-) => {
+export const updateAnswer = (questionId: string, answer: string | string[]) => {
const answers = [...useQuizViewStore.getState().answers];
const answerIndex = answers.findIndex(
(answer) => questionId === answer.questionId
);
if (answerIndex < 0) {
- answers.push({ questionId, answer, changed });
+ answers.push({ questionId, answer });
} else {
- answers[answerIndex] = { questionId, answer, changed };
+ answers[answerIndex] = { questionId, answer };
}
useQuizViewStore.setState({ answers });
@@ -50,3 +53,44 @@ export const deleteAnswer = (questionId: string) => {
useQuizViewStore.setState({ answers: filteredItems });
};
+
+export const updateOwnVariant = (contentId: string, answer: string) => {
+ const ownVariants = [...useQuizViewStore.getState().ownVariants];
+ const ownVariantIndex = ownVariants.findIndex(
+ (variant) => variant.contentId === contentId
+ );
+
+ if (ownVariantIndex < 0) {
+ ownVariants.push({
+ contentId,
+ variant: {
+ id: getRandom(),
+ answer,
+ extendedText: "",
+ hints: "",
+ originalImageUrl: "",
+ },
+ });
+ } else {
+ ownVariants[ownVariantIndex].variant.answer = answer;
+ }
+
+ useQuizViewStore.setState({ ownVariants });
+};
+
+export const deleteOwnVariant = (contentId: string) => {
+ const ownVariants = [...useQuizViewStore.getState().ownVariants];
+
+ const filteredOwnVariants = ownVariants.filter(
+ (variant) => variant.contentId !== contentId
+ );
+
+ useQuizViewStore.setState({ ownVariants: filteredOwnVariants });
+};
+
+function getRandom() {
+ const min = Math.ceil(1000000);
+ const max = Math.floor(10000000);
+
+ return String(Math.floor(Math.random() * (max - min)) + min);
+}
diff --git a/src/ui_kit/StartPagePreview/YoutubeEmbedIframe.tsx b/src/ui_kit/StartPagePreview/YoutubeEmbedIframe.tsx
index 5e83bf19..677690e5 100644
--- a/src/ui_kit/StartPagePreview/YoutubeEmbedIframe.tsx
+++ b/src/ui_kit/StartPagePreview/YoutubeEmbedIframe.tsx
@@ -1,12 +1,13 @@
-import { Box } from "@mui/material";
+import { Box, SxProps } from "@mui/material";
interface Props {
videoUrl: string;
+ containerSX?: SxProps;
}
-export default function YoutubeEmbedIframe({ videoUrl }: Props) {
+export default function YoutubeEmbedIframe({ videoUrl, containerSX }: Props) {
const extractYoutubeVideoId = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/gi;
const videoId = extractYoutubeVideoId.exec(videoUrl)?.[1];
if (!videoId) return null;
@@ -21,7 +22,8 @@ export default function YoutubeEmbedIframe({ videoUrl }: Props) {
"& iframe": {
width: "100%",
height: "100%",
- }
+ },
+ ...containerSX
}}>