diff --git a/lib/components/ViewPublicationPage/Footer.tsx b/lib/components/ViewPublicationPage/Footer.tsx index ee5203e..0f9a6fb 100644 --- a/lib/components/ViewPublicationPage/Footer.tsx +++ b/lib/components/ViewPublicationPage/Footer.tsx @@ -16,6 +16,9 @@ export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => { const { questions, settings } = useQuizSettings(); const questionsAmount = questions.filter(({ type }) => type !== "result").length; + console.log("questions"); + console.log(questions); + return ( { Вопрос {stepNumber} из {questionsAmount} - + )} {prevButton} diff --git a/lib/components/ViewPublicationPage/ViewPublicationPage.tsx b/lib/components/ViewPublicationPage/ViewPublicationPage.tsx index f6fe595..8f85cb6 100644 --- a/lib/components/ViewPublicationPage/ViewPublicationPage.tsx +++ b/lib/components/ViewPublicationPage/ViewPublicationPage.tsx @@ -20,8 +20,9 @@ import NextButton from "./tools/NextButton"; import PrevButton from "./tools/PrevButton"; export default function ViewPublicationPage() { - const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizSettings(); + const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle, questions } = useQuizSettings(); const answers = useQuizViewStore((state) => state.answers); + const ownVariants = useQuizViewStore((state) => state.ownVariants); let currentQuizStep = useQuizViewStore((state) => state.currentQuizStep); const { currentQuestion, @@ -99,7 +100,7 @@ export default function ViewPublicationPage() { if (preview) return; - sendQuestionAnswer(quizId, currentQuestion, currentAnswer)?.catch((e) => { + sendQuestionAnswer(quizId, currentQuestion, currentAnswer, ownVariants)?.catch((e) => { enqueueSnackbar("Ошибка при отправке ответа"); console.error("Error sending answer", e); }); diff --git a/lib/components/ViewPublicationPage/questions/Images/ImageVariant.tsx b/lib/components/ViewPublicationPage/questions/Images/ImageVariant.tsx index f5ce58c..986ad34 100644 --- a/lib/components/ViewPublicationPage/questions/Images/ImageVariant.tsx +++ b/lib/components/ViewPublicationPage/questions/Images/ImageVariant.tsx @@ -1,6 +1,7 @@ +import { CheckboxIcon } from "@/assets/icons/Checkbox"; import type { QuestionVariant } from "@/model/questionTypes/shared"; import { useQuizSettings } from "@contexts/QuizDataContext"; -import { Box, FormControlLabel, Radio, useTheme } from "@mui/material"; +import { Box, Checkbox, FormControlLabel, Radio, useTheme } from "@mui/material"; import { useQuizViewStore } from "@stores/quizView"; import RadioCheck from "@ui_kit/RadioCheck"; import RadioIcon from "@ui_kit/RadioIcon"; @@ -11,35 +12,46 @@ type ImagesProps = { questionId: string; variant: QuestionVariant; index: number; + isMulti: boolean; + answer: string | string[] | undefined; }; -export const ImageVariant = ({ questionId, variant, index }: ImagesProps) => { +export const ImageVariant = ({ questionId, answer, isMulti, variant, index }: ImagesProps) => { const { settings } = useQuizSettings(); - const answers = useQuizViewStore((state) => state.answers); const { deleteAnswer, updateAnswer } = useQuizViewStore((state) => state); const theme = useTheme(); - const answer = answers.find((answer) => answer.questionId === questionId)?.answer; + const answers = useQuizViewStore((state) => state.answers); const onVariantClick = async (event: MouseEvent) => { event.preventDefault(); - updateAnswer(questionId, variant.id, variant.points || 0); + const variantId = variant.id; + if (isMulti) { + const currentAnswer = typeof answer !== "string" ? answer || [] : []; - if (answer === variant.id) { + return updateAnswer( + questionId, + currentAnswer.includes(variantId) + ? currentAnswer?.filter((item) => item !== variantId) + : [...currentAnswer, variantId], + variant.points || 0 + ); + } + + updateAnswer(questionId, variantId, variant.points || 0); + + if (answer === variantId) { deleteAnswer(questionId); } }; - console.log("answers"); - console.log(answers); - return ( { }} value={index} control={ - } - icon={} - sx={{ - position: "absolute", - top: "-297px", - right: 0, - }} - /> + isMulti ? ( + } + icon={} + sx={{ + position: "absolute", + top: "-297px", + right: 0, + }} + /> + ) : ( + } + icon={} + sx={{ + position: "absolute", + top: "-297px", + right: 0, + }} + /> + ) } label={variant.answer} /> diff --git a/lib/components/ViewPublicationPage/questions/Images/index.tsx b/lib/components/ViewPublicationPage/questions/Images/index.tsx index 438ce08..29c327e 100644 --- a/lib/components/ViewPublicationPage/questions/Images/index.tsx +++ b/lib/components/ViewPublicationPage/questions/Images/index.tsx @@ -3,6 +3,7 @@ import type { QuizQuestionImages } from "@model/questionTypes/images"; import { Box, RadioGroup, Typography, useTheme } from "@mui/material"; import { createQuizViewStore, useQuizViewStore } from "@stores/quizView"; import { ImageVariant } from "./ImageVariant"; +import moment from "moment"; type ImagesProps = { currentQuestion: QuizQuestionImages; @@ -14,10 +15,11 @@ export const Images = ({ currentQuestion }: ImagesProps) => { const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer; const isTablet = useRootContainerSize() < 1000; const isMobile = useRootContainerSize() < 500; - const a = createQuizViewStore().getState(); + console.log(currentQuestion); - console.log("store"); - console.log(a); + + if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question"); + return ( { questionId={currentQuestion.id} variant={variant} index={index} + answer={answer} + isMulti={Boolean(currentQuestion.content.multi)} /> ))} diff --git a/lib/components/ViewPublicationPage/questions/Variant/VariantItem.tsx b/lib/components/ViewPublicationPage/questions/Variant/VariantItem.tsx index 3835ed8..9195bfc 100644 --- a/lib/components/ViewPublicationPage/questions/Variant/VariantItem.tsx +++ b/lib/components/ViewPublicationPage/questions/Variant/VariantItem.tsx @@ -93,15 +93,10 @@ export const VariantItem = ({ labelPlacement="start" control={ isMulti ? ( - - } - icon={} + checkedIcon={} + icon={} /> ) : ( void; + questionOwn: boolean; + questionLargeCheck: boolean; + isMulti: boolean; + answer: string | string[] | undefined; }; -export const VarimgVariant = ({ questionId, variant, index, isSending, setIsSending }: VarimgVariantProps) => { +interface OwnInputProps { + questionId: string; + variant: QuestionVariant; + largeCheck: boolean; +} +const OwnInput = ({ questionId, variant, largeCheck }: OwnInputProps) => { + const theme = useTheme(); + const ownVariants = useQuizViewStore((state) => state.ownVariants); + const { updateOwnVariant } = useQuizViewStore((state) => state); + + const ownAnswer = ownVariants[ownVariants.findIndex((v) => v.id === variant.id)].variant.answer || ""; + + return largeCheck ? ( + ) => e.stopPropagation()} + onChange={(e: React.ChangeEvent) => { + updateOwnVariant(variant.id, e.target.value); + }} + /> + ) : ( + ) => e.stopPropagation()} + onChange={(e: React.ChangeEvent) => { + updateOwnVariant(variant.id, e.target.value); + }} + /> + ); +}; + +export const VarimgVariant = ({ + questionId, + variant, + index, + isSending, + setIsSending, + questionOwn, + questionLargeCheck, + answer, +}: VarimgVariantProps) => { const { settings } = useQuizSettings(); const { updateAnswer, deleteAnswer } = useQuizViewStore((state) => state); - const answers = useQuizViewStore((state) => state.answers); const theme = useTheme(); - const { answer } = answers.find((answer) => answer.questionId === questionId) ?? {}; - const sendVariant = async (event: MouseEvent) => { event.preventDefault(); @@ -61,6 +120,7 @@ export const VarimgVariant = ({ questionId, variant, index, isSending, setIsSend height: variant.answer.length <= 60 ? undefined : "60px", overflow: "auto", lineHeight: "normal", + width: "100%", "&::-webkit-scrollbar": { width: "4px" }, "&::-webkit-scrollbar-thumb": { backgroundColor: "#b8babf" }, }, @@ -71,7 +131,17 @@ export const VarimgVariant = ({ questionId, variant, index, isSending, setIsSend labelPlacement="start" value={index} onClick={sendVariant} - label={variant.answer} + label={ + variant?.isOwn ? ( + + ) : ( + variant.answer + ) + } control={ } diff --git a/lib/components/ViewPublicationPage/questions/Varimg/index.tsx b/lib/components/ViewPublicationPage/questions/Varimg/index.tsx index d0f9c3b..eb3473c 100644 --- a/lib/components/ViewPublicationPage/questions/Varimg/index.tsx +++ b/lib/components/ViewPublicationPage/questions/Varimg/index.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Box, RadioGroup, Typography, useTheme } from "@mui/material"; import { VarimgVariant } from "./VarimgVariant"; @@ -9,6 +9,7 @@ import { useRootContainerSize } from "@contexts/RootContainerWidthContext"; import BlankImage from "@icons/BlankImage"; import type { QuizQuestionVarImg } from "@model/questionTypes/varimg"; +import moment from "moment"; type VarimgProps = { currentQuestion: QuizQuestionVarImg; @@ -17,13 +18,25 @@ type VarimgProps = { export const Varimg = ({ currentQuestion }: VarimgProps) => { const [isSending, setIsSending] = useState(false); const answers = useQuizViewStore((state) => state.answers); + const ownVariants = useQuizViewStore((state) => state.ownVariants); + const updateOwnVariant = useQuizViewStore((state) => state.updateOwnVariant); const theme = useTheme(); const isMobile = useRootContainerSize() < 650; const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.id) ?? {}; + const ownVariant = ownVariants.find((variant) => variant.id === currentQuestion.id); const variant = currentQuestion.content.variants.find(({ id }) => answer === id); + useEffect(() => { + if (!ownVariant) { + updateOwnVariant(currentQuestion.id, ""); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + if (moment.isMoment(answer)) throw new Error("Answer is Moment in Variant question"); + return ( { isSending={isSending} setIsSending={setIsSending} index={index} + questionOwn={currentQuestion.content.own} + questionLargeCheck={currentQuestion.content.largeCheck} + isMulti={Boolean(currentQuestion.content.multi)} + answer={answer} /> ))} diff --git a/lib/model/questionTypes/shared.ts b/lib/model/questionTypes/shared.ts index 6f77a51..1235145 100644 --- a/lib/model/questionTypes/shared.ts +++ b/lib/model/questionTypes/shared.ts @@ -43,6 +43,8 @@ export type QuestionVariant = { hints: string; /** Дополнительное поле для текста, emoji, ссылки на картинку */ extendedText: string; + isOwn?: boolean; + isMulti?: boolean; /** Оригинал изображения (до кропа) */ originalImageUrl: string; points?: number; diff --git a/lib/stores/quizView.ts b/lib/stores/quizView.ts index 8dca52c..06078ae 100644 --- a/lib/stores/quizView.ts +++ b/lib/stores/quizView.ts @@ -14,7 +14,7 @@ export type QuestionAnswer = { answer: Answer; }; -type OwnVariant = { +export type OwnVariant = { id: string; variant: QuestionVariant; }; @@ -57,10 +57,7 @@ export const createQuizViewStore = () => updateAnswer(questionId, answer, points) { set( (state) => { - console.log(state); const index = state.answers.findIndex((answer) => questionId === answer.questionId); - console.log("state"); - console.log(state.answers); if (index < 0) { state.answers.push({ questionId, answer }); @@ -98,11 +95,11 @@ export const createQuizViewStore = () => (state) => { const index = state.ownVariants.findIndex((variant) => variant.id === id); - if (index < 0) { + if (index < 0 || !index) { state.ownVariants.push({ id, variant: { - id: nanoid(), + id: id, answer, extendedText: "", hints: "", diff --git a/lib/utils/sendQuestionAnswer.ts b/lib/utils/sendQuestionAnswer.ts index f603794..9cd6684 100644 --- a/lib/utils/sendQuestionAnswer.ts +++ b/lib/utils/sendQuestionAnswer.ts @@ -1,13 +1,14 @@ import { sendAnswer } from "@/api/quizRelase"; import { RealTypedQuizQuestion } from "@/model/questionTypes/shared"; -import { QuestionAnswer } from "@/stores/quizView"; +import { OwnVariant, QuestionAnswer, createQuizViewStore } from "@/stores/quizView"; import moment from "moment"; import { notReachable } from "./notReachable"; export function sendQuestionAnswer( quizId: string, question: RealTypedQuizQuestion, - questionAnswer: QuestionAnswer | undefined + questionAnswer: QuestionAnswer | undefined, + ownVariants: OwnVariant[] ) { if (!questionAnswer) { return sendAnswer({ @@ -40,7 +41,32 @@ export function sendQuestionAnswer( return; } case "images": { + if (question.content.multi) { + const answer = questionAnswer.answer; + if (!Array.isArray(answer)) throw new Error("Cannot send answer in select question"); + + //Оставляем только выбранные варианты + const selectedVariants = question.content.variants.filter((v) => answer.includes(v.id)); + + let answerString = ``; + selectedVariants.forEach((variant) => { + const body = JSON.stringify({ + Image: variant.extendedText, + Description: variant.answer, + }); + answerString += `\`${body}\`,`; + }); + answerString = answerString.slice(0, -1); + + return sendAnswer({ + questionId: question.id, + body: answerString, + qid: quizId, + }); + } + const variant = question.content.variants.find((v) => v.id === questionAnswer.answer); + if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`); const body = { Image: variant.extendedText, @@ -101,12 +127,9 @@ export function sendQuestionAnswer( const answer = questionAnswer.answer; if (!Array.isArray(answer)) throw new Error("Cannot send answer in select question"); - console.log("до фильтра"); - console.log(question.content.variants); //Оставляем только выбранные варианты const selectedVariants = question.content.variants.filter((v) => answer.includes(v.id)); - console.log("после фильтра"); - console.log(selectedVariants); + let answerString = ``; selectedVariants.forEach((e) => { answerString += `\`${e.answer}\`,`; @@ -116,7 +139,6 @@ export function sendQuestionAnswer( return sendAnswer({ questionId: question.id, body: answerString, - // body: selectedVariants.map((v) => v.answer).join(", "), qid: quizId, }); } @@ -132,10 +154,13 @@ export function sendQuestionAnswer( } case "varimg": { const variant = question.content.variants.find((v) => v.id === questionAnswer.answer); + const ownAnswer = + ownVariants[ownVariants.findIndex((variant) => variant.id === questionAnswer.answer)].variant.answer || ""; + if (!variant) throw new Error(`Cannot find variant with id ${questionAnswer.answer} in question ${question.id}`); const body = { Image: variant.extendedText, - Description: variant.answer, + Description: question.content.own ? ownAnswer : variant.answer, }; if (!body) throw new Error(`Body of answer in question ${question.id} is undefined`);