Merge branch 'staging' into 'main'
подправлена стартовая станица мобилки, автофокус на инпуте, отправка данных... See merge request frontend/squzanswerer!83
This commit is contained in:
commit
41f1b57c9a
@ -160,7 +160,7 @@ export const ContactForm = ({ currentQuestion, onShowResult }: Props) => {
|
|||||||
sx={{
|
sx={{
|
||||||
width: isWide && !isMobile ? "100%" : isMobile ? undefined : "530px",
|
width: isWide && !isMobile ? "100%" : isMobile ? undefined : "530px",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
height: "90vh",
|
height: "100%",
|
||||||
display: isWide && !isMobile ? "flex" : undefined,
|
display: isWide && !isMobile ? "flex" : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Box, Link, useTheme} from "@mui/material";
|
import { Box, Link, useTheme } from "@mui/material";
|
||||||
|
|
||||||
import { Footer } from "./Footer";
|
import { Footer } from "./Footer";
|
||||||
import { Date } from "./questions/Date";
|
import { Date } from "./questions/Date";
|
||||||
@ -15,13 +15,12 @@ import { Varimg } from "./questions/Varimg";
|
|||||||
|
|
||||||
import type { RealTypedQuizQuestion } from "../../model/questionTypes/shared";
|
import type { RealTypedQuizQuestion } from "../../model/questionTypes/shared";
|
||||||
|
|
||||||
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
import { NameplateLogoFQ } from "@icons/NameplateLogoFQ";
|
import { NameplateLogoFQ } from "@icons/NameplateLogoFQ";
|
||||||
import { NameplateLogoFQDark } from "@icons/NameplateLogoFQDark";
|
import { NameplateLogoFQDark } from "@icons/NameplateLogoFQDark";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
|
||||||
import { notReachable } from "@utils/notReachable";
|
import { notReachable } from "@utils/notReachable";
|
||||||
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
import { quizThemes } from "@utils/themes/Publication/themePublication";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { useRootContainerSize } from "../../contexts/RootContainerWidthContext";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
currentQuestion: RealTypedQuizQuestion;
|
currentQuestion: RealTypedQuizQuestion;
|
||||||
@ -38,12 +37,11 @@ export const Question = ({
|
|||||||
}: Props) => {
|
}: Props) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings } = useQuizData();
|
const { settings } = useQuizData();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
console.log(currentQuestionStepNumber)
|
||||||
console.log(settings)
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
height: isMobile ? "100%" : "100vh"
|
height: "100%",
|
||||||
}}>
|
}}>
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
height: "calc(100% - 75px)",
|
height: "calc(100% - 75px)",
|
||||||
@ -56,11 +54,11 @@ console.log(settings)
|
|||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
justifyContent: "space-between"
|
justifyContent: "space-between"
|
||||||
}}>
|
}}>
|
||||||
<QuestionByType key={currentQuestion.id} question={currentQuestion} />
|
<QuestionByType key={currentQuestion.id} question={currentQuestion} stepNumber={currentQuestionStepNumber} />
|
||||||
{quizThemes[settings.cfg.theme].isLight ? (
|
{quizThemes[settings.cfg.theme].isLight ? (
|
||||||
<Link target={"_blank"} href={"https://quiz.pena.digital"}>
|
<Link target={"_blank"} href={"https://quiz.pena.digital"}>
|
||||||
<NameplateLogoFQ style={{ fontSize: "34px", width: "200px", height: "auto" }} />
|
<NameplateLogoFQ style={{ fontSize: "34px", width: "200px", height: "auto" }} />
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<Link target={"_blank"} href={"https://quiz.pena.digital"}>
|
<Link target={"_blank"} href={"https://quiz.pena.digital"}>
|
||||||
<NameplateLogoFQDark style={{ fontSize: "34px", width: "200px", height: "auto" }} />
|
<NameplateLogoFQDark style={{ fontSize: "34px", width: "200px", height: "auto" }} />
|
||||||
@ -77,15 +75,16 @@ console.log(settings)
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function QuestionByType({ question }: {
|
function QuestionByType({ question, stepNumber }: {
|
||||||
question: RealTypedQuizQuestion;
|
question: RealTypedQuizQuestion;
|
||||||
|
stepNumber: number | null;
|
||||||
}) {
|
}) {
|
||||||
switch (question.type) {
|
switch (question.type) {
|
||||||
case "variant": return <Variant currentQuestion={question} />;
|
case "variant": return <Variant currentQuestion={question} />;
|
||||||
case "images": return <Images currentQuestion={question} />;
|
case "images": return <Images currentQuestion={question} />;
|
||||||
case "varimg": return <Varimg currentQuestion={question} />;
|
case "varimg": return <Varimg currentQuestion={question} />;
|
||||||
case "emoji": return <Emoji currentQuestion={question} />;
|
case "emoji": return <Emoji currentQuestion={question} />;
|
||||||
case "text": return <Text currentQuestion={question} />;
|
case "text": return <Text currentQuestion={question} stepNumber={stepNumber}/>;
|
||||||
case "select": return <Select currentQuestion={question} />;
|
case "select": return <Select currentQuestion={question} />;
|
||||||
case "date": return <Date currentQuestion={question} />;
|
case "date": return <Date currentQuestion={question} />;
|
||||||
case "number": return <Number currentQuestion={question} />;
|
case "number": return <Number currentQuestion={question} />;
|
||||||
|
@ -23,6 +23,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
const { settings } = useQuizData();
|
const { settings } = useQuizData();
|
||||||
|
const spec = settings.cfg.spec
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -32,7 +33,7 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
width: "100vw",
|
width: "100%",
|
||||||
pt: "28px",
|
pt: "28px",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
}}
|
}}
|
||||||
@ -63,8 +64,8 @@ export const ResultForm = ({ resultQuestion }: ResultFormProps) => {
|
|||||||
component="img"
|
component="img"
|
||||||
src={resultQuestion.content.back}
|
src={resultQuestion.content.back}
|
||||||
sx={{
|
sx={{
|
||||||
width: isMobile ? "100%" : "490px",
|
width: spec ? "100%" : isMobile ? "100%" : "490px",
|
||||||
height: isMobile ? "100%" : "280px",
|
height: spec ? "auto" : isMobile ? "100%" : "280px",
|
||||||
}}
|
}}
|
||||||
></Box>
|
></Box>
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,7 @@ export const StartPageViewPublication = () => {
|
|||||||
const handleCopyNumber = () => {
|
const handleCopyNumber = () => {
|
||||||
navigator.clipboard.writeText(settings.cfg.info.phonenumber);
|
navigator.clipboard.writeText(settings.cfg.info.phonenumber);
|
||||||
};
|
};
|
||||||
console.log(settings.cfg.startpage.background.type)
|
console.log(settings.cfg.startpage.background.type);
|
||||||
|
|
||||||
const background =
|
const background =
|
||||||
settings.cfg.startpage.background.type === "image" ? (
|
settings.cfg.startpage.background.type === "image" ? (
|
||||||
@ -45,9 +45,7 @@ export const StartPageViewPublication = () => {
|
|||||||
width:
|
width:
|
||||||
settings.cfg.startpageType === "centered"
|
settings.cfg.startpageType === "centered"
|
||||||
? "550px"
|
? "550px"
|
||||||
: settings.cfg.startpageType === "expanded"
|
: "100%",
|
||||||
? "100vw"
|
|
||||||
: "100%",
|
|
||||||
height:
|
height:
|
||||||
settings.cfg.startpageType === "centered"
|
settings.cfg.startpageType === "centered"
|
||||||
? "275px"
|
? "275px"
|
||||||
@ -304,7 +302,7 @@ function QuizPreviewLayoutByType({
|
|||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
alignItems: "flex-start",
|
alignItems: "flex-start",
|
||||||
p: "25px",
|
p: "25px",
|
||||||
height: "80%",
|
height: "100%",
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
overflowX: "hidden"
|
overflowX: "hidden"
|
||||||
}}
|
}}
|
||||||
@ -345,7 +343,7 @@ function QuizPreviewLayoutByType({
|
|||||||
<StartPageMobile />
|
<StartPageMobile />
|
||||||
) : (
|
) : (
|
||||||
<Box
|
<Box
|
||||||
id="pain"
|
id="pain"
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: alignType === "left" ? (isMobile ? "column-reverse" : "row") : "row-reverse",
|
flexDirection: alignType === "left" ? (isMobile ? "column-reverse" : "row") : "row-reverse",
|
||||||
|
@ -25,7 +25,7 @@ export const Date = ({ currentQuestion }: DateProps) => {
|
|||||||
({ questionId }) => questionId === currentQuestion.id
|
({ questionId }) => questionId === currentQuestion.id
|
||||||
)?.answer as string;
|
)?.answer as string;
|
||||||
const currentAnswer = moment(answer) || moment();
|
const currentAnswer = moment(answer) || moment();
|
||||||
const [readySend, setReadySend] = useState(true)
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
@ -53,29 +53,26 @@ export const Date = ({ currentQuestion }: DateProps) => {
|
|||||||
}}
|
}}
|
||||||
value={currentAnswer}
|
value={currentAnswer}
|
||||||
onChange={async (date) => {
|
onChange={async (date) => {
|
||||||
if (readySend) {
|
if (isSending || !date) return;
|
||||||
setReadySend(false)
|
|
||||||
if (!date) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
setIsSending(true);
|
||||||
await sendAnswer({
|
try {
|
||||||
questionId: currentQuestion.id,
|
await sendAnswer({
|
||||||
body: moment(date).format("YYYY.MM.DD"),
|
questionId: currentQuestion.id,
|
||||||
qid: quizId,
|
body: moment(date).format("YYYY.MM.DD"),
|
||||||
});
|
qid: quizId,
|
||||||
|
});
|
||||||
|
|
||||||
updateAnswer(
|
updateAnswer(
|
||||||
currentQuestion.id,
|
currentQuestion.id,
|
||||||
date,
|
date,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
|
||||||
setReadySend(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
openPickerButton: {
|
openPickerButton: {
|
||||||
|
@ -36,7 +36,7 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
|
|||||||
answers.find(
|
answers.find(
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
({ questionId }) => questionId === currentQuestion.id
|
||||||
) ?? {};
|
) ?? {};
|
||||||
const [readySend, setReadySend] = useState(true)
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
@ -70,6 +70,7 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
|
|||||||
{currentQuestion.content.variants.map((variant, index) => (
|
{currentQuestion.content.variants.map((variant, index) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
key={variant.id}
|
key={variant.id}
|
||||||
|
disabled={isSending}
|
||||||
sx={{
|
sx={{
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
border: `1px solid`,
|
border: `1px solid`,
|
||||||
@ -130,45 +131,39 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
|
|||||||
value={index}
|
value={index}
|
||||||
onClick={async (event) => {
|
onClick={async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (readySend) {
|
if (isSending) return;
|
||||||
setReadySend(false)
|
|
||||||
try {
|
|
||||||
|
|
||||||
|
setIsSending(true);
|
||||||
|
try {
|
||||||
|
await sendAnswer({
|
||||||
|
questionId: currentQuestion.id,
|
||||||
|
body: currentQuestion.content.variants[index].extendedText + " " + currentQuestion.content.variants[index].answer,
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
|
||||||
|
updateAnswer(
|
||||||
|
currentQuestion.id,
|
||||||
|
currentQuestion.content.variants[index].id,
|
||||||
|
currentQuestion.content.variants[index].points || 0
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (answer === currentQuestion.content.variants[index].id) {
|
||||||
|
deleteAnswer(currentQuestion.id);
|
||||||
|
try {
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: currentQuestion.content.variants[index].extendedText + " " + currentQuestion.content.variants[index].answer,
|
body: "",
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAnswer(
|
|
||||||
currentQuestion.id,
|
|
||||||
currentQuestion.content.variants[index].id,
|
|
||||||
currentQuestion.content.variants[index].points || 0
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (answer === currentQuestion.content.variants[index].id) {
|
|
||||||
deleteAnswer(currentQuestion.id);
|
|
||||||
try {
|
|
||||||
|
|
||||||
await sendAnswer({
|
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: "",
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setReadySend(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
control={
|
control={
|
||||||
|
@ -16,6 +16,7 @@ import { enqueueSnackbar } from "notistack";
|
|||||||
import { useRootContainerSize } from "../../../contexts/RootContainerWidthContext";
|
import { useRootContainerSize } from "../../../contexts/RootContainerWidthContext";
|
||||||
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
|
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
type ImagesProps = {
|
type ImagesProps = {
|
||||||
currentQuestion: QuizQuestionImages;
|
currentQuestion: QuizQuestionImages;
|
||||||
@ -26,6 +27,7 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
|
|||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer;
|
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer;
|
||||||
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
const isTablet = useRootContainerSize() < 1000;
|
const isTablet = useRootContainerSize() < 1000;
|
||||||
const isMobile = useRootContainerSize() < 500;
|
const isMobile = useRootContainerSize() < 500;
|
||||||
|
|
||||||
@ -65,43 +67,44 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
|
|||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
border: `1px solid`,
|
border: `1px solid`,
|
||||||
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
borderColor: answer === variant.id ? theme.palette.primary.main : "#9A9AAF",
|
||||||
|
transition: "opacity 0.5s ease",
|
||||||
|
opacity: isSending ? 0.5 : 1,
|
||||||
|
pointerEvents: isSending ? "none" : "auto",
|
||||||
}}
|
}}
|
||||||
onClick={async (event) => {
|
onClick={async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
if (isSending) return;
|
||||||
|
|
||||||
|
setIsSending(true);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: `${currentQuestion.content.variants[index].answer} <img style="width:100%; max-width:250px; max-height:250px" src="${currentQuestion.content.variants[index].extendedText}"/>`,
|
body: `${currentQuestion.content.variants[index].answer} <img style="width:100%; max-width:250px; max-height:250px" src="${currentQuestion.content.variants[index].extendedText}"/>`,
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAnswer(
|
updateAnswer(
|
||||||
currentQuestion.id,
|
currentQuestion.id,
|
||||||
currentQuestion.content.variants[index].id,
|
currentQuestion.content.variants[index].id,
|
||||||
currentQuestion.content.variants[index].points || 0
|
currentQuestion.content.variants[index].points || 0
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (answer === currentQuestion.content.variants[index].id) {
|
if (answer === currentQuestion.content.variants[index].id) {
|
||||||
deleteAnswer(currentQuestion.id);
|
deleteAnswer(currentQuestion.id);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: "",
|
body: "",
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
||||||
@ -159,5 +162,4 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
|
|||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -32,6 +32,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
|
|||||||
useState<string>("100000000000");
|
useState<string>("100000000000");
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
const [minBorder, maxBorder] = currentQuestion.content.range
|
const [minBorder, maxBorder] = currentQuestion.content.range
|
||||||
@ -40,8 +41,13 @@ export const Number = ({ currentQuestion }: NumberProps) => {
|
|||||||
const min = minBorder < maxBorder ? minBorder : maxBorder;
|
const min = minBorder < maxBorder ? minBorder : maxBorder;
|
||||||
const max = minBorder < maxBorder ? maxBorder : minBorder;
|
const max = minBorder < maxBorder ? maxBorder : minBorder;
|
||||||
const reversed = minBorder > maxBorder;
|
const reversed = minBorder > maxBorder;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("reversed:", reversed)
|
||||||
|
}, [reversed])
|
||||||
|
|
||||||
const sendAnswerToBackend = async (value: string, noUpdate = false) => {
|
const sendAnswerToBackend = async (value: string, noUpdate = false) => {
|
||||||
|
setIsSending(true);
|
||||||
try {
|
try {
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
@ -55,6 +61,8 @@ export const Number = ({ currentQuestion }: NumberProps) => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateValueDebounced = useDebouncedCallback(async (value: string) => {
|
const updateValueDebounced = useDebouncedCallback(async (value: string) => {
|
||||||
@ -353,7 +361,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{wordBreak: "break-word"}}>
|
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
|
||||||
{currentQuestion.title}
|
{currentQuestion.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box
|
<Box
|
||||||
|
@ -43,7 +43,7 @@ export const Page = ({ currentQuestion }: PageProps) => {
|
|||||||
containerSX={{
|
containerSX={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "calc(100% - 270px)",
|
height: "calc(100% - 270px)",
|
||||||
maxHeight: "80vh",
|
maxHeight: "80%",
|
||||||
objectFit: "contain",
|
objectFit: "contain",
|
||||||
}}
|
}}
|
||||||
videoUrl={currentQuestion.content.video}
|
videoUrl={currentQuestion.content.video}
|
||||||
|
@ -20,6 +20,7 @@ import { enqueueSnackbar } from "notistack";
|
|||||||
import { useRootContainerSize } from "../../../contexts/RootContainerWidthContext";
|
import { useRootContainerSize } from "../../../contexts/RootContainerWidthContext";
|
||||||
import type { QuizQuestionRating } from "../../../model/questionTypes/rating";
|
import type { QuizQuestionRating } from "../../../model/questionTypes/rating";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
type RatingProps = {
|
type RatingProps = {
|
||||||
currentQuestion: QuizQuestionRating;
|
currentQuestion: QuizQuestionRating;
|
||||||
@ -61,6 +62,7 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
|
|||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
const { answer } =
|
const { answer } =
|
||||||
answers.find(
|
answers.find(
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
({ questionId }) => questionId === currentQuestion.id
|
||||||
@ -89,10 +91,10 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RatingComponent
|
<RatingComponent
|
||||||
|
disabled={isSending}
|
||||||
value={Number(answer || 0)}
|
value={Number(answer || 0)}
|
||||||
onChange={async (_, value) => {
|
onChange={async (_, value) => {
|
||||||
|
setIsSending(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
@ -106,12 +108,15 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
height: "50px",
|
height: "50px",
|
||||||
gap: isMobile ? undefined : "15px",
|
gap: isMobile ? undefined : "15px",
|
||||||
justifyContent: isMobile ? "space-between" : undefined,
|
justifyContent: isMobile ? "space-between" : undefined,
|
||||||
width: isMobile ? "100%" : undefined
|
width: isMobile ? "100%" : undefined,
|
||||||
|
transition: "opacity 0.5s ease",
|
||||||
}}
|
}}
|
||||||
max={currentQuestion.content.steps}
|
max={currentQuestion.content.steps}
|
||||||
icon={form?.icon(theme.palette.primary.main)}
|
icon={form?.icon(theme.palette.primary.main)}
|
||||||
|
@ -8,6 +8,7 @@ import { sendAnswer } from "@api/quizRelase";
|
|||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
|
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
type SelectProps = {
|
type SelectProps = {
|
||||||
currentQuestion: QuizQuestionSelect;
|
currentQuestion: QuizQuestionSelect;
|
||||||
@ -16,6 +17,7 @@ type SelectProps = {
|
|||||||
export const Select = ({ currentQuestion }: SelectProps) => {
|
export const Select = ({ currentQuestion }: SelectProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { quizId } = useQuizData();
|
const { quizId } = useQuizData();
|
||||||
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const { answer } =
|
const { answer } =
|
||||||
answers.find(
|
answers.find(
|
||||||
@ -24,7 +26,7 @@ export const Select = ({ currentQuestion }: SelectProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{wordBreak: "break-word"}}>{currentQuestion.title}</Typography>
|
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -34,11 +36,13 @@ export const Select = ({ currentQuestion }: SelectProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectComponent
|
<SelectComponent
|
||||||
|
disabled={isSending}
|
||||||
placeholder={currentQuestion.content.default}
|
placeholder={currentQuestion.content.default}
|
||||||
activeItemIndex={answer ? Number(answer) : -1}
|
activeItemIndex={answer ? Number(answer) : -1}
|
||||||
items={currentQuestion.content.variants.map(({ answer }) => answer)}
|
items={currentQuestion.content.variants.map(({ answer }) => answer)}
|
||||||
colorMain={theme.palette.primary.main}
|
colorMain={theme.palette.primary.main}
|
||||||
onChange={async (_, value) => {
|
onChange={async (_, value) => {
|
||||||
|
setIsSending(true);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
deleteAnswer(currentQuestion.id);
|
deleteAnswer(currentQuestion.id);
|
||||||
try {
|
try {
|
||||||
@ -52,7 +56,7 @@ export const Select = ({ currentQuestion }: SelectProps) => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
return;
|
return setIsSending(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -69,7 +73,7 @@ export const Select = ({ currentQuestion }: SelectProps) => {
|
|||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,43 +1,102 @@
|
|||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import {Box, TextField, Typography, useTheme} from "@mui/material";
|
||||||
|
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
|
||||||
import { updateAnswer, useQuizViewStore } from "@stores/quizView";
|
import { updateAnswer, useQuizViewStore } from "@stores/quizView";
|
||||||
|
|
||||||
import { sendAnswer } from "@api/quizRelase";
|
import { sendAnswer } from "@api/quizRelase";
|
||||||
|
import { useQuizData } from "@contexts/QuizDataContext";
|
||||||
|
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
|
||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
|
import {ChangeEvent, useEffect, useState} from "react";
|
||||||
import { useDebouncedCallback } from "use-debounce";
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import type { QuizQuestionText } from "../../../model/questionTypes/text";
|
import type { QuizQuestionText } from "../../../model/questionTypes/text";
|
||||||
import { useQuizData } from "@contexts/QuizDataContext";
|
|
||||||
|
|
||||||
type TextProps = {
|
type TextProps = {
|
||||||
currentQuestion: QuizQuestionText;
|
currentQuestion: QuizQuestionText;
|
||||||
|
stepNumber: number | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Text = ({ currentQuestion }: TextProps) => {
|
const Orientation = [
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: false},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: false},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: false},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: false},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: false},
|
||||||
|
{horizontal: false},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
{horizontal: true},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const Text = ({ currentQuestion, stepNumber }: TextProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const { settings } = useQuizData();
|
||||||
|
const spec = settings.cfg.spec
|
||||||
const { quizId } = useQuizData();
|
const { quizId } = useQuizData();
|
||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(650));
|
const isMobile = useRootContainerSize() < 650;
|
||||||
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {};
|
||||||
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
const inputHC = useDebouncedCallback(async (text) => {
|
const inputHC = useDebouncedCallback(async (text) => {
|
||||||
|
setIsSending(true);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: text,
|
body: text,
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
}, 400);
|
}, 400);
|
||||||
return (
|
useEffect(
|
||||||
|
() => () => {
|
||||||
|
inputHC.flush();
|
||||||
|
},
|
||||||
|
[inputHC]
|
||||||
|
);
|
||||||
|
switch (spec) {
|
||||||
|
case true:
|
||||||
|
return <TextSpecial currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} stepNumber={stepNumber}/>;
|
||||||
|
case undefined:
|
||||||
|
return <TextNormal currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} />;
|
||||||
|
default:
|
||||||
|
return <TextNormal currentQuestion={currentQuestion} answer={answer} inputHC={inputHC} />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
currentQuestion: QuizQuestionText;
|
||||||
|
answer: any,
|
||||||
|
inputHC: (a: string) => void;
|
||||||
|
stepNumber?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TextNormal = ({currentQuestion, answer, inputHC}: Props) => {
|
||||||
|
const isMobile = useRootContainerSize() < 650;
|
||||||
|
const theme = useTheme();
|
||||||
|
return(
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{wordBreak: "break-word"}}>{currentQuestion.title}</Typography>
|
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -47,21 +106,20 @@ export const Text = ({ currentQuestion }: TextProps) => {
|
|||||||
alignItems: "center"
|
alignItems: "center"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={currentQuestion.content.placeholder}
|
placeholder={currentQuestion.content.placeholder}
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
value={answer || ""}
|
value={answer || ""}
|
||||||
onChange={async ({ target }) => {
|
onChange={async ({ target }) => {
|
||||||
updateAnswer(currentQuestion.id, target.value, 0);
|
updateAnswer(currentQuestion.id, target.value, 0);
|
||||||
inputHC(target.value);
|
inputHC(target.value);
|
||||||
}
|
}}
|
||||||
}
|
sx={{
|
||||||
sx={{
|
"&:focus-visible": {
|
||||||
"&:focus-visible": {
|
borderColor: theme.palette.primary.main
|
||||||
borderColor: theme.palette.primary.main
|
}
|
||||||
}
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
|
||||||
{currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
{currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
||||||
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px", margin: "15px" }}>
|
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px", margin: "15px" }}>
|
||||||
<img
|
<img
|
||||||
@ -74,5 +132,71 @@ export const Text = ({ currentQuestion }: TextProps) => {
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TextSpecial = ({currentQuestion, answer, inputHC, stepNumber}: Props) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMobile = useRootContainerSize() < 650;
|
||||||
|
const isHorizontal = Orientation[Number(stepNumber) -1].horizontal
|
||||||
|
return(
|
||||||
|
<Box sx={{display: "flex", flexDirection: isMobile? "column" : undefined, alignItems: isMobile ? "center" : undefined,}}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "20px",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "20px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
||||||
|
{isHorizontal && currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
||||||
|
<Box sx={{margin: "30px", width: "50vw", maxHeight: "550px" }}>
|
||||||
|
<img
|
||||||
|
key={currentQuestion.id}
|
||||||
|
src={currentQuestion.content.back}
|
||||||
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{
|
||||||
|
//@ts-ignore
|
||||||
|
(<TextField
|
||||||
|
autoFocus={true}
|
||||||
|
multiline
|
||||||
|
maxRows={4}
|
||||||
|
placeholder={currentQuestion.content.placeholder}
|
||||||
|
//@ts-ignore
|
||||||
|
value={answer || ""}
|
||||||
|
onChange={async ({ target }:ChangeEvent<HTMLInputElement>) => {
|
||||||
|
updateAnswer(currentQuestion.id, target.value, 0);
|
||||||
|
inputHC(target.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputProps={{maxLength:400}}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
"&:focus-visible": {
|
||||||
|
borderColor: theme.palette.primary.main
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>)
|
||||||
|
}
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
{!isHorizontal && currentQuestion.content.back && currentQuestion.content.back !== " " && (
|
||||||
|
<Box sx={{margin: "15px", width: "40vw" }}>
|
||||||
|
<img
|
||||||
|
key={currentQuestion.id}
|
||||||
|
src={currentQuestion.content.back}
|
||||||
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
@ -38,16 +38,6 @@ type VariantProps = {
|
|||||||
currentQuestion: QuizQuestionVariant;
|
currentQuestion: QuizQuestionVariant;
|
||||||
};
|
};
|
||||||
|
|
||||||
type VariantItemProps = {
|
|
||||||
currentQuestion: QuizQuestionVariant;
|
|
||||||
variant: QuestionVariant;
|
|
||||||
answer: string | string[] | undefined;
|
|
||||||
index: number;
|
|
||||||
own?: boolean;
|
|
||||||
readySend: boolean;
|
|
||||||
setReadySend: (a: boolean) => void
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Variant = ({ currentQuestion }: VariantProps) => {
|
export const Variant = ({ currentQuestion }: VariantProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
@ -60,7 +50,7 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
|
|||||||
(variant) => variant.id === currentQuestion.id
|
(variant) => variant.id === currentQuestion.id
|
||||||
);
|
);
|
||||||
|
|
||||||
const [readySend, setReadySend] = useState(true)
|
const [isSending, setIsSending] = useState(false);
|
||||||
|
|
||||||
const Group = currentQuestion.content.multi ? FormGroup : RadioGroup;
|
const Group = currentQuestion.content.multi ? FormGroup : RadioGroup;
|
||||||
|
|
||||||
@ -109,8 +99,8 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
answer={answer}
|
answer={answer}
|
||||||
index={index}
|
index={index}
|
||||||
readySend={readySend}
|
isSending={isSending}
|
||||||
setReadySend={setReadySend}
|
setIsSending={setIsSending}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{currentQuestion.content.own && ownVariant && (
|
{currentQuestion.content.own && ownVariant && (
|
||||||
@ -121,8 +111,8 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
answer={answer}
|
answer={answer}
|
||||||
index={currentQuestion.content.variants.length + 2}
|
index={currentQuestion.content.variants.length + 2}
|
||||||
readySend={readySend}
|
isSending={isSending}
|
||||||
setReadySend={setReadySend}
|
setIsSending={setIsSending}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
@ -148,15 +138,24 @@ const VariantItem = ({
|
|||||||
answer,
|
answer,
|
||||||
index,
|
index,
|
||||||
own = false,
|
own = false,
|
||||||
readySend,
|
isSending,
|
||||||
setReadySend
|
setIsSending,
|
||||||
}: VariantItemProps) => {
|
}: {
|
||||||
|
currentQuestion: QuizQuestionVariant;
|
||||||
|
variant: QuestionVariant;
|
||||||
|
answer: string | string[] | undefined;
|
||||||
|
index: number;
|
||||||
|
own?: boolean;
|
||||||
|
isSending: boolean;
|
||||||
|
setIsSending: (a: boolean) => void;
|
||||||
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings, quizId } = useQuizData();
|
const { settings, quizId } = useQuizData();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
key={variant.id}
|
key={variant.id}
|
||||||
|
disabled={isSending}
|
||||||
sx={{
|
sx={{
|
||||||
margin: "0",
|
margin: "0",
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
@ -205,74 +204,75 @@ const VariantItem = ({
|
|||||||
label={own ? <TextField label="Другое..." /> : variant.answer}
|
label={own ? <TextField label="Другое..." /> : variant.answer}
|
||||||
onClick={async (event) => {
|
onClick={async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (readySend) {
|
if (isSending) return;
|
||||||
setReadySend(false)
|
|
||||||
const variantId = currentQuestion.content.variants[index].id;
|
|
||||||
console.log(answer);
|
|
||||||
|
|
||||||
if (currentQuestion.content.multi) {
|
setIsSending(true);
|
||||||
const currentAnswer = typeof answer !== "string" ? answer || [] : [];
|
const variantId = currentQuestion.content.variants[index].id;
|
||||||
|
console.log(answer);
|
||||||
|
|
||||||
try {
|
if (currentQuestion.content.multi) {
|
||||||
await sendAnswer({
|
const currentAnswer = typeof answer !== "string" ? answer || [] : [];
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: currentAnswer.includes(variantId)
|
|
||||||
? currentAnswer?.filter((item) => item !== variantId)
|
|
||||||
: [...currentAnswer, variantId],
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
|
|
||||||
updateAnswer(
|
|
||||||
currentQuestion.id,
|
|
||||||
currentAnswer.includes(variantId)
|
|
||||||
? currentAnswer?.filter((item) => item !== variantId)
|
|
||||||
: [...currentAnswer, variantId],
|
|
||||||
currentQuestion.content.variants[index].points || 0
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: currentQuestion.content.variants[index].answer,
|
body: currentAnswer.includes(variantId)
|
||||||
|
? currentAnswer?.filter((item) => item !== variantId)
|
||||||
|
: [...currentAnswer, variantId],
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAnswer(currentQuestion.id, variantId,
|
updateAnswer(
|
||||||
answer === variantId ? 0
|
currentQuestion.id,
|
||||||
:
|
currentAnswer.includes(variantId)
|
||||||
currentQuestion.content.variants[index].points || 0
|
? currentAnswer?.filter((item) => item !== variantId)
|
||||||
|
: [...currentAnswer, variantId],
|
||||||
|
currentQuestion.content.variants[index].points || 0
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (answer === variantId) {
|
setIsSending(false);
|
||||||
try {
|
return;
|
||||||
|
|
||||||
await sendAnswer({
|
|
||||||
questionId: currentQuestion.id,
|
|
||||||
body: "",
|
|
||||||
qid: quizId,
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
|
||||||
}
|
|
||||||
deleteAnswer(currentQuestion.id);
|
|
||||||
}
|
|
||||||
setReadySend(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sendAnswer({
|
||||||
|
questionId: currentQuestion.id,
|
||||||
|
body: currentQuestion.content.variants[index].answer,
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
|
||||||
|
updateAnswer(currentQuestion.id, variantId,
|
||||||
|
answer === variantId ? 0
|
||||||
|
:
|
||||||
|
currentQuestion.content.variants[index].points || 0
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (answer === variantId) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
await sendAnswer({
|
||||||
|
questionId: currentQuestion.id,
|
||||||
|
body: "",
|
||||||
|
qid: quizId,
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
|
}
|
||||||
|
deleteAnswer(currentQuestion.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -18,6 +18,7 @@ import { quizThemes } from "@utils/themes/Publication/themePublication";
|
|||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
import { useRootContainerSize } from "../../../contexts/RootContainerWidthContext";
|
import { useRootContainerSize } from "../../../contexts/RootContainerWidthContext";
|
||||||
import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
|
import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
type VarimgProps = {
|
type VarimgProps = {
|
||||||
currentQuestion: QuizQuestionVarImg;
|
currentQuestion: QuizQuestionVarImg;
|
||||||
@ -28,6 +29,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
|||||||
const { answers } = useQuizViewStore();
|
const { answers } = useQuizViewStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useRootContainerSize() < 650;
|
const isMobile = useRootContainerSize() < 650;
|
||||||
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
const { answer } =
|
const { answer } =
|
||||||
answers.find(
|
answers.find(
|
||||||
@ -39,7 +41,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.text.primary} sx={{wordBreak: "break-word"}}>{currentQuestion.title}</Typography>
|
<Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
marginTop: "20px",
|
marginTop: "20px",
|
||||||
@ -66,6 +68,7 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
|||||||
{currentQuestion.content.variants.map((variant, index) => (
|
{currentQuestion.content.variants.map((variant, index) => (
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
key={variant.id}
|
key={variant.id}
|
||||||
|
disabled={isSending}
|
||||||
sx={{
|
sx={{
|
||||||
marginBottom: "15px",
|
marginBottom: "15px",
|
||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
@ -88,14 +91,13 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
|||||||
"&::-webkit-scrollbar-thumb": {
|
"&::-webkit-scrollbar-thumb": {
|
||||||
backgroundColor: "#b8babf",
|
backgroundColor: "#b8babf",
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}}
|
}}
|
||||||
value={index}
|
value={index}
|
||||||
onClick={async (event) => {
|
onClick={async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
setIsSending(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
@ -129,6 +131,8 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
|||||||
}
|
}
|
||||||
deleteAnswer(currentQuestion.id);
|
deleteAnswer(currentQuestion.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
control={
|
control={
|
||||||
<Radio checkedIcon={<RadioCheck color={theme.palette.primary.main} />} icon={<RadioIcon />} />
|
<Radio checkedIcon={<RadioCheck color={theme.palette.primary.main} />} icon={<RadioIcon />} />
|
||||||
@ -165,20 +169,20 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => {
|
|||||||
) : (
|
) : (
|
||||||
<BlankImage />
|
<BlankImage />
|
||||||
)
|
)
|
||||||
) : currentQuestion.content.back !== " "
|
) : currentQuestion.content.back !== " "
|
||||||
&& currentQuestion.content.back !== null
|
&& currentQuestion.content.back !== null
|
||||||
&& currentQuestion.content.back.length > 0
|
&& currentQuestion.content.back.length > 0
|
||||||
? (
|
? (
|
||||||
<img
|
<img
|
||||||
src={currentQuestion.content.back}
|
src={currentQuestion.content.back}
|
||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
) : (currentQuestion.content.replText !== " " && currentQuestion.content.replText.length > 0) ? currentQuestion.content.replText : variant?.extendedText || isMobile ? (
|
) : (currentQuestion.content.replText !== " " && currentQuestion.content.replText.length > 0) ? currentQuestion.content.replText : variant?.extendedText || isMobile ? (
|
||||||
"Выберите вариант ответа ниже"
|
"Выберите вариант ответа ниже"
|
||||||
) : (
|
) : (
|
||||||
"Выберите вариант ответа слева"
|
"Выберите вариант ответа слева"
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
{/* )} */}
|
{/* )} */}
|
||||||
|
@ -20,6 +20,7 @@ type SelectProps = {
|
|||||||
colorMain?: string;
|
colorMain?: string;
|
||||||
colorPlaceholder?: string;
|
colorPlaceholder?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Select = ({
|
export const Select = ({
|
||||||
@ -31,6 +32,7 @@ export const Select = ({
|
|||||||
placeholder = "",
|
placeholder = "",
|
||||||
colorMain = "#7E2AEA",
|
colorMain = "#7E2AEA",
|
||||||
colorPlaceholder = "#9A9AAF",
|
colorPlaceholder = "#9A9AAF",
|
||||||
|
disabled = false,
|
||||||
}: SelectProps) => {
|
}: SelectProps) => {
|
||||||
const [activeItem, setActiveItem] = useState<number>(
|
const [activeItem, setActiveItem] = useState<number>(
|
||||||
empty ? -1 : activeItemIndex
|
empty ? -1 : activeItemIndex
|
||||||
@ -57,6 +59,7 @@ export const Select = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl
|
<FormControl
|
||||||
|
disabled={disabled}
|
||||||
fullWidth
|
fullWidth
|
||||||
size="small"
|
size="small"
|
||||||
sx={{ width: "100%", height: "48px", ...sx }}
|
sx={{ width: "100%", height: "48px", ...sx }}
|
||||||
|
@ -48,6 +48,7 @@ export type QuizSettings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface QuizConfig {
|
export interface QuizConfig {
|
||||||
|
spec: undefined | true,
|
||||||
type: QuizType;
|
type: QuizType;
|
||||||
noStartPage: boolean;
|
noStartPage: boolean;
|
||||||
startpageType: QuizStartpageType;
|
startpageType: QuizStartpageType;
|
||||||
|
5290
pub.js
5290
pub.js
File diff suppressed because one or more lines are too long
@ -7,7 +7,7 @@ import QuizAnswerer from "../lib/components/QuizAnswerer";
|
|||||||
import { ApologyPage } from "../lib/components/ViewPublicationPage/ApologyPage";
|
import { ApologyPage } from "../lib/components/ViewPublicationPage/ApologyPage";
|
||||||
|
|
||||||
// const defaultQuizId = "45ef7f9c-784d-4e58-badb-f6b337f08ba0"; // branching
|
// const defaultQuizId = "45ef7f9c-784d-4e58-badb-f6b337f08ba0"; // branching
|
||||||
const defaultQuizId = "cde381db-8ccb-402c-b55f-2c814be9bf25"; //looooong header
|
const defaultQuizId = "26f2e98b-06ac-4e6c-b82e-0793e2768310"; //looooong header
|
||||||
// const defaultQuizId = "ad7f5a87-b833-4f5b-854e-453706ed655c"; // linear
|
// const defaultQuizId = "ad7f5a87-b833-4f5b-854e-453706ed655c"; // linear
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
Loading…
Reference in New Issue
Block a user