Merge branch 'dev' into startpage-preview-fix

This commit is contained in:
Nastya 2023-12-12 19:02:26 +03:00
commit 24e6084d48
12 changed files with 448 additions and 520 deletions

@ -216,6 +216,7 @@ function CsComponent({
} }
} }
const removeNode = ({ targetNodeContentId }: { targetNodeContentId: string }) => { const removeNode = ({ targetNodeContentId }: { targetNodeContentId: string }) => {
const deleteNodes = [] as string[] const deleteNodes = [] as string[]
const deleteEdges: any = [] const deleteEdges: any = []
@ -331,6 +332,7 @@ function CsComponent({
} }
useEffect(() => { useEffect(() => {
if (startCreate) { if (startCreate) {
addNode({ parentNodeContentId: startCreate }); addNode({ parentNodeContentId: startCreate });
@ -348,7 +350,6 @@ function CsComponent({
const readyLO = (e) => { const readyLO = (e) => {
console.log('REAdy')
if (e.cy.data('firstNode') === 'nonroot') { if (e.cy.data('firstNode') === 'nonroot') {
e.cy.data('firstNode', 'root') e.cy.data('firstNode', 'root')
e.cy.nodes().sort((a, b) => (a.data('root') ? 1 : -1)).layout(lyopts).run() e.cy.nodes().sort((a, b) => (a.data('root') ? 1 : -1)).layout(lyopts).run()
@ -433,7 +434,6 @@ function CsComponent({
task.task.forEach(n => { task.task.forEach(n => {
const width = n.data('subtreeWidth') const width = n.data('subtreeWidth')
console.log('ORORORORO', n.data(), yoffset, width, oldPos, task.parent.data('subtreeWidth'))
n.data('oldPos', { x: 250 * n.data('layer'), y: yoffset + width / 2 }) n.data('oldPos', { x: 250 * n.data('layer'), y: yoffset + width / 2 })
yoffset += width yoffset += width
queue.push({ task: n.cy().edges(`[source="${n.id()}"]`).targets(), parent: n }) queue.push({ task: n.cy().edges(`[source="${n.id()}"]`).targets(), parent: n })
@ -462,7 +462,6 @@ function CsComponent({
} }
useEffect(() => { useEffect(() => {
console.log('KEKEKE')
document.querySelector("#root")?.addEventListener("mouseup", cleardragQuestionContentId); document.querySelector("#root")?.addEventListener("mouseup", cleardragQuestionContentId);
const cy = cyRef.current; const cy = cyRef.current;
const eles = cy?.add(storeToNodes(questions.filter((question: AnyTypedQuizQuestion) => (question.type !== "result" && question.type !== null)))) const eles = cy?.add(storeToNodes(questions.filter((question: AnyTypedQuizQuestion) => (question.type !== "result" && question.type !== null))))
@ -510,7 +509,6 @@ function CsComponent({
if (!container) { if (!container) {
return; return;
} }
console.log('POP')
container.style.overflow = "hidden"; container.style.overflow = "hidden";
@ -540,7 +538,6 @@ function CsComponent({
const bb = n.boundingBox() const bb = n.boundingBox()
return bb.x2 > ext.x1 && bb.x1 < ext.x2 && bb.y2 > ext.y1 && bb.y1 < ext.y2 return bb.x2 > ext.x1 && bb.x1 < ext.x2 && bb.y2 > ext.y1 && bb.y1 < ext.y2
}) })
console.log('POPE')
nodesInView nodesInView
.toArray() .toArray()
@ -553,7 +550,6 @@ function CsComponent({
modifiers: [{ name: "flip", options: { boundary: node } }], modifiers: [{ name: "flip", options: { boundary: node } }],
}, },
content: ([item]) => { content: ([item]) => {
console.log('POPPER', item.id())
const itemId = item.id(); const itemId = item.id();
const itemElement = layoutsContainer.current?.querySelector( const itemElement = layoutsContainer.current?.querySelector(
`.popper-layout[data-id='${itemId}']` `.popper-layout[data-id='${itemId}']`
@ -583,7 +579,6 @@ function CsComponent({
modifiers: [{ name: "flip", options: { boundary: node } }], modifiers: [{ name: "flip", options: { boundary: node } }],
}, },
content: ([item]) => { content: ([item]) => {
console.log('POPPER+', item.id())
const itemId = item.id(); const itemId = item.id();
const itemElement = plusesContainer.current?.querySelector( const itemElement = plusesContainer.current?.querySelector(
`.popper-plus[data-id='${itemId}']` `.popper-plus[data-id='${itemId}']`
@ -612,7 +607,6 @@ function CsComponent({
modifiers: [{ name: "flip", options: { boundary: node } }], modifiers: [{ name: "flip", options: { boundary: node } }],
}, },
content: ([item]) => { content: ([item]) => {
console.log('POPPERx', item.id())
const itemId = item.id(); const itemId = item.id();
const itemElement = crossesContainer.current?.querySelector( const itemElement = crossesContainer.current?.querySelector(
`.popper-cross[data-id='${itemId}']` `.popper-cross[data-id='${itemId}']`
@ -643,11 +637,7 @@ function CsComponent({
modifiers: [{ name: "flip", options: { boundary: node } }], modifiers: [{ name: "flip", options: { boundary: node } }],
}, },
content: ([item]) => { content: ([item]) => {
console.log('POPPERg', item.id())
const itemId = item.id(); const itemId = item.id();
if (item.cy().edges(`[target="${itemId}"]`).sources().length === 0) {
return;
}
const itemElement = gearsContainer.current?.querySelector( const itemElement = gearsContainer.current?.querySelector(
`.popper-gear[data-id='${itemId}']` `.popper-gear[data-id='${itemId}']`
@ -670,7 +660,6 @@ function CsComponent({
}); });
const update = async () => { const update = async () => {
console.log('POPPERi=u', item.id())
await plusesPopper.update(); await plusesPopper.update();
await crossesPopper.update(); await crossesPopper.update();
await gearsPopper.update(); await gearsPopper.update();
@ -696,6 +685,18 @@ function CsComponent({
{ name: "offset", options: { offset: [0, -130 * zoom] } }, { name: "offset", options: { offset: [0, -130 * zoom] } },
], ],
}); });
plusesPopper.setOptions({
modifiers: [
{ name: "flip", options: { boundary: node } },
{ name: "offset", options: { offset: [0, 0 * zoom] } },
],
});
gearsPopper.setOptions({
modifiers: [
{ name: "flip", options: { boundary: node } },
{ name: "offset", options: { offset: [0, 0] } },
],
});
layoutsContainer.current layoutsContainer.current
?.querySelectorAll("#popper-layouts > .popper-layout") ?.querySelectorAll("#popper-layouts > .popper-layout")
@ -735,13 +736,13 @@ function CsComponent({
}; };
//node?.on("position", update); //node?.on("position", update);
let pressed = false let pressed = false
let hide = false let hide = false
cy?.on('mousedown',() => {pressed = true}) cy?.on('mousedown', () => { pressed = true })
cy?.on('mouseup',() => { cy?.on('mouseup', () => {
pressed = false pressed = false
hide = false hide = false
const gc = gearsContainer.current const gc = gearsContainer.current
if (gc) gc.style.display = 'block' if (gc) gc.style.display = 'block'
@ -751,23 +752,23 @@ let pressed = false
if (pc) pc.style.display = 'block' if (pc) pc.style.display = 'block'
if (xc) xc.style.display = 'block' if (xc) xc.style.display = 'block'
if (lc) lc.style.display = 'block' if (lc) lc.style.display = 'block'
update() update()
}) })
cy?.on('mousemove',() => { cy?.on('mousemove', () => {
if (pressed && !hide) { if (pressed && !hide) {
hide = true hide = true
const gc = gearsContainer.current const gc = gearsContainer.current
if (gc) gc.style.display = 'none' if (gc) gc.style.display = 'none'
const pc = plusesContainer.current const pc = plusesContainer.current
const xc = crossesContainer.current const xc = crossesContainer.current
const lc = layoutsContainer.current const lc = layoutsContainer.current
if (pc) pc.style.display = 'none' if (pc) pc.style.display = 'none'
if (xc) xc.style.display = 'none' if (xc) xc.style.display = 'none'
if (lc) lc.style.display = 'block' if (lc) lc.style.display = 'block'
} }
}); });
cy?.on("zoom render", onZoom); cy?.on("zoom render", onZoom);
}); });
}; };
@ -785,7 +786,7 @@ let pressed = false
variant="text" variant="text"
onClick={() => { onClick={() => {
//код сюда cyRef.current?.fit()
}} }}
> >

@ -1,6 +1,6 @@
import { Box } from "@mui/material" import { Box } from "@mui/material"
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { updateDragQuestionContentId, updateQuestion } from "@root/questions/actions" import { deleteQuestion, updateDragQuestionContentId, updateQuestion } from "@root/questions/actions"
import { updateRootContentId } from "@root/quizes/actions" import { updateRootContentId } from "@root/quizes/actions"
import { useCurrentQuiz } from "@root/quizes/hooks" import { useCurrentQuiz } from "@root/quizes/hooks"
import { useQuestionsStore } from "@root/questions/store" import { useQuestionsStore } from "@root/questions/store"
@ -11,8 +11,9 @@ interface Props {
modalQuestionTargetContentId: string; modalQuestionTargetContentId: string;
} }
export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetContentId }: Props) => { export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetContentId }: Props) => {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { dragQuestionContentId } = useQuestionsStore() const { dragQuestionContentId, questions } = useQuestionsStore()
const Container = useRef<HTMLDivElement | null>(null); const Container = useRef<HTMLDivElement | null>(null);
const modalOpen = () => setOpenedModalQuestions(true) const modalOpen = () => setOpenedModalQuestions(true)
@ -22,6 +23,11 @@ export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetCon
if (dragQuestionContentId) { if (dragQuestionContentId) {
updateRootContentId(quiz?.id, dragQuestionContentId) updateRootContentId(quiz?.id, dragQuestionContentId)
updateQuestion(dragQuestionContentId, (question) => question.content.rule.parentId = "root") updateQuestion(dragQuestionContentId, (question) => question.content.rule.parentId = "root")
//если были результаты - удалить
questions.forEach((q) => {
if (q.type === 'result') deleteQuestion(q.id)
})
} }
} else { } else {
enqueueSnackbar("Нет информации о взятом опроснике") enqueueSnackbar("Нет информации о взятом опроснике")
@ -44,6 +50,10 @@ export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetCon
if (modalQuestionTargetContentId) { if (modalQuestionTargetContentId) {
updateRootContentId(quiz?.id, modalQuestionTargetContentId) updateRootContentId(quiz?.id, modalQuestionTargetContentId)
updateQuestion(modalQuestionTargetContentId, (question) => question.content.rule.parentId = "root") updateQuestion(modalQuestionTargetContentId, (question) => question.content.rule.parentId = "root")
//если были результаты - удалить
questions.forEach((q) => {
if (q.type === 'result') deleteQuestion(q.id)
})
} }
} else { } else {
enqueueSnackbar("Нет информации о взятом опроснике") enqueueSnackbar("Нет информации о взятом опроснике")

@ -11,7 +11,7 @@ import {
useMediaQuery, useMediaQuery,
useTheme, useTheme,
} from "@mui/material"; } from "@mui/material";
import { copyQuestion, deleteQuestion, updateOpenBranchingPanel, updateDesireToOpenABranchingModal } from "@root/questions/actions"; import { copyQuestion, deleteQuestion, updateOpenBranchingPanel, updateDesireToOpenABranchingModal, updateOpenedModalSettingsId, clearRuleForAll } from "@root/questions/actions";
import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon"; import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon";
import Branching from "../../assets/icons/questionsPage/branching"; import Branching from "../../assets/icons/questionsPage/branching";
@ -22,7 +22,7 @@ import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { enqueueSnackbar } from "notistack"; import { enqueueSnackbar } from "notistack";
import { useQuestionsStore } from "@root/questions/store"; import { useQuestionsStore } from "@root/questions/store";
import { updateOpenedModalSettingsId } from "@root/questions/actions"; import { updateRootContentId } from "@root/quizes/actions";
interface Props { interface Props {
switchState: string; switchState: string;
@ -40,7 +40,7 @@ export default function ButtonsOptions({
const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isMobile = useMediaQuery(theme.breakpoints.down(790));
const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920)); const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920));
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { openBranchingPanel } = useQuestionsStore.getState() const { questions } = useQuestionsStore.getState()
const openedModal = () => { const openedModal = () => {
updateOpenedModalSettingsId(question.id) updateOpenedModalSettingsId(question.id)

@ -33,7 +33,6 @@ export const ResultSettings = () => {
isReadyToLeave = false; isReadyToLeave = false;
} }
}); });
console.log(`setting isReadyToLeaveRef to ${isReadyToLeave}`);
isReadyToLeaveRef.current = isReadyToLeave; isReadyToLeaveRef.current = isReadyToLeave;
}, [results]) }, [results])

@ -1,3 +1,4 @@
import dayjs from "dayjs";
import { DatePicker } from "@mui/x-date-pickers"; import { DatePicker } from "@mui/x-date-pickers";
import { Box, Typography } from "@mui/material"; import { Box, Typography } from "@mui/material";
@ -14,10 +15,9 @@ type DateProps = {
export const Date = ({ currentQuestion }: DateProps) => { export const Date = ({ currentQuestion }: DateProps) => {
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const { answer } = const answer = answers.find(
answers.find( ({ questionId }) => questionId === currentQuestion.content.id
({ questionId }) => questionId === currentQuestion.content.id )?.answer as string;
) ?? {};
const [day, month, year] = answer?.split(".") || []; const [day, month, year] = answer?.split(".") || [];
return ( return (
@ -32,50 +32,54 @@ export const Date = ({ currentQuestion }: DateProps) => {
}} }}
> >
<DatePicker <DatePicker
slots={{ slots={{
openPickerIcon: () => <CalendarIcon />, openPickerIcon: () => <CalendarIcon />,
}} }}
selected={ value={dayjs(
answer answer
? new window.Date(`${month}.${day}.${year}`) ? new window.Date(`${month}.${day}.${year}`)
: new window.Date() : new window.Date()
} )}
onChange={(date) => onChange={(date) => {
if (!date) {
return;
}
updateAnswer( updateAnswer(
currentQuestion.content.id, currentQuestion.content.id,
String( String(
date?.toLocaleDateString("ru-RU", { new window.Date(date.toDate()).toLocaleDateString("ru-RU", {
year: "numeric", year: "numeric",
month: "2-digit", month: "2-digit",
day: "2-digit", day: "2-digit",
}) })
) )
) );
} }}
slotProps={{ slotProps={{
openPickerButton: { openPickerButton: {
sx: { sx: {
p: 0, p: 0,
}, },
"data-cy": "open-datepicker", "data-cy": "open-datepicker",
}, },
}} }}
sx={{ sx={{
"& .MuiInputBase-root": { "& .MuiInputBase-root": {
backgroundColor: "#F2F3F7", backgroundColor: "#F2F3F7",
borderRadius: "10px", borderRadius: "10px",
maxWidth: "250px", maxWidth: "250px",
pr: "22px", pr: "22px",
"& input": { "& input": {
py: "11px", py: "11px",
pl: "20px", pl: "20px",
lineHeight: "19px", lineHeight: "19px",
}, },
"& fieldset": { "& fieldset": {
borderColor: "#9A9AAF", borderColor: "#9A9AAF",
}, },
}, },
}} }}
/> />
</Box> </Box>
</Box> </Box>

@ -16,13 +16,18 @@ type FileProps = {
export const File = ({ currentQuestion }: FileProps) => { export const File = ({ currentQuestion }: FileProps) => {
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const { answer } = answers.find(({ questionId }) => questionId === currentQuestion.content.id) ?? {}; const answer = answers.find(
({ questionId }) => questionId === currentQuestion.content.id
)?.answer as string;
const uploadFile = ({ target }: ChangeEvent<HTMLInputElement>) => { const uploadFile = ({ target }: ChangeEvent<HTMLInputElement>) => {
const file = target.files?.[0]; const file = target.files?.[0];
if (file) { if (file) {
updateAnswer(currentQuestion.content.id, `${file.name}|${URL.createObjectURL(file)}`); updateAnswer(
currentQuestion.content.id,
`${file.name}|${URL.createObjectURL(file)}`
);
} }
}; };
@ -47,6 +52,28 @@ export const File = ({ currentQuestion }: FileProps) => {
/> />
<UploadBox icon={<UploadIcon />} text="5 MB максимум" /> <UploadBox icon={<UploadIcon />} text="5 MB максимум" />
</ButtonBase> </ButtonBase>
{answer && currentQuestion.content.type === "picture" && (
<img
src={answer.split("|")[1]}
alt=""
style={{
marginTop: "15px",
maxWidth: "300px",
maxHeight: "300px",
}}
/>
)}
{answer && currentQuestion.content.type === "video" && (
<video
src={answer.split("|")[1]}
style={{
marginTop: "15px",
maxWidth: "300px",
maxHeight: "300px",
objectFit: "cover",
}}
/>
)}
{answer?.split("|")[0] && ( {answer?.split("|")[0] && (
<Typography sx={{ marginTop: "15px" }}> <Typography sx={{ marginTop: "15px" }}>
{answer?.split("|")[0]} {answer?.split("|")[0]}

@ -60,9 +60,22 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
<Box <Box
key={index} key={index}
sx={{ sx={{
cursor: "pointer",
borderRadius: "5px", borderRadius: "5px",
border: `1px solid ${theme.palette.grey2.main}`, border: `1px solid ${theme.palette.grey2.main}`,
}} }}
onClick={(event) => {
event.preventDefault();
updateAnswer(
currentQuestion.content.id,
currentQuestion.content.variants[index].id
);
if (answer === currentQuestion.content.variants[index].id) {
deleteAnswer(currentQuestion.content.id);
}
}}
> >
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}> <Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
<Box sx={{ width: "100%", height: "300px" }}> <Box sx={{ width: "100%", height: "300px" }}>
@ -88,18 +101,6 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
color: theme.palette.grey2.main, color: theme.palette.grey2.main,
marginTop: "10px", marginTop: "10px",
}} }}
onClick={(event) => {
event.preventDefault();
updateAnswer(
currentQuestion.content.id,
currentQuestion.content.variants[index].id
);
if (answer === currentQuestion.content.variants[index].id) {
deleteAnswer(currentQuestion.content.id);
}
}}
value={index} value={index}
control={ control={
<Radio checkedIcon={<RadioCheck />} icon={<RadioIcon />} /> <Radio checkedIcon={<RadioCheck />} icon={<RadioIcon />} />

@ -37,16 +37,14 @@ export const Number = ({ currentQuestion }: NumberProps) => {
}, },
1000 1000
); );
const { answer } = const answer = answers.find(
answers.find( ({ questionId }) => questionId === currentQuestion.content.id
({ questionId }) => questionId === currentQuestion.content.id )?.answer as string;
) ?? {};
const min = window.Number(currentQuestion.content.range.split("—")[0]); const min = window.Number(currentQuestion.content.range.split("—")[0]);
const max = window.Number(currentQuestion.content.range.split("—")[1]); const max = window.Number(currentQuestion.content.range.split("—")[1]);
useEffect(() => { useEffect(() => {
console.log("ans", currentQuestion.content.start);
if (answer) { if (answer) {
setMinRange(answer.split("—")[0]); setMinRange(answer.split("—")[0]);
setMaxRange(answer.split("—")[1]); setMaxRange(answer.split("—")[1]);
@ -76,8 +74,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
marginTop: "20px", marginTop: "20px",
}} }}
> >
<Slider
<Slider
value={ value={
currentQuestion.content.chooseRange currentQuestion.content.chooseRange
? answer?.split("—").length || 0 > 1 ? answer?.split("—").length || 0 > 1
@ -89,34 +86,35 @@ export const Number = ({ currentQuestion }: NumberProps) => {
max={max} max={max}
step={currentQuestion.content.step || 1} step={currentQuestion.content.step || 1}
sx={{ sx={{
marginBottom: "20px",
color: theme.palette.brightPurple.main, color: theme.palette.brightPurple.main,
padding: "0", padding: "0",
marginTop: "75px", marginTop: "75px",
"& .MuiSlider-valueLabel":{ "& .MuiSlider-valueLabel": {
background: theme.palette.brightPurple.main, background: theme.palette.brightPurple.main,
borderRadius: "8px", borderRadius: "8px",
width: "60px", width: "60px",
height: "36px" height: "36px",
}, },
"& .MuiSlider-valueLabel::before": { "& .MuiSlider-valueLabel::before": {
width: "6px", width: "6px",
height: "2px", height: "2px",
transform: "translate(-50%, 50%) rotate(90deg)", transform: "translate(-50%, 50%) rotate(90deg)",
bottom: "-5px" bottom: "-5px",
},
"& .MuiSlider-rail": {
backgroundColor: "#F2F3F7",
border: `1px solid #9A9AAF`,
height: "12px",
},
"& .MuiSlider-thumb": {
border: "3px #f2f3f7 solid",
height: "23px",
width: "23px",
},
"& .MuiSlider-track": {
height: "12px",
}, },
"& .MuiSlider-rail": {
backgroundColor: "#F2F3F7",
border: `1px solid #9A9AAF`,
height: "12px"
},
"& .MuiSlider-thumb": {
border: "3px #f2f3f7 solid",
height: "23px",
width: "23px"
},
"& .MuiSlider-track": {
height: "12px"
}
}} }}
onChange={(_, value) => { onChange={(_, value) => {
const range = String(value).replace(",", "—"); const range = String(value).replace(",", "—");
@ -152,12 +150,13 @@ export const Number = ({ currentQuestion }: NumberProps) => {
}} }}
/> />
)} )}
{currentQuestion.content.chooseRange && ( {currentQuestion.content.chooseRange && (
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
gap: "15px", gap: "15px",
alignItems: "center",
"& .MuiFormControl-root": { width: "auto" }, "& .MuiFormControl-root": { width: "auto" },
}} }}
> >
@ -180,9 +179,7 @@ export const Number = ({ currentQuestion }: NumberProps) => {
"& .MuiInputBase-input": { textAlign: "center" }, "& .MuiInputBase-input": { textAlign: "center" },
}} }}
/> />
<Typography>до</Typography>
до
<CustomTextField <CustomTextField
placeholder="0" placeholder="0"
value={maxRange} value={maxRange}
@ -204,7 +201,6 @@ export const Number = ({ currentQuestion }: NumberProps) => {
/> />
</Box> </Box>
)} )}
</Box> </Box>
</Box> </Box>
); );

@ -44,12 +44,14 @@ export const Rating = ({ currentQuestion }: RatingProps) => {
<StarIconMini <StarIconMini
color={theme.palette.brightPurple.main} color={theme.palette.brightPurple.main}
width={50} width={50}
sx={{ transform: "scale(1.4)" }}
/> />
} }
emptyIcon={ emptyIcon={
<StarIconMini <StarIconMini
color={theme.palette.grey2.main} color={theme.palette.grey2.main}
width={50} width={50}
sx={{ transform: "scale(1.4)" }}
/> />
} }
/> />

@ -2,8 +2,10 @@ import {
Box, Box,
Typography, Typography,
RadioGroup, RadioGroup,
FormGroup,
FormControlLabel, FormControlLabel,
Radio, Radio,
Checkbox,
useTheme, useTheme,
} from "@mui/material"; } from "@mui/material";
@ -27,11 +29,13 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
({ questionId }) => questionId === currentQuestion.content.id ({ questionId }) => questionId === currentQuestion.content.id
) ?? {}; ) ?? {};
const Group = currentQuestion.content.multi ? FormGroup : RadioGroup;
return ( return (
<Box> <Box>
<Typography variant="h5">{currentQuestion.title}</Typography> <Typography variant="h5">{currentQuestion.title}</Typography>
<Box sx={{ display: "flex" }}> <Box sx={{ display: "flex" }}>
<RadioGroup <Group
name={currentQuestion.id} name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex( value={currentQuestion.content.variants.findIndex(
({ id }) => answer === id ({ id }) => answer === id
@ -70,25 +74,45 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
value={index} value={index}
labelPlacement="start" labelPlacement="start"
control={ control={
<Radio checkedIcon={<RadioCheck />} icon={<RadioIcon />} /> currentQuestion.content.multi ? (
<Checkbox
checked={!!answer?.includes(variant.id)}
checkedIcon={<RadioCheck />}
icon={<RadioIcon />}
/>
) : (
<Radio checkedIcon={<RadioCheck />} icon={<RadioIcon />} />
)
} }
label={variant.answer} label={variant.answer}
onClick={(event) => { onClick={(event) => {
event.preventDefault(); event.preventDefault();
const variantId = currentQuestion.content.variants[index].id;
updateAnswer( if (currentQuestion.content.multi) {
currentQuestion.content.id, const currentAnswer =
currentQuestion.content.variants[index].id typeof answer !== "string" ? answer || [] : [];
);
if (answer === currentQuestion.content.variants[index].id) { 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); deleteAnswer(currentQuestion.content.id);
} }
}} }}
/> />
))} ))}
</Box> </Box>
</RadioGroup> </Group>
{currentQuestion.content.back && ( {currentQuestion.content.back && (
<Box sx={{ maxWidth: "400px", width: "100%", height: "300px" }}> <Box sx={{ maxWidth: "400px", width: "100%", height: "300px" }}>
<img <img

@ -3,7 +3,7 @@ import { devtools } from "zustand/middleware";
type Answer = { type Answer = {
questionId: string; questionId: string;
answer: string; answer: string | string[];
// Поле отвечающее за первое изменение ответа, нужно для галочки "Необязательный вопрос" // Поле отвечающее за первое изменение ответа, нужно для галочки "Необязательный вопрос"
changed: boolean; changed: boolean;
}; };
@ -25,7 +25,7 @@ export const useQuizViewStore = create<QuizViewStore>()(
export const updateAnswer = ( export const updateAnswer = (
questionId: string, questionId: string,
answer: string, answer: string | string[],
changed = true changed = true
) => { ) => {
const answers = [...useQuizViewStore.getState().answers]; const answers = [...useQuizViewStore.getState().answers];

646
yarn.lock

File diff suppressed because it is too large Load Diff