- fix
This commit is contained in:
parent
2828a5ebe2
commit
fa2dedeed6
@ -1,8 +1,4 @@
|
|||||||
import type {
|
import type { QuizQuestionBase, QuestionHint, PreviewRule } from "./shared";
|
||||||
QuizQuestionBase,
|
|
||||||
QuestionHint,
|
|
||||||
PreviewRule,
|
|
||||||
} from "./shared";
|
|
||||||
|
|
||||||
export interface QuizQuestionPage extends QuizQuestionBase {
|
export interface QuizQuestionPage extends QuizQuestionBase {
|
||||||
type: "page";
|
type: "page";
|
||||||
@ -15,6 +11,7 @@ export interface QuizQuestionPage extends QuizQuestionBase {
|
|||||||
text: string;
|
text: string;
|
||||||
picture: string;
|
picture: string;
|
||||||
originalPicture: string;
|
originalPicture: string;
|
||||||
|
useImage: boolean;
|
||||||
video: string;
|
video: string;
|
||||||
hint: QuestionHint;
|
hint: QuestionHint;
|
||||||
rule: PreviewRule;
|
rule: PreviewRule;
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { MessageIcon } from "@icons/messagIcon";
|
import { MessageIcon } from "@icons/messagIcon";
|
||||||
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
|
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
|
||||||
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
||||||
import {TextareaAutosize} from "@mui/base/TextareaAutosize";
|
import { TextareaAutosize } from "@mui/base/TextareaAutosize";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
FormControl,
|
FormControl,
|
||||||
IconButton,
|
IconButton,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
Popover,
|
Popover,
|
||||||
TextField,
|
TextField,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { addQuestionVariant, deleteQuestionVariant, setQuestionVariantField } from "@root/questions/actions";
|
import { addQuestionVariant, deleteQuestionVariant, setQuestionVariantField } from "@root/questions/actions";
|
||||||
import type { KeyboardEvent, ReactNode } from "react";
|
import type { KeyboardEvent, ReactNode } from "react";
|
||||||
@ -18,158 +18,147 @@ import { useState } from "react";
|
|||||||
import { Draggable } from "react-beautiful-dnd";
|
import { Draggable } from "react-beautiful-dnd";
|
||||||
import type { QuestionVariant } from "../../../model/questionTypes/shared";
|
import type { QuestionVariant } from "../../../model/questionTypes/shared";
|
||||||
import { useDebouncedCallback } from "use-debounce";
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
|
import { enqueueSnackbar } from "notistack";
|
||||||
|
|
||||||
type AnswerItemProps = {
|
type AnswerItemProps = {
|
||||||
index: number;
|
index: number;
|
||||||
questionId: string;
|
questionId: string;
|
||||||
variant: QuestionVariant;
|
variant: QuestionVariant;
|
||||||
largeCheck: boolean;
|
largeCheck: boolean;
|
||||||
additionalContent?: ReactNode;
|
disableKeyDown?: boolean;
|
||||||
additionalMobile?: ReactNode;
|
additionalContent?: ReactNode;
|
||||||
|
additionalMobile?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnswerItem = ({
|
export const AnswerItem = ({
|
||||||
index,
|
index,
|
||||||
variant,
|
variant,
|
||||||
questionId,
|
questionId,
|
||||||
largeCheck,
|
largeCheck,
|
||||||
additionalContent,
|
additionalContent,
|
||||||
additionalMobile,
|
additionalMobile,
|
||||||
|
disableKeyDown,
|
||||||
}: AnswerItemProps) => {
|
}: AnswerItemProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(790));
|
const isTablet = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
||||||
|
|
||||||
const setQuestionVariantAnswer = useDebouncedCallback((value) => {
|
const setQuestionVariantAnswer = useDebouncedCallback((value) => {
|
||||||
setQuestionVariantField(questionId, variant.id, "answer", value);
|
setQuestionVariantField(questionId, variant.id, "answer", value);
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
setAnchorEl(event.currentTarget);
|
setAnchorEl(event.currentTarget);
|
||||||
setIsOpen(true);
|
setIsOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Draggable draggableId={String(index)} index={index}>
|
<Draggable draggableId={String(index)} index={index}>
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<Box ref={provided.innerRef} {...provided.draggableProps}>
|
<Box ref={provided.innerRef} {...provided.draggableProps}>
|
||||||
<FormControl
|
<FormControl
|
||||||
key={index}
|
key={index}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="standard"
|
variant="standard"
|
||||||
sx={{
|
sx={{
|
||||||
margin: isTablet ? " 15px 0 20px 0" : "0 0 15px 0",
|
margin: isTablet ? " 15px 0 20px 0" : "0 0 15px 0",
|
||||||
borderRadius: "10px",
|
borderRadius: "10px",
|
||||||
border: "1px solid rgba(0, 0, 0, 0.23)",
|
border: "1px solid rgba(0, 0, 0, 0.23)",
|
||||||
background: "white",
|
background: "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
defaultValue={variant.answer}
|
||||||
|
fullWidth
|
||||||
|
focused={false}
|
||||||
|
placeholder={"Добавьте ответ"}
|
||||||
|
multiline={largeCheck}
|
||||||
|
onChange={({ target }) => {
|
||||||
|
setQuestionVariantAnswer(target.value || " ");
|
||||||
|
}}
|
||||||
|
onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (disableKeyDown) {
|
||||||
|
enqueueSnackbar("100 максимальное количество вопросов");
|
||||||
|
} else if (event.code === "Enter" && !largeCheck) {
|
||||||
|
addQuestionVariant(questionId);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: (
|
||||||
|
<>
|
||||||
|
<InputAdornment {...provided.dragHandleProps} position="start">
|
||||||
|
<PointsIcon style={{ color: "#9A9AAF", fontSize: "30px" }} />
|
||||||
|
</InputAdornment>
|
||||||
|
{additionalContent}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<IconButton sx={{ padding: "0" }} aria-describedby="my-popover-id" onClick={handleClick}>
|
||||||
|
<MessageIcon
|
||||||
|
style={{
|
||||||
|
color: "#9A9AAF",
|
||||||
|
fontSize: "30px",
|
||||||
|
marginRight: "6.5px",
|
||||||
}}
|
}}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
<Popover
|
||||||
|
id="my-popover-id"
|
||||||
|
open={isOpen}
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
onClose={handleClose}
|
||||||
|
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextareaAutosize
|
||||||
defaultValue={variant.answer}
|
style={{ margin: "10px" }}
|
||||||
fullWidth
|
placeholder="Подсказка для этого ответа"
|
||||||
focused={false}
|
value={variant.hints}
|
||||||
placeholder={"Добавьте ответ"}
|
onChange={(e) => setQuestionVariantAnswer(e.target.value || " ")}
|
||||||
multiline={largeCheck}
|
onKeyDown={(event: KeyboardEvent<HTMLTextAreaElement>) => event.stopPropagation()}
|
||||||
onChange={({ target }) => {
|
/>
|
||||||
setQuestionVariantAnswer(target.value || " ");
|
</Popover>
|
||||||
}}
|
<IconButton sx={{ padding: "0" }} onClick={() => deleteQuestionVariant(questionId, variant.id)}>
|
||||||
onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => {
|
<DeleteIcon
|
||||||
if (event.code === "Enter" && !largeCheck) {
|
style={{
|
||||||
addQuestionVariant(questionId);
|
color: theme.palette.grey2.main,
|
||||||
}
|
marginRight: "-1px",
|
||||||
}}
|
}}
|
||||||
InputProps={{
|
/>
|
||||||
startAdornment: (
|
</IconButton>
|
||||||
<>
|
</InputAdornment>
|
||||||
<InputAdornment
|
),
|
||||||
{...provided.dragHandleProps}
|
}}
|
||||||
position="start"
|
sx={{
|
||||||
>
|
"& .MuiInputBase-root": {
|
||||||
<PointsIcon
|
padding: additionalContent ? "5px 13px" : "13px",
|
||||||
style={{ color: "#9A9AAF", fontSize: "30px" }}
|
borderRadius: "10px",
|
||||||
/>
|
background: "#ffffff",
|
||||||
</InputAdornment>
|
"& input.MuiInputBase-input": {
|
||||||
{additionalContent}
|
height: "22px",
|
||||||
</>
|
},
|
||||||
),
|
"& textarea.MuiInputBase-input": {
|
||||||
endAdornment: (
|
marginTop: "1px",
|
||||||
<InputAdornment position="end">
|
},
|
||||||
<IconButton
|
"& .MuiOutlinedInput-notchedOutline": {
|
||||||
sx={{ padding: "0" }}
|
border: "none",
|
||||||
aria-describedby="my-popover-id"
|
},
|
||||||
onClick={handleClick}
|
},
|
||||||
>
|
}}
|
||||||
<MessageIcon
|
inputProps={{
|
||||||
style={{
|
sx: { fontSize: "18px", lineHeight: "21px", py: 0, ml: "13px" },
|
||||||
color: "#9A9AAF",
|
"data-cy": "quiz-variant-question-answer",
|
||||||
fontSize: "30px",
|
}}
|
||||||
marginRight: "6.5px",
|
/>
|
||||||
}}
|
{additionalMobile}
|
||||||
/>
|
</FormControl>
|
||||||
</IconButton>
|
</Box>
|
||||||
<Popover
|
)}
|
||||||
id="my-popover-id"
|
</Draggable>
|
||||||
open={isOpen}
|
);
|
||||||
anchorEl={anchorEl}
|
|
||||||
onClose={handleClose}
|
|
||||||
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
|
||||||
>
|
|
||||||
<TextareaAutosize
|
|
||||||
style={{ margin: "10px" }}
|
|
||||||
placeholder="Подсказка для этого ответа"
|
|
||||||
value={variant.hints}
|
|
||||||
onChange={e => setQuestionVariantAnswer(e.target.value || " ")}
|
|
||||||
onKeyDown={(
|
|
||||||
event: KeyboardEvent<HTMLTextAreaElement>
|
|
||||||
) => event.stopPropagation()}
|
|
||||||
/>
|
|
||||||
</Popover>
|
|
||||||
<IconButton
|
|
||||||
sx={{ padding: "0" }}
|
|
||||||
onClick={() => deleteQuestionVariant(questionId, variant.id)}
|
|
||||||
>
|
|
||||||
<DeleteIcon
|
|
||||||
style={{
|
|
||||||
color: theme.palette.grey2.main,
|
|
||||||
marginRight: "-1px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</InputAdornment>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
"& .MuiInputBase-root": {
|
|
||||||
padding: additionalContent ? "5px 13px" : "13px",
|
|
||||||
borderRadius: "10px",
|
|
||||||
background: "#ffffff",
|
|
||||||
"& input.MuiInputBase-input": {
|
|
||||||
height: "22px",
|
|
||||||
},
|
|
||||||
"& textarea.MuiInputBase-input": {
|
|
||||||
marginTop: "1px",
|
|
||||||
},
|
|
||||||
"& .MuiOutlinedInput-notchedOutline": {
|
|
||||||
border: "none",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
inputProps={{
|
|
||||||
sx: { fontSize: "18px", lineHeight: "21px", py: 0, ml: "13px" },
|
|
||||||
"data-cy": "quiz-variant-question-answer",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{additionalMobile}
|
|
||||||
</FormControl>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Draggable>
|
|
||||||
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
@ -6,44 +6,40 @@ import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
|||||||
import type { QuestionVariant, QuizQuestionsWithVariants } from "../../../model/questionTypes/shared";
|
import type { QuestionVariant, QuizQuestionsWithVariants } from "../../../model/questionTypes/shared";
|
||||||
import { AnswerItem } from "./AnswerItem";
|
import { AnswerItem } from "./AnswerItem";
|
||||||
|
|
||||||
|
|
||||||
type AnswerDraggableListProps = {
|
type AnswerDraggableListProps = {
|
||||||
question: QuizQuestionsWithVariants;
|
question: QuizQuestionsWithVariants;
|
||||||
additionalContent?: (variant: QuestionVariant, index: number) => ReactNode;
|
additionalContent?: (variant: QuestionVariant, index: number) => ReactNode;
|
||||||
additionalMobile?: (variant: QuestionVariant, index: number) => ReactNode;
|
additionalMobile?: (variant: QuestionVariant, index: number) => ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnswerDraggableList = ({
|
export const AnswerDraggableList = ({ question, additionalContent, additionalMobile }: AnswerDraggableListProps) => {
|
||||||
question,
|
const onDragEnd = ({ destination, source }: DropResult) => {
|
||||||
additionalContent,
|
if (destination) {
|
||||||
additionalMobile,
|
reorderQuestionVariants(question.id, source.index, destination.index);
|
||||||
}: AnswerDraggableListProps) => {
|
}
|
||||||
const onDragEnd = ({ destination, source }: DropResult) => {
|
};
|
||||||
if (destination) {
|
|
||||||
reorderQuestionVariants(question.id, source.index, destination.index);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
<Droppable droppableId="droppable-answer-list">
|
<Droppable droppableId="droppable-answer-list">
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<Box ref={provided.innerRef} {...provided.droppableProps}>
|
<Box ref={provided.innerRef} {...provided.droppableProps}>
|
||||||
{question.content.variants.map((variant, index) => (
|
{question.content.variants.map((variant, index) => (
|
||||||
<AnswerItem
|
<AnswerItem
|
||||||
key={variant.id}
|
key={variant.id}
|
||||||
index={index}
|
index={index}
|
||||||
questionId={question.id}
|
disableKeyDown={question.content.variants.length >= 100}
|
||||||
largeCheck={("largeCheck" in question.content) ? question.content.largeCheck : false}
|
questionId={question.id}
|
||||||
variant={variant}
|
largeCheck={"largeCheck" in question.content ? question.content.largeCheck : false}
|
||||||
additionalContent={additionalContent?.(variant, index)}
|
variant={variant}
|
||||||
additionalMobile={additionalMobile?.(variant, index)}
|
additionalContent={additionalContent?.(variant, index)}
|
||||||
/>
|
additionalMobile={additionalMobile?.(variant, index)}
|
||||||
))}
|
/>
|
||||||
{provided.placeholder}
|
))}
|
||||||
</Box>
|
{provided.placeholder}
|
||||||
)}
|
</Box>
|
||||||
</Droppable>
|
)}
|
||||||
</DragDropContext>
|
</Droppable>
|
||||||
);
|
</DragDropContext>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
useTheme,
|
useTheme,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { AnyTypedQuizQuestion, createBranchingRuleMain } from "../../../model/questionTypes/shared"
|
import { AnyTypedQuizQuestion, createBranchingRuleMain } from "../../../model/questionTypes/shared";
|
||||||
import { Select } from "../Select";
|
import { Select } from "../Select";
|
||||||
|
|
||||||
import RadioCheck from "@ui_kit/RadioCheck";
|
import RadioCheck from "@ui_kit/RadioCheck";
|
||||||
@ -27,45 +27,51 @@ import { updateOpenedModalSettingsId } from "@root/uiTools/actions";
|
|||||||
import { useUiTools } from "@root/uiTools/store";
|
import { useUiTools } from "@root/uiTools/store";
|
||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
|
|
||||||
|
|
||||||
export default function BranchingQuestions() {
|
export default function BranchingQuestions() {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const { openedModalSettingsId } = useUiTools();
|
const { openedModalSettingsId } = useUiTools();
|
||||||
const [targetQuestion, setTargetQuestion] = useState<AnyTypedQuizQuestion | null>(getQuestionById(openedModalSettingsId) || getQuestionByContentId(openedModalSettingsId))
|
const [targetQuestion, setTargetQuestion] = useState<AnyTypedQuizQuestion | null>(
|
||||||
const [parentQuestion, setParentQuestion] = useState<AnyTypedQuizQuestion | null>(getQuestionByContentId(targetQuestion?.content.rule.parentId))
|
getQuestionById(openedModalSettingsId) || getQuestionByContentId(openedModalSettingsId)
|
||||||
|
);
|
||||||
|
const [parentQuestion, setParentQuestion] = useState<AnyTypedQuizQuestion | null>(
|
||||||
|
getQuestionByContentId(targetQuestion?.content.rule.parentId)
|
||||||
|
);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (parentQuestion === null) return
|
if (parentQuestion === null) return;
|
||||||
if (parentQuestion.content.rule.main.length === 0) {
|
if (parentQuestion.content.rule.main.length === 0) {
|
||||||
let mutate = JSON.parse(JSON.stringify(parentQuestion))
|
let mutate = JSON.parse(JSON.stringify(parentQuestion));
|
||||||
mutate.content.rule.main = [{
|
mutate.content.rule.main = [
|
||||||
next: targetQuestion.content.id,
|
{
|
||||||
or: true,
|
next: targetQuestion.content.id,
|
||||||
rules: [{
|
or: true,
|
||||||
question: parentQuestion.content.id,
|
rules: [
|
||||||
answers: []
|
{
|
||||||
}]
|
question: parentQuestion.content.id,
|
||||||
}]
|
answers: [],
|
||||||
setParentQuestion(mutate)
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
setParentQuestion(mutate);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
if (targetQuestion === null || parentQuestion === null) {
|
if (targetQuestion === null || parentQuestion === null) {
|
||||||
enqueueSnackbar("Невозможно найти данные ветвления для этого вопроса")
|
enqueueSnackbar("Невозможно найти данные ветвления для этого вопроса");
|
||||||
return <></>
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveData = () => {
|
const saveData = () => {
|
||||||
if (parentQuestion !== null) {
|
if (parentQuestion !== null) {
|
||||||
updateQuestion(parentQuestion.content.id, question => question.content = parentQuestion.content)
|
updateQuestion(parentQuestion.content.id, (question) => (question.content = parentQuestion.content));
|
||||||
}
|
}
|
||||||
handleClose()
|
handleClose();
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
updateOpenedModalSettingsId()
|
updateOpenedModalSettingsId();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -100,44 +106,50 @@ export default function BranchingQuestions() {
|
|||||||
<Box sx={{ color: "#4d4d4d" }}>
|
<Box sx={{ color: "#4d4d4d" }}>
|
||||||
<Typography component="span">{targetQuestion.title}</Typography>
|
<Typography component="span">{targetQuestion.title}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Tooltip
|
<Tooltip title="Настройте условия, при которых данный вопрос будет отображаться в квизе." placement="top">
|
||||||
title="Настройте условия, при которых данный вопрос будет отображаться в квизе."
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<Box>
|
<Box>
|
||||||
<InfoIcon />
|
<InfoIcon />
|
||||||
</Box>
|
</Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
height: "400px",
|
height: "400px",
|
||||||
overflow: "auto"
|
overflow: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{
|
{parentQuestion.content.rule.main.length ? (
|
||||||
parentQuestion.content.rule.main.length ?
|
parentQuestion.content.rule.main.map((e: any, i: number) => {
|
||||||
parentQuestion.content.rule.main.map((e: any, i: number) => {
|
if (e.next === targetQuestion.content.id) {
|
||||||
if (e.next === targetQuestion.content.id) {
|
return (
|
||||||
return <TypeSwitch key={i} setParentQuestion={setParentQuestion} targetQuestion={targetQuestion} parentQuestion={parentQuestion} ruleIndex={i} />
|
<TypeSwitch
|
||||||
} else {
|
key={i}
|
||||||
<></>
|
setParentQuestion={setParentQuestion}
|
||||||
}
|
targetQuestion={targetQuestion}
|
||||||
})
|
parentQuestion={parentQuestion}
|
||||||
:
|
ruleIndex={i}
|
||||||
<TypeSwitch targetQuestion={targetQuestion} setParentQuestion={setParentQuestion} parentQuestion={parentQuestion} ruleIndex={0} />
|
/>
|
||||||
}
|
);
|
||||||
|
} else {
|
||||||
|
<></>;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<TypeSwitch
|
||||||
|
targetQuestion={targetQuestion}
|
||||||
|
setParentQuestion={setParentQuestion}
|
||||||
|
parentQuestion={parentQuestion}
|
||||||
|
ruleIndex={0}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
margin: "20px 0 0 20px",
|
margin: "20px 0 0 20px",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column"
|
flexDirection: "column",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
@ -145,48 +157,45 @@ export default function BranchingQuestions() {
|
|||||||
sx={{
|
sx={{
|
||||||
color: theme.palette.brightPurple.main,
|
color: theme.palette.brightPurple.main,
|
||||||
marginBottom: "10px",
|
marginBottom: "10px",
|
||||||
cursor: "pointer"
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const mutate = JSON.parse(JSON.stringify(parentQuestion))
|
const mutate = JSON.parse(JSON.stringify(parentQuestion));
|
||||||
mutate.content.rule.main.push(createBranchingRuleMain(targetQuestion.content.id, parentQuestion.content.id))
|
mutate.content.rule.main.push(
|
||||||
setParentQuestion(mutate)
|
createBranchingRuleMain(targetQuestion.content.id, parentQuestion.content.id)
|
||||||
|
);
|
||||||
|
setParentQuestion(mutate);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Добавить условие
|
Добавить условие
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
<FormControlLabel
|
||||||
<FormControlLabel control={<Checkbox
|
control={
|
||||||
|
<Checkbox
|
||||||
sx={{
|
sx={{
|
||||||
margin: 0
|
margin: 0,
|
||||||
}}
|
}}
|
||||||
checked={parentQuestion.content.rule.default === targetQuestion.content.id}
|
checked={parentQuestion.content.rule.default === targetQuestion.content.id}
|
||||||
|
onClick={() => {
|
||||||
onClick={() => {
|
let mutate = JSON.parse(JSON.stringify(parentQuestion));
|
||||||
let mutate = JSON.parse(JSON.stringify(parentQuestion))
|
mutate.content.rule.default =
|
||||||
mutate.content.rule.default = parentQuestion.content.rule.default === targetQuestion.content.id ? "" : targetQuestion.content.id
|
parentQuestion.content.rule.default === targetQuestion.content.id
|
||||||
setParentQuestion(mutate)
|
? ""
|
||||||
}}
|
: targetQuestion.content.id;
|
||||||
/>} label="Следующий вопрос по-умолчанию" />
|
setParentQuestion(mutate);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Следующий вопрос по-умолчанию"
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
<Box sx={{ display: "flex", justifyContent: "end", gap: "10px", margin: "20px" }}>
|
<Box sx={{ display: "flex", justifyContent: "end", gap: "10px", margin: "20px" }}>
|
||||||
<Button
|
<Button variant="outlined" onClick={handleClose} sx={{ width: "100%", maxWidth: "130px" }}>
|
||||||
variant="outlined"
|
|
||||||
onClick={handleClose}
|
|
||||||
sx={{ width: "100%", maxWidth: "130px" }}
|
|
||||||
>
|
|
||||||
Отмена
|
Отмена
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button variant="contained" sx={{ width: "100%", maxWidth: "130px" }} onClick={saveData}>
|
||||||
variant="contained"
|
|
||||||
sx={{ width: "100%", maxWidth: "130px" }}
|
|
||||||
onClick={saveData}
|
|
||||||
>
|
|
||||||
Готово
|
Готово
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -18,18 +18,31 @@ import RatingIcon from "@icons/questionsPage/rating";
|
|||||||
import Slider from "@icons/questionsPage/slider";
|
import Slider from "@icons/questionsPage/slider";
|
||||||
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
||||||
import {
|
import {
|
||||||
Box, Button,
|
Box,
|
||||||
Checkbox,
|
Button,
|
||||||
FormControl,
|
Checkbox,
|
||||||
FormControlLabel,
|
FormControl,
|
||||||
IconButton,
|
FormControlLabel,
|
||||||
InputAdornment, Modal,
|
IconButton,
|
||||||
Paper,
|
InputAdornment,
|
||||||
TextField, Typography,
|
Modal,
|
||||||
useMediaQuery,
|
Paper,
|
||||||
useTheme,
|
TextField,
|
||||||
|
Typography,
|
||||||
|
useMediaQuery,
|
||||||
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { copyQuestion, createUntypedQuestion, deleteQuestion, clearRuleForAll, toggleExpandQuestion, updateQuestion, updateUntypedQuestion, getQuestionByContentId, deleteQuestionWithTimeout } from "@root/questions/actions";
|
import {
|
||||||
|
copyQuestion,
|
||||||
|
createUntypedQuestion,
|
||||||
|
deleteQuestion,
|
||||||
|
clearRuleForAll,
|
||||||
|
toggleExpandQuestion,
|
||||||
|
updateQuestion,
|
||||||
|
updateUntypedQuestion,
|
||||||
|
getQuestionByContentId,
|
||||||
|
deleteQuestionWithTimeout,
|
||||||
|
} from "@root/questions/actions";
|
||||||
import { updateRootContentId } from "@root/quizes/actions";
|
import { updateRootContentId } from "@root/quizes/actions";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import type { DraggableProvidedDragHandleProps } from "react-beautiful-dnd";
|
import type { DraggableProvidedDragHandleProps } from "react-beautiful-dnd";
|
||||||
@ -44,493 +57,449 @@ import { useCurrentQuiz } from "@root/quizes/hooks";
|
|||||||
import { useQuestionsStore } from "@root/questions/store";
|
import { useQuestionsStore } from "@root/questions/store";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: AnyTypedQuizQuestion | UntypedQuizQuestion;
|
question: AnyTypedQuizQuestion | UntypedQuizQuestion;
|
||||||
draggableProps: DraggableProvidedDragHandleProps | null | undefined;
|
draggableProps: DraggableProvidedDragHandleProps | null | undefined;
|
||||||
isDragging: boolean;
|
isDragging: boolean;
|
||||||
index: number;
|
index: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function QuestionsPageCard({ question, draggableProps, isDragging, index }: Props) {
|
export default function QuestionsPageCard({ question, draggableProps, isDragging, index }: Props) {
|
||||||
const { questions } = useQuestionsStore();
|
const maxLengthTextField = 225;
|
||||||
const [plusVisible, setPlusVisible] = useState<boolean>(false);
|
|
||||||
const [open, setOpen] = useState<boolean>(false);
|
|
||||||
const [openDelete, setOpenDelete] = useState<boolean>(false);
|
|
||||||
const theme = useTheme();
|
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
|
||||||
const anchorRef = useRef(null);
|
|
||||||
const quiz = useCurrentQuiz();
|
|
||||||
|
|
||||||
const setTitle = useDebouncedCallback((title) => {
|
const { questions } = useQuestionsStore();
|
||||||
const updateQuestionFn = question.type === null ? updateUntypedQuestion : updateQuestion;
|
const [plusVisible, setPlusVisible] = useState<boolean>(false);
|
||||||
|
const [isTextFieldtActive, setIsTextFieldtActive] = useState(false);
|
||||||
|
const [open, setOpen] = useState<boolean>(false);
|
||||||
|
const [openDelete, setOpenDelete] = useState<boolean>(false);
|
||||||
|
const theme = useTheme();
|
||||||
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
|
const anchorRef = useRef(null);
|
||||||
|
const quiz = useCurrentQuiz();
|
||||||
|
|
||||||
updateQuestionFn(question.id, question => {
|
const setTitle = useDebouncedCallback((title) => {
|
||||||
question.title = title;
|
const updateQuestionFn = question.type === null ? updateUntypedQuestion : updateQuestion;
|
||||||
|
|
||||||
|
updateQuestionFn(question.id, (question) => {
|
||||||
|
question.title = title;
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
|
||||||
|
const deleteFn = () => {
|
||||||
|
if (question.type !== null) {
|
||||||
|
if (question.content.rule.parentId === "root") {
|
||||||
|
//удалить из стора root и очистить rule всем вопросам
|
||||||
|
updateRootContentId(quiz.id, "");
|
||||||
|
clearRuleForAll();
|
||||||
|
deleteQuestion(question.id);
|
||||||
|
questions.forEach((q) => {
|
||||||
|
if (q.type === "result") {
|
||||||
|
deleteQuestion(q.id);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, 200);
|
} else if (question.content.rule.parentId.length > 0) {
|
||||||
|
//удалить из стора вопрос из дерева и очистить его потомков
|
||||||
|
const clearQuestions = [] as string[];
|
||||||
|
|
||||||
const deleteFn = () => {
|
//записываем потомков , а их результаты удаляем
|
||||||
if (question.type !== null) {
|
const getChildren = (parentQuestion: AnyTypedQuizQuestion) => {
|
||||||
if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам
|
questions.forEach((targetQuestion) => {
|
||||||
updateRootContentId(quiz.id, "");
|
if (targetQuestion.content.rule.parentId === parentQuestion.content.id) {
|
||||||
clearRuleForAll();
|
//если у вопроса совпал родитель с родителем => он потомок, в кучу его
|
||||||
deleteQuestion(question.id);
|
if (targetQuestion.type === "result") {
|
||||||
questions.forEach(q => {
|
deleteQuestion(targetQuestion.id);
|
||||||
if (q.type === "result") {
|
} else {
|
||||||
deleteQuestion(q.id);
|
if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id);
|
||||||
}
|
getChildren(targetQuestion); //и ищем его потомков
|
||||||
});
|
}
|
||||||
} else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков
|
|
||||||
const clearQuestions = [] as string[];
|
|
||||||
|
|
||||||
//записываем потомков , а их результаты удаляем
|
|
||||||
const getChildren = (parentQuestion: AnyTypedQuizQuestion) => {
|
|
||||||
questions.forEach((targetQuestion) => {
|
|
||||||
if (targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его
|
|
||||||
if (targetQuestion.type === "result") {
|
|
||||||
deleteQuestion(targetQuestion.id);
|
|
||||||
} else {
|
|
||||||
if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id);
|
|
||||||
getChildren(targetQuestion); //и ищем его потомков
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
getChildren(question);
|
|
||||||
//чистим потомков от инфы ветвления
|
|
||||||
clearQuestions.forEach((id) => {
|
|
||||||
updateQuestion(id, question => {
|
|
||||||
question.content.rule.parentId = "";
|
|
||||||
question.content.rule.main = [];
|
|
||||||
question.content.rule.default = "";
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//чистим rule родителя
|
|
||||||
const parentQuestion = getQuestionByContentId(question.content.rule.parentId);
|
|
||||||
const newRule = {};
|
|
||||||
newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== question.content.id); //удаляем условия перехода от родителя к этому вопросу
|
|
||||||
newRule.parentId = parentQuestion.content.rule.parentId;
|
|
||||||
newRule.default = parentQuestion.content.rule.parentId === question.content.id ? "" : parentQuestion.content.rule.parentId;
|
|
||||||
newRule.children = [...parentQuestion.content.rule.children].splice(parentQuestion.content.rule.children.indexOf(question.content.id), 1);
|
|
||||||
|
|
||||||
updateQuestion(question.content.rule.parentId, (PQ) => {
|
|
||||||
PQ.content.rule = newRule;
|
|
||||||
});
|
|
||||||
deleteQuestion(question.id);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
getChildren(question);
|
||||||
|
//чистим потомков от инфы ветвления
|
||||||
|
clearQuestions.forEach((id) => {
|
||||||
|
updateQuestion(id, (question) => {
|
||||||
|
question.content.rule.parentId = "";
|
||||||
|
question.content.rule.main = [];
|
||||||
|
question.content.rule.default = "";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//чистим rule родителя
|
||||||
|
const parentQuestion = getQuestionByContentId(question.content.rule.parentId);
|
||||||
|
const newRule = {};
|
||||||
|
newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== question.content.id); //удаляем условия перехода от родителя к этому вопросу
|
||||||
|
newRule.parentId = parentQuestion.content.rule.parentId;
|
||||||
|
newRule.default =
|
||||||
|
parentQuestion.content.rule.parentId === question.content.id ? "" : parentQuestion.content.rule.parentId;
|
||||||
|
newRule.children = [...parentQuestion.content.rule.children].splice(
|
||||||
|
parentQuestion.content.rule.children.indexOf(question.content.id),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
deleteQuestion(question.id);
|
updateQuestion(question.content.rule.parentId, (PQ) => {
|
||||||
} else {
|
PQ.content.rule = newRule;
|
||||||
console.log("удаляю безтипогово");
|
});
|
||||||
deleteQuestion(question.id);
|
deleteQuestion(question.id);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
deleteQuestion(question.id);
|
||||||
<>
|
} else {
|
||||||
<Paper
|
console.log("удаляю безтипогово");
|
||||||
id={question.id}
|
deleteQuestion(question.id);
|
||||||
data-cy="quiz-question-card"
|
}
|
||||||
sx={{
|
};
|
||||||
maxWidth: "796px",
|
|
||||||
width: "100%",
|
const handleInputFocus = () => {
|
||||||
borderRadius: "12px",
|
setIsTextFieldtActive(true);
|
||||||
backgroundColor: question.expanded ? "white" : "#EEE4FC",
|
};
|
||||||
border: question.expanded ? "none" : "1px solid #9A9AAF",
|
|
||||||
boxShadow: "0px 10px 30px #e7e7e7",
|
const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {
|
||||||
}}
|
setIsTextFieldtActive(false);
|
||||||
>
|
};
|
||||||
<Box
|
|
||||||
sx={{
|
return (
|
||||||
display: "flex",
|
<>
|
||||||
alignItems: "center",
|
<Paper
|
||||||
padding: isMobile ? "10px" : "20px 10px 20px 20px",
|
id={question.id}
|
||||||
flexDirection: isMobile ? "column" : null,
|
data-cy="quiz-question-card"
|
||||||
}}
|
sx={{
|
||||||
>
|
maxWidth: "796px",
|
||||||
<FormControl
|
width: "100%",
|
||||||
variant="standard"
|
borderRadius: "12px",
|
||||||
sx={{
|
backgroundColor: question.expanded ? "white" : "#EEE4FC",
|
||||||
p: 0,
|
border: question.expanded ? "none" : "1px solid #9A9AAF",
|
||||||
maxWidth: isTablet ? "549px" : "640px",
|
boxShadow: "0px 10px 30px #e7e7e7",
|
||||||
width: "100%",
|
}}
|
||||||
marginRight: isMobile ? "0px" : "16.1px",
|
>
|
||||||
}}
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: isMobile ? "10px" : "20px 10px 20px 20px",
|
||||||
|
flexDirection: isMobile ? "column" : null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
variant="standard"
|
||||||
|
sx={{
|
||||||
|
p: 0,
|
||||||
|
maxWidth: isTablet ? "549px" : "640px",
|
||||||
|
width: "100%",
|
||||||
|
marginRight: isMobile ? "0px" : "16.1px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
defaultValue={question.title}
|
||||||
|
placeholder={"Заголовок вопроса"}
|
||||||
|
onChange={({ target }: { target: HTMLInputElement }) => setTitle(target.value || " ")}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
|
inputProps={{
|
||||||
|
maxLength: maxLengthTextField,
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: (
|
||||||
|
<Box>
|
||||||
|
<InputAdornment
|
||||||
|
ref={anchorRef}
|
||||||
|
position="start"
|
||||||
|
sx={{ cursor: "pointer" }}
|
||||||
|
onClick={() => setOpen((isOpened) => !isOpened)}
|
||||||
>
|
>
|
||||||
<TextField
|
{IconAndrom(question.expanded, question.type)}
|
||||||
defaultValue={question.title}
|
</InputAdornment>
|
||||||
placeholder={"Заголовок вопроса"}
|
<ChooseAnswerModal
|
||||||
onChange={({ target }: { target: HTMLInputElement; }) => setTitle(target.value || " ")}
|
open={open}
|
||||||
InputProps={{
|
onClose={() => setOpen(false)}
|
||||||
startAdornment: (
|
anchorRef={anchorRef}
|
||||||
<Box>
|
question={question}
|
||||||
<InputAdornment
|
questionType={question.type}
|
||||||
ref={anchorRef}
|
|
||||||
position="start"
|
|
||||||
sx={{ cursor: "pointer" }}
|
|
||||||
onClick={() => setOpen((isOpened) => !isOpened)}
|
|
||||||
>
|
|
||||||
{IconAndrom(question.expanded, question.type)}
|
|
||||||
</InputAdornment>
|
|
||||||
<ChooseAnswerModal
|
|
||||||
open={open}
|
|
||||||
onClose={() => setOpen(false)}
|
|
||||||
anchorRef={anchorRef}
|
|
||||||
question={question}
|
|
||||||
questionType={question.type}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
margin: isMobile ? "10px 0" : 0,
|
|
||||||
"& .MuiInputBase-root": {
|
|
||||||
color: "#000000",
|
|
||||||
backgroundColor: question.expanded
|
|
||||||
? theme.palette.background.default
|
|
||||||
: "transparent",
|
|
||||||
height: "48px",
|
|
||||||
borderRadius: "10px",
|
|
||||||
".MuiOutlinedInput-notchedOutline": {
|
|
||||||
borderWidth: "1px !important",
|
|
||||||
border: !question.expanded ? "none" : null,
|
|
||||||
},
|
|
||||||
"& .MuiInputBase-input::placeholder": {
|
|
||||||
color: "#4D4D4D",
|
|
||||||
opacity: 0.8,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
inputProps={{
|
|
||||||
sx: {
|
|
||||||
fontSize: "18px",
|
|
||||||
lineHeight: "21px",
|
|
||||||
py: 0,
|
|
||||||
paddingLeft: question.type === null ? 0 : "18px",
|
|
||||||
},
|
|
||||||
"data-cy": "quiz-question-title",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-end",
|
|
||||||
width: isMobile ? "100%" : "auto",
|
|
||||||
position: "relative",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
sx={{ padding: "0", margin: "5px" }}
|
|
||||||
disableRipple
|
|
||||||
data-cy="expand-question"
|
|
||||||
onClick={() => toggleExpandQuestion(question.id)}
|
|
||||||
>
|
|
||||||
{question.expanded ? (
|
|
||||||
<ArrowDownIcon
|
|
||||||
style={{
|
|
||||||
width: "18px",
|
|
||||||
color: "#4D4D4D",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ExpandLessIcon
|
|
||||||
sx={{
|
|
||||||
boxSizing: "border-box",
|
|
||||||
fill: theme.palette.brightPurple.main,
|
|
||||||
background: "#FFF",
|
|
||||||
borderRadius: "6px",
|
|
||||||
height: "30px",
|
|
||||||
width: "30px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</IconButton>
|
|
||||||
{question.expanded ? (
|
|
||||||
<></>
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
height: "30px",
|
|
||||||
borderRight: "solid 1px #4D4D4D",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
icon={
|
|
||||||
<HideIcon
|
|
||||||
style={{
|
|
||||||
boxSizing: "border-box",
|
|
||||||
color: "#7E2AEA",
|
|
||||||
background: "#FFF",
|
|
||||||
borderRadius: "6px",
|
|
||||||
height: "30px",
|
|
||||||
width: "30px",
|
|
||||||
padding: "3px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
checkedIcon={<CrossedEyeIcon />}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={""}
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.grey2.main,
|
|
||||||
ml: "-9px",
|
|
||||||
mr: 0,
|
|
||||||
userSelect: "none",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
sx={{ padding: "0" }}
|
|
||||||
onClick={() => copyQuestion(question.id, question.quizId)}
|
|
||||||
>
|
|
||||||
<CopyIcon
|
|
||||||
style={{ color: theme.palette.brightPurple.main }}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
borderRadius: "6px",
|
|
||||||
padding: "0",
|
|
||||||
margin: "0 5px 0 10px",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
if(question.content.rule.parentId.length !== 0) {
|
|
||||||
setOpenDelete(true)
|
|
||||||
} else {
|
|
||||||
deleteQuestionWithTimeout(question.id, deleteFn);
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
data-cy="delete-question"
|
|
||||||
>
|
|
||||||
<DeleteIcon
|
|
||||||
style={{ color: theme.palette.brightPurple.main }}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
<Modal open={openDelete} onClose={() => setOpenDelete(false)}>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
top: "50%",
|
|
||||||
left: "50%",
|
|
||||||
transform: "translate(-50%, -50%)",
|
|
||||||
padding: "30px",
|
|
||||||
borderRadius: "10px",
|
|
||||||
background: "#FFFFFF",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="h6" sx={{textAlign: "center"}}>
|
|
||||||
Вы удаляете вопрос, участвующий в ветвлении. Все его потомки потеряют данные ветвления. Вы уверены, что хотите удалить вопрос?
|
|
||||||
</Typography>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
marginTop: "30px",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
gap: "15px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
sx={{ minWidth: "150px" }}
|
|
||||||
onClick={() => setOpenDelete(false)}
|
|
||||||
>
|
|
||||||
Отмена
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
sx={{ minWidth: "150px" }}
|
|
||||||
onClick={() => {
|
|
||||||
deleteQuestionWithTimeout(question.id, deleteFn);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Подтвердить
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Modal>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
{question.type !== null &&
|
|
||||||
<Box
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
height: "30px",
|
|
||||||
width: "30px",
|
|
||||||
marginLeft: "3px",
|
|
||||||
borderRadius: "50%",
|
|
||||||
fontSize: "16px",
|
|
||||||
color: question.expanded
|
|
||||||
? theme.palette.brightPurple.main
|
|
||||||
: "#FFF",
|
|
||||||
background: question.expanded
|
|
||||||
? "#EEE4FC"
|
|
||||||
: theme.palette.brightPurple.main,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{question.page + 1}
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
<IconButton
|
|
||||||
disableRipple
|
|
||||||
sx={{
|
|
||||||
padding: isMobile ? "0" : "0 5px",
|
|
||||||
right: isMobile ? "0" : null,
|
|
||||||
bottom: isMobile ? "0" : null,
|
|
||||||
}}
|
|
||||||
{...draggableProps}
|
|
||||||
>
|
|
||||||
<PointsIcon style={{ color: "#4D4D4D", fontSize: "30px" }} />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
{question.expanded && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
padding: 0,
|
|
||||||
borderRadius: "12px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{question.type === null ? (
|
|
||||||
<TypeQuestions question={question} />
|
|
||||||
) : (
|
|
||||||
<SwitchQuestionsPage question={question} />
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Paper>
|
|
||||||
<Box
|
|
||||||
onMouseEnter={() => setPlusVisible(true)}
|
|
||||||
onMouseLeave={() => setPlusVisible(false)}
|
|
||||||
sx={{
|
|
||||||
maxWidth: "825px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
height: "40px",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
onClick={() => createUntypedQuestion(question.quizId, question.id)}
|
|
||||||
sx={{
|
|
||||||
display: plusVisible && !isDragging ? "flex" : "none",
|
|
||||||
width: "100%",
|
|
||||||
alignItems: "center",
|
|
||||||
columnGap: "10px",
|
|
||||||
}}
|
|
||||||
data-cy="create-question"
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
boxSizing: "border-box",
|
|
||||||
width: "100%",
|
|
||||||
height: "1px",
|
|
||||||
backgroundPosition: "bottom",
|
|
||||||
backgroundRepeat: "repeat-x",
|
|
||||||
backgroundSize: "20px 1px",
|
|
||||||
backgroundImage:
|
|
||||||
"radial-gradient(circle, #7E2AEA 6px, #F2F3F7 1px)",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<PlusIcon />
|
</Box>
|
||||||
</Box>
|
),
|
||||||
</Box>
|
endAdornment: isTextFieldtActive && question.title.length >= maxLengthTextField - 7 && (
|
||||||
</>
|
<Box
|
||||||
);
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginLeft: "auto",
|
||||||
|
position: "absolute",
|
||||||
|
bottom: "-28px",
|
||||||
|
right: "0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography fontSize="14px">{question.title.length}</Typography>
|
||||||
|
<span>/</span>
|
||||||
|
<Typography fontSize="14px">{maxLengthTextField}</Typography>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
margin: isMobile ? "10px 0" : 0,
|
||||||
|
"& .MuiInputBase-root": {
|
||||||
|
color: "#000000",
|
||||||
|
backgroundColor: question.expanded ? theme.palette.background.default : "transparent",
|
||||||
|
height: "48px",
|
||||||
|
borderRadius: "10px",
|
||||||
|
".MuiOutlinedInput-notchedOutline": {
|
||||||
|
borderWidth: "1px !important",
|
||||||
|
border: !question.expanded ? "none" : null,
|
||||||
|
},
|
||||||
|
"& .MuiInputBase-input::placeholder": {
|
||||||
|
color: "#4D4D4D",
|
||||||
|
opacity: 0.8,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
width: isMobile ? "100%" : "auto",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
sx={{ padding: "0", margin: "5px" }}
|
||||||
|
disableRipple
|
||||||
|
data-cy="expand-question"
|
||||||
|
onClick={() => toggleExpandQuestion(question.id)}
|
||||||
|
>
|
||||||
|
{question.expanded ? (
|
||||||
|
<ArrowDownIcon
|
||||||
|
style={{
|
||||||
|
width: "18px",
|
||||||
|
color: "#4D4D4D",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ExpandLessIcon
|
||||||
|
sx={{
|
||||||
|
boxSizing: "border-box",
|
||||||
|
fill: theme.palette.brightPurple.main,
|
||||||
|
background: "#FFF",
|
||||||
|
borderRadius: "6px",
|
||||||
|
height: "30px",
|
||||||
|
width: "30px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</IconButton>
|
||||||
|
{question.expanded ? (
|
||||||
|
<></>
|
||||||
|
) : (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
height: "30px",
|
||||||
|
borderRight: "solid 1px #4D4D4D",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
icon={
|
||||||
|
<HideIcon
|
||||||
|
style={{
|
||||||
|
boxSizing: "border-box",
|
||||||
|
color: "#7E2AEA",
|
||||||
|
background: "#FFF",
|
||||||
|
borderRadius: "6px",
|
||||||
|
height: "30px",
|
||||||
|
width: "30px",
|
||||||
|
padding: "3px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
checkedIcon={<CrossedEyeIcon />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={""}
|
||||||
|
sx={{
|
||||||
|
color: theme.palette.grey2.main,
|
||||||
|
ml: "-9px",
|
||||||
|
mr: 0,
|
||||||
|
userSelect: "none",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<IconButton sx={{ padding: "0" }} onClick={() => copyQuestion(question.id, question.quizId)}>
|
||||||
|
<CopyIcon style={{ color: theme.palette.brightPurple.main }} />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
sx={{
|
||||||
|
cursor: "pointer",
|
||||||
|
borderRadius: "6px",
|
||||||
|
padding: "0",
|
||||||
|
margin: "0 5px 0 10px",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
if (question.content.rule.parentId.length !== 0) {
|
||||||
|
setOpenDelete(true);
|
||||||
|
} else {
|
||||||
|
deleteQuestionWithTimeout(question.id, deleteFn);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
data-cy="delete-question"
|
||||||
|
>
|
||||||
|
<DeleteIcon style={{ color: theme.palette.brightPurple.main }} />
|
||||||
|
</IconButton>
|
||||||
|
<Modal open={openDelete} onClose={() => setOpenDelete(false)}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
padding: "30px",
|
||||||
|
borderRadius: "10px",
|
||||||
|
background: "#FFFFFF",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h6" sx={{ textAlign: "center" }}>
|
||||||
|
Вы удаляете вопрос, участвующий в ветвлении. Все его потомки потеряют данные ветвления. Вы
|
||||||
|
уверены, что хотите удалить вопрос?
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
marginTop: "30px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
gap: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button variant="contained" sx={{ minWidth: "150px" }} onClick={() => setOpenDelete(false)}>
|
||||||
|
Отмена
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
sx={{ minWidth: "150px" }}
|
||||||
|
onClick={() => {
|
||||||
|
deleteQuestionWithTimeout(question.id, deleteFn);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Подтвердить
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{question.type !== null && (
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
height: "30px",
|
||||||
|
width: "30px",
|
||||||
|
marginLeft: "3px",
|
||||||
|
borderRadius: "50%",
|
||||||
|
fontSize: "16px",
|
||||||
|
color: question.expanded ? theme.palette.brightPurple.main : "#FFF",
|
||||||
|
background: question.expanded ? "#EEE4FC" : theme.palette.brightPurple.main,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{question.page + 1}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<IconButton
|
||||||
|
disableRipple
|
||||||
|
sx={{
|
||||||
|
padding: isMobile ? "0" : "0 5px",
|
||||||
|
right: isMobile ? "0" : null,
|
||||||
|
bottom: isMobile ? "0" : null,
|
||||||
|
}}
|
||||||
|
{...draggableProps}
|
||||||
|
>
|
||||||
|
<PointsIcon style={{ color: "#4D4D4D", fontSize: "30px" }} />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
{question.expanded && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
padding: 0,
|
||||||
|
borderRadius: "12px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{question.type === null ? (
|
||||||
|
<TypeQuestions question={question} />
|
||||||
|
) : (
|
||||||
|
<SwitchQuestionsPage question={question} />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
<Box
|
||||||
|
onMouseEnter={() => setPlusVisible(true)}
|
||||||
|
onMouseLeave={() => setPlusVisible(false)}
|
||||||
|
sx={{
|
||||||
|
maxWidth: "825px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "40px",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
onClick={() => createUntypedQuestion(question.quizId, question.id)}
|
||||||
|
sx={{
|
||||||
|
display: plusVisible && !isDragging ? "flex" : "none",
|
||||||
|
width: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
columnGap: "10px",
|
||||||
|
}}
|
||||||
|
data-cy="create-question"
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
boxSizing: "border-box",
|
||||||
|
width: "100%",
|
||||||
|
height: "1px",
|
||||||
|
backgroundPosition: "bottom",
|
||||||
|
backgroundRepeat: "repeat-x",
|
||||||
|
backgroundSize: "20px 1px",
|
||||||
|
backgroundImage: "radial-gradient(circle, #7E2AEA 6px, #F2F3F7 1px)",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<PlusIcon />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const IconAndrom = (isExpanded: boolean, questionType: QuestionType | null) => {
|
const IconAndrom = (isExpanded: boolean, questionType: QuestionType | null) => {
|
||||||
switch (questionType) {
|
switch (questionType) {
|
||||||
case "variant":
|
case "variant":
|
||||||
return (
|
return <Answer color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
<Answer
|
case "images":
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
return <OptionsPict color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
sx={{ height: "22px", width: "20px" }}
|
case "varimg":
|
||||||
/>
|
return <OptionsAndPict color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
);
|
case "emoji":
|
||||||
case "images":
|
return <Emoji color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
return (
|
case "text":
|
||||||
<OptionsPict
|
return <Input color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
case "select":
|
||||||
sx={{ height: "22px", width: "20px" }}
|
return <DropDown color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
/>
|
case "date":
|
||||||
);
|
return <Date color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
case "varimg":
|
case "number":
|
||||||
return (
|
return <Slider color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
<OptionsAndPict
|
case "file":
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
return <Download color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
sx={{ height: "22px", width: "20px" }}
|
case "page":
|
||||||
/>
|
return <Page color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
);
|
case "rating":
|
||||||
case "emoji":
|
return <RatingIcon color={isExpanded ? "#9A9AAF" : "#7E2AEA"} sx={{ height: "22px", width: "20px" }} />;
|
||||||
return (
|
default:
|
||||||
<Emoji
|
return <></>;
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
}
|
||||||
sx={{ height: "22px", width: "20px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "text":
|
|
||||||
return (
|
|
||||||
<Input
|
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
||||||
sx={{ height: "22px", width: "20px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "select":
|
|
||||||
return (
|
|
||||||
<DropDown
|
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
||||||
sx={{ height: "22px", width: "20px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "date":
|
|
||||||
return (
|
|
||||||
<Date
|
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
||||||
sx={{ height: "22px", width: "20px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "number":
|
|
||||||
return (
|
|
||||||
<Slider
|
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
||||||
sx={{ height: "22px", width: "20px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "file":
|
|
||||||
return (
|
|
||||||
<Download
|
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
||||||
sx={{ height: "22px", width: "20px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "page":
|
|
||||||
return (
|
|
||||||
<Page
|
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
||||||
sx={{ height: "22px", width: "20px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "rating":
|
|
||||||
return (
|
|
||||||
<RatingIcon
|
|
||||||
color={isExpanded ? "#9A9AAF" : "#7E2AEA"}
|
|
||||||
sx={{ height: "22px", width: "20px" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return <></>;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
@ -4,15 +4,16 @@ import { AnswerDraggableList } from "../AnswerDraggableList";
|
|||||||
import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon";
|
import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon";
|
||||||
import SwitchDropDown from "./switchDropDown";
|
import SwitchDropDown from "./switchDropDown";
|
||||||
import ButtonsOptions from "../ButtonsOptions";
|
import ButtonsOptions from "../ButtonsOptions";
|
||||||
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
|
|
||||||
import { addQuestionVariant } from "@root/questions/actions";
|
import { addQuestionVariant } from "@root/questions/actions";
|
||||||
|
import { useAddAnswer } from "../../../utils/hooks/useAddAnswer";
|
||||||
|
|
||||||
|
import type { QuizQuestionSelect } from "../../../model/questionTypes/select";
|
||||||
interface Props {
|
interface Props {
|
||||||
question: QuizQuestionSelect;
|
question: QuizQuestionSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DropDown({ question }: Props) {
|
export default function DropDown({ question }: Props) {
|
||||||
|
const onClickAddAnAnswer = useAddAnswer();
|
||||||
const [switchState, setSwitchState] = useState("setting");
|
const [switchState, setSwitchState] = useState("setting");
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
@ -60,7 +61,7 @@ export default function DropDown({ question }: Props) {
|
|||||||
mr: "4px",
|
mr: "4px",
|
||||||
height: "19px",
|
height: "19px",
|
||||||
}}
|
}}
|
||||||
onClick={() => addQuestionVariant(question.id)}
|
onClick={() => onClickAddAnAnswer(question)}
|
||||||
>
|
>
|
||||||
Добавьте ответ
|
Добавьте ответ
|
||||||
</Link>
|
</Link>
|
||||||
@ -87,11 +88,7 @@ export default function DropDown({ question }: Props) {
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<ButtonsOptions
|
<ButtonsOptions switchState={switchState} SSHC={SSHC} question={question} />
|
||||||
switchState={switchState}
|
|
||||||
SSHC={SSHC}
|
|
||||||
question={question}
|
|
||||||
/>
|
|
||||||
<SwitchDropDown switchState={switchState} question={question} />
|
<SwitchDropDown switchState={switchState} question={question} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
import { EmojiIcons } from "@icons/EmojiIocns";
|
import { EmojiIcons } from "@icons/EmojiIocns";
|
||||||
import AddEmoji from "@icons/questionsPage/addEmoji";
|
import AddEmoji from "@icons/questionsPage/addEmoji";
|
||||||
import PlusImage from "@icons/questionsPage/plus";
|
import PlusImage from "@icons/questionsPage/plus";
|
||||||
import {
|
import { Box, Link, Popover, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
Box,
|
|
||||||
Link,
|
|
||||||
Popover,
|
|
||||||
Typography,
|
|
||||||
useMediaQuery,
|
|
||||||
useTheme,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { addQuestionVariant, updateQuestion } from "@root/questions/actions";
|
import { addQuestionVariant, updateQuestion } from "@root/questions/actions";
|
||||||
import { EmojiPicker } from "@ui_kit/EmojiPicker";
|
import { EmojiPicker } from "@ui_kit/EmojiPicker";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
@ -17,225 +10,220 @@ import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji";
|
|||||||
import { AnswerDraggableList } from "../AnswerDraggableList";
|
import { AnswerDraggableList } from "../AnswerDraggableList";
|
||||||
import ButtonsOptions from "../ButtonsOptions";
|
import ButtonsOptions from "../ButtonsOptions";
|
||||||
import SwitchEmoji from "./switchEmoji";
|
import SwitchEmoji from "./switchEmoji";
|
||||||
|
import { useAddAnswer } from "../../../utils/hooks/useAddAnswer";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: QuizQuestionEmoji;
|
question: QuizQuestionEmoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Emoji({ question }: Props) {
|
export default function Emoji({ question }: Props) {
|
||||||
const [switchState, setSwitchState] = useState<string>("setting");
|
const [switchState, setSwitchState] = useState<string>("setting");
|
||||||
const [open, setOpen] = useState<boolean>(false);
|
const onClickAddAnAnswer = useAddAnswer();
|
||||||
const [anchorElement, setAnchorElement] = useState<HTMLDivElement | null>(
|
const [open, setOpen] = useState<boolean>(false);
|
||||||
null
|
const [anchorElement, setAnchorElement] = useState<HTMLDivElement | null>(null);
|
||||||
);
|
const [selectedVariant, setSelectedVariant] = useState<string | null>(null);
|
||||||
const [selectedVariant, setSelectedVariant] = useState<string | null>(null);
|
const theme = useTheme();
|
||||||
const theme = useTheme();
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
|
||||||
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ padding: "20px" }}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
<AnswerDraggableList
|
<AnswerDraggableList
|
||||||
question={question}
|
question={question}
|
||||||
additionalContent={(variant) => (
|
additionalContent={(variant) => (
|
||||||
<>
|
<>
|
||||||
{!isTablet && (
|
{!isTablet && (
|
||||||
<Box sx={{ cursor: "pointer" }}>
|
<Box sx={{ cursor: "pointer" }}>
|
||||||
<Box
|
<Box
|
||||||
data-cy="choose-emoji-button"
|
data-cy="choose-emoji-button"
|
||||||
onClick={({ currentTarget }) => {
|
onClick={({ currentTarget }) => {
|
||||||
setAnchorElement(currentTarget);
|
setAnchorElement(currentTarget);
|
||||||
setSelectedVariant(variant.id);
|
setSelectedVariant(variant.id);
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "5px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{variant.extendedText ? (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
height: "40px",
|
|
||||||
width: "60px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
background: "#EEE4FC",
|
|
||||||
borderRadius: "3px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{variant.extendedText}
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<PlusImage />
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<AddEmoji />
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
additionalMobile={(variant) => (
|
|
||||||
<>
|
|
||||||
{isTablet && (
|
|
||||||
<Box
|
|
||||||
onClick={({ currentTarget }) => {
|
|
||||||
setAnchorElement(currentTarget);
|
|
||||||
setSelectedVariant(variant.id);
|
|
||||||
setOpen(true);
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
m: "8px",
|
|
||||||
position: "relative",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
background: "#EEE4FC",
|
|
||||||
height: "40px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{variant.extendedText ? (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
color: "#7E2AEA",
|
|
||||||
fontSize: "20px",
|
|
||||||
left: "45%",
|
|
||||||
right: "55%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{variant.extendedText}
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<EmojiIcons
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
color: "#7E2AEA",
|
|
||||||
fontSize: "20px",
|
|
||||||
left: "45%",
|
|
||||||
right: "55%",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
width: "20px",
|
|
||||||
background: "#EEE4FC",
|
|
||||||
height: "40px",
|
|
||||||
color: "white",
|
|
||||||
backgroundColor: "#7E2AEA",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Popover
|
|
||||||
open={open}
|
|
||||||
anchorEl={anchorElement}
|
|
||||||
onClick={(event) => event.stopPropagation()}
|
|
||||||
onClose={() => setOpen(false)}
|
|
||||||
anchorOrigin={{
|
|
||||||
vertical: "bottom",
|
|
||||||
horizontal: "right",
|
|
||||||
}}
|
}}
|
||||||
sx={{
|
>
|
||||||
".MuiPaper-root.MuiPaper-rounded": {
|
<Box
|
||||||
borderRadius: "10px",
|
sx={{
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<EmojiPicker
|
|
||||||
onEmojiSelect={({ native }) => {
|
|
||||||
setOpen(false);
|
|
||||||
updateQuestion(question.id, question => {
|
|
||||||
if (question.type !== "emoji") return;
|
|
||||||
|
|
||||||
const variant = question.content.variants.find(v => v.id === selectedVariant);
|
|
||||||
if (!variant) return;
|
|
||||||
|
|
||||||
variant.extendedText = native;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Popover>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: "10px",
|
gap: "5px",
|
||||||
marginBottom: isMobile ? "17px" : "20px",
|
}}
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Link
|
|
||||||
component="button"
|
|
||||||
variant="body2"
|
|
||||||
sx={{ color: theme.palette.brightPurple.main }}
|
|
||||||
onClick={() => addQuestionVariant(question.id)}
|
|
||||||
>
|
>
|
||||||
Добавьте ответ
|
{variant.extendedText ? (
|
||||||
</Link>
|
<Box
|
||||||
{!isTablet && (
|
sx={{
|
||||||
<>
|
height: "40px",
|
||||||
<Typography
|
width: "60px",
|
||||||
sx={{
|
display: "flex",
|
||||||
fontWeight: 400,
|
alignItems: "center",
|
||||||
lineHeight: "21.33px",
|
justifyContent: "space-between",
|
||||||
color: theme.palette.grey2.main,
|
background: "#EEE4FC",
|
||||||
fontSize: "16px",
|
borderRadius: "3px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
или нажмите Enter
|
<Box
|
||||||
</Typography>
|
sx={{
|
||||||
<EnterIcon
|
width: "100%",
|
||||||
style={{
|
display: "flex",
|
||||||
color: "#7E2AEA",
|
justifyContent: "center",
|
||||||
fontSize: "24px",
|
}}
|
||||||
marginLeft: "6px",
|
>
|
||||||
}}
|
{variant.extendedText}
|
||||||
/>
|
</Box>
|
||||||
</>
|
<Box>
|
||||||
)}
|
<PlusImage />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<AddEmoji />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
)}
|
||||||
<ButtonsOptions
|
</>
|
||||||
switchState={switchState}
|
)}
|
||||||
SSHC={SSHC}
|
additionalMobile={(variant) => (
|
||||||
question={question}
|
<>
|
||||||
/>
|
{isTablet && (
|
||||||
<SwitchEmoji switchState={switchState} question={question} />
|
<Box
|
||||||
</>
|
onClick={({ currentTarget }) => {
|
||||||
);
|
setAnchorElement(currentTarget);
|
||||||
|
setSelectedVariant(variant.id);
|
||||||
|
setOpen(true);
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
m: "8px",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
background: "#EEE4FC",
|
||||||
|
height: "40px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{variant.extendedText ? (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
color: "#7E2AEA",
|
||||||
|
fontSize: "20px",
|
||||||
|
left: "45%",
|
||||||
|
right: "55%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{variant.extendedText}
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<EmojiIcons
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
color: "#7E2AEA",
|
||||||
|
fontSize: "20px",
|
||||||
|
left: "45%",
|
||||||
|
right: "55%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "20px",
|
||||||
|
background: "#EEE4FC",
|
||||||
|
height: "40px",
|
||||||
|
color: "white",
|
||||||
|
backgroundColor: "#7E2AEA",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
open={open}
|
||||||
|
anchorEl={anchorElement}
|
||||||
|
onClick={(event) => event.stopPropagation()}
|
||||||
|
onClose={() => setOpen(false)}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: "bottom",
|
||||||
|
horizontal: "right",
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
".MuiPaper-root.MuiPaper-rounded": {
|
||||||
|
borderRadius: "10px",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<EmojiPicker
|
||||||
|
onEmojiSelect={({ native }) => {
|
||||||
|
setOpen(false);
|
||||||
|
updateQuestion(question.id, (question) => {
|
||||||
|
if (question.type !== "emoji") return;
|
||||||
|
|
||||||
|
const variant = question.content.variants.find((v) => v.id === selectedVariant);
|
||||||
|
if (!variant) return;
|
||||||
|
|
||||||
|
variant.extendedText = native;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "10px",
|
||||||
|
marginBottom: isMobile ? "17px" : "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
component="button"
|
||||||
|
variant="body2"
|
||||||
|
sx={{ color: theme.palette.brightPurple.main }}
|
||||||
|
onClick={() => onClickAddAnAnswer(question)}
|
||||||
|
>
|
||||||
|
Добавьте ответ
|
||||||
|
</Link>
|
||||||
|
{!isTablet && (
|
||||||
|
<>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontWeight: 400,
|
||||||
|
lineHeight: "21.33px",
|
||||||
|
color: theme.palette.grey2.main,
|
||||||
|
fontSize: "16px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
или нажмите Enter
|
||||||
|
</Typography>
|
||||||
|
<EnterIcon
|
||||||
|
style={{
|
||||||
|
color: "#7E2AEA",
|
||||||
|
fontSize: "24px",
|
||||||
|
marginLeft: "6px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<ButtonsOptions switchState={switchState} SSHC={SSHC} question={question} />
|
||||||
|
<SwitchEmoji switchState={switchState} question={question} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
import {
|
import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
Box,
|
|
||||||
Link,
|
|
||||||
Typography,
|
|
||||||
useMediaQuery,
|
|
||||||
useTheme
|
|
||||||
} from "@mui/material";
|
|
||||||
import { addQuestionVariant, uploadQuestionImage } from "@root/questions/actions";
|
import { addQuestionVariant, uploadQuestionImage } from "@root/questions/actions";
|
||||||
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
|
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
|
||||||
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
|
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
|
||||||
@ -17,165 +11,153 @@ import { UploadImageModal } from "../UploadImage/UploadImageModal";
|
|||||||
import SwitchAnswerOptionsPict from "./switchOptionsPict";
|
import SwitchAnswerOptionsPict from "./switchOptionsPict";
|
||||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||||
import { useDisclosure } from "../../../utils/useDisclosure";
|
import { useDisclosure } from "../../../utils/useDisclosure";
|
||||||
|
import { useAddAnswer } from "../../../utils/hooks/useAddAnswer";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: QuizQuestionImages;
|
question: QuizQuestionImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function OptionsPicture({ question }: Props) {
|
export default function OptionsPicture({ question }: Props) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const quizQid = useCurrentQuiz()?.qid;
|
const onClickAddAnAnswer = useAddAnswer();
|
||||||
const [selectedVariantId, setSelectedVariantId] = useState<string | null>(null);
|
const quizQid = useCurrentQuiz()?.qid;
|
||||||
const [switchState, setSwitchState] = useState("setting");
|
const [selectedVariantId, setSelectedVariantId] = useState<string | null>(null);
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const [switchState, setSwitchState] = useState("setting");
|
||||||
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = useDisclosure();
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const {
|
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = useDisclosure();
|
||||||
isCropModalOpen,
|
const { isCropModalOpen, openCropModal, closeCropModal, imageBlob, originalImageUrl, setCropModalImageBlob } =
|
||||||
openCropModal,
|
useCropModalState();
|
||||||
closeCropModal,
|
|
||||||
imageBlob,
|
|
||||||
originalImageUrl,
|
|
||||||
setCropModalImageBlob,
|
|
||||||
} = useCropModalState();
|
|
||||||
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleImageUpload = async (file: File) => {
|
const handleImageUpload = async (file: File) => {
|
||||||
if (!selectedVariantId) return;
|
if (!selectedVariantId) return;
|
||||||
|
|
||||||
const url = await uploadQuestionImage(question.id, quizQid, file, (question, url) => {
|
const url = await uploadQuestionImage(question.id, quizQid, file, (question, url) => {
|
||||||
if (!("variants" in question.content)) return;
|
if (!("variants" in question.content)) return;
|
||||||
|
|
||||||
const variant = question.content.variants.find(variant => variant.id === selectedVariantId);
|
const variant = question.content.variants.find((variant) => variant.id === selectedVariantId);
|
||||||
if (!variant) return;
|
if (!variant) return;
|
||||||
|
|
||||||
variant.extendedText = url;
|
variant.extendedText = url;
|
||||||
variant.originalImageUrl = url;
|
variant.originalImageUrl = url;
|
||||||
});
|
});
|
||||||
closeImageUploadModal();
|
closeImageUploadModal();
|
||||||
openCropModal(file, url);
|
openCropModal(file, url);
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleCropModalSaveClick(imageBlob: Blob) {
|
function handleCropModalSaveClick(imageBlob: Blob) {
|
||||||
if (!selectedVariantId) return;
|
if (!selectedVariantId) return;
|
||||||
|
|
||||||
uploadQuestionImage(question.id, quizQid, imageBlob, (question, url) => {
|
uploadQuestionImage(question.id, quizQid, imageBlob, (question, url) => {
|
||||||
if (!("variants" in question.content)) return;
|
if (!("variants" in question.content)) return;
|
||||||
|
|
||||||
const variant = question.content.variants.find(variant => variant.id === selectedVariantId);
|
const variant = question.content.variants.find((variant) => variant.id === selectedVariantId);
|
||||||
if (!variant) return;
|
if (!variant) return;
|
||||||
|
|
||||||
variant.extendedText = url;
|
variant.extendedText = url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ padding: "20px" }}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
<AnswerDraggableList
|
<AnswerDraggableList
|
||||||
question={question}
|
question={question}
|
||||||
additionalContent={(variant) => (
|
additionalContent={(variant) => (
|
||||||
<>
|
<>
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<AddOrEditImageButton
|
<AddOrEditImageButton
|
||||||
imageSrc={variant.extendedText}
|
imageSrc={variant.extendedText}
|
||||||
onImageClick={() => {
|
onImageClick={() => {
|
||||||
setSelectedVariantId(variant.id);
|
setSelectedVariantId(variant.id);
|
||||||
if (variant.extendedText) {
|
if (variant.extendedText) {
|
||||||
return openCropModal(
|
return openCropModal(variant.extendedText, variant.originalImageUrl);
|
||||||
variant.extendedText,
|
}
|
||||||
variant.originalImageUrl
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
openImageUploadModal();
|
openImageUploadModal();
|
||||||
}}
|
}}
|
||||||
onPlusClick={() => {
|
onPlusClick={() => {
|
||||||
setSelectedVariantId(variant.id);
|
setSelectedVariantId(variant.id);
|
||||||
openImageUploadModal();
|
openImageUploadModal();
|
||||||
}}
|
}}
|
||||||
sx={{ mx: "10px" }}
|
sx={{ mx: "10px" }}
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
additionalMobile={(variant) => (
|
|
||||||
<>
|
|
||||||
{isMobile && (
|
|
||||||
<AddOrEditImageButton
|
|
||||||
imageSrc={variant.extendedText}
|
|
||||||
onImageClick={() => {
|
|
||||||
setSelectedVariantId(variant.id);
|
|
||||||
if (variant.extendedText) {
|
|
||||||
return openCropModal(
|
|
||||||
variant.extendedText,
|
|
||||||
variant.originalImageUrl
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
openImageUploadModal();
|
|
||||||
}}
|
|
||||||
onPlusClick={() => {
|
|
||||||
setSelectedVariantId(variant.id);
|
|
||||||
openImageUploadModal();
|
|
||||||
}}
|
|
||||||
sx={{ m: "8px", width: "auto" }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<UploadImageModal
|
)}
|
||||||
isOpen={isImageUploadOpen}
|
</>
|
||||||
onClose={closeImageUploadModal}
|
)}
|
||||||
handleImageChange={handleImageUpload}
|
additionalMobile={(variant) => (
|
||||||
/>
|
<>
|
||||||
<CropModal
|
{isMobile && (
|
||||||
isOpen={isCropModalOpen}
|
<AddOrEditImageButton
|
||||||
imageBlob={imageBlob}
|
imageSrc={variant.extendedText}
|
||||||
originalImageUrl={originalImageUrl}
|
onImageClick={() => {
|
||||||
setCropModalImageBlob={setCropModalImageBlob}
|
setSelectedVariantId(variant.id);
|
||||||
onClose={closeCropModal}
|
if (variant.extendedText) {
|
||||||
onSaveImageClick={handleCropModalSaveClick}
|
return openCropModal(variant.extendedText, variant.originalImageUrl);
|
||||||
/>
|
}
|
||||||
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
|
||||||
<Link
|
|
||||||
component="button"
|
|
||||||
variant="body2"
|
|
||||||
sx={{ color: theme.palette.brightPurple.main }}
|
|
||||||
onClick={() => addQuestionVariant(question.id)}
|
|
||||||
>
|
|
||||||
Добавьте ответ
|
|
||||||
</Link>
|
|
||||||
{isMobile ? null : (
|
|
||||||
<>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontWeight: 400,
|
|
||||||
lineHeight: "21.33px",
|
|
||||||
color: theme.palette.grey2.main,
|
|
||||||
fontSize: "16px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
или нажмите Enter
|
|
||||||
</Typography>
|
|
||||||
<EnterIcon
|
|
||||||
style={{
|
|
||||||
color: "#7E2AEA",
|
|
||||||
fontSize: "24px",
|
|
||||||
marginLeft: "6px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<ButtonsOptions switchState={switchState} SSHC={SSHC} question={question} />
|
|
||||||
<SwitchAnswerOptionsPict switchState={switchState} question={question} />
|
|
||||||
</>
|
|
||||||
|
|
||||||
);
|
openImageUploadModal();
|
||||||
|
}}
|
||||||
|
onPlusClick={() => {
|
||||||
|
setSelectedVariantId(variant.id);
|
||||||
|
openImageUploadModal();
|
||||||
|
}}
|
||||||
|
sx={{ m: "8px", width: "auto" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<UploadImageModal
|
||||||
|
isOpen={isImageUploadOpen}
|
||||||
|
onClose={closeImageUploadModal}
|
||||||
|
handleImageChange={handleImageUpload}
|
||||||
|
/>
|
||||||
|
<CropModal
|
||||||
|
isOpen={isCropModalOpen}
|
||||||
|
imageBlob={imageBlob}
|
||||||
|
originalImageUrl={originalImageUrl}
|
||||||
|
setCropModalImageBlob={setCropModalImageBlob}
|
||||||
|
onClose={closeCropModal}
|
||||||
|
onSaveImageClick={handleCropModalSaveClick}
|
||||||
|
/>
|
||||||
|
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
||||||
|
<Link
|
||||||
|
component="button"
|
||||||
|
variant="body2"
|
||||||
|
sx={{ color: theme.palette.brightPurple.main }}
|
||||||
|
onClick={() => onClickAddAnAnswer(question)}
|
||||||
|
>
|
||||||
|
Добавьте ответ
|
||||||
|
</Link>
|
||||||
|
{isMobile ? null : (
|
||||||
|
<>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontWeight: 400,
|
||||||
|
lineHeight: "21.33px",
|
||||||
|
color: theme.palette.grey2.main,
|
||||||
|
fontSize: "16px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
или нажмите Enter
|
||||||
|
</Typography>
|
||||||
|
<EnterIcon
|
||||||
|
style={{
|
||||||
|
color: "#7E2AEA",
|
||||||
|
fontSize: "24px",
|
||||||
|
marginLeft: "6px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<ButtonsOptions switchState={switchState} SSHC={SSHC} question={question} />
|
||||||
|
<SwitchAnswerOptionsPict switchState={switchState} question={question} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { VideofileIcon } from "@icons/questionsPage/VideofileIcon";
|
import { VideofileIcon } from "@icons/questionsPage/VideofileIcon";
|
||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Button, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
|
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
|
||||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||||
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
|
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
|
||||||
@ -14,253 +14,252 @@ import { UploadVideoModal } from "../UploadVideoModal";
|
|||||||
import SwitchPageOptions from "./switchPageOptions";
|
import SwitchPageOptions from "./switchPageOptions";
|
||||||
import { useDisclosure } from "../../../utils/useDisclosure";
|
import { useDisclosure } from "../../../utils/useDisclosure";
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
disableInput?: boolean;
|
disableInput?: boolean;
|
||||||
question: QuizQuestionPage;
|
question: QuizQuestionPage;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function PageOptions({ disableInput, question }: Props) {
|
export default function PageOptions({ disableInput, question }: Props) {
|
||||||
const [openVideoModal, setOpenVideoModal] = useState<boolean>(false);
|
const [openVideoModal, setOpenVideoModal] = useState<boolean>(false);
|
||||||
const [switchState, setSwitchState] = useState("setting");
|
const [switchState, setSwitchState] = useState("setting");
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(980));
|
const isTablet = useMediaQuery(theme.breakpoints.down(980));
|
||||||
const isFigmaTablet = useMediaQuery(theme.breakpoints.down(990));
|
const isFigmaTablet = useMediaQuery(theme.breakpoints.down(990));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(780));
|
const isMobile = useMediaQuery(theme.breakpoints.down(780));
|
||||||
const quizQid = useCurrentQuiz()?.qid;
|
const quizQid = useCurrentQuiz()?.qid;
|
||||||
const {
|
const { isCropModalOpen, openCropModal, closeCropModal, imageBlob, originalImageUrl, setCropModalImageBlob } =
|
||||||
isCropModalOpen,
|
useCropModalState();
|
||||||
openCropModal,
|
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = useDisclosure();
|
||||||
closeCropModal,
|
|
||||||
imageBlob,
|
|
||||||
originalImageUrl,
|
|
||||||
setCropModalImageBlob,
|
|
||||||
} = useCropModalState();
|
|
||||||
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = useDisclosure();
|
|
||||||
|
|
||||||
const setText = useDebouncedCallback((value) => {
|
const setText = useDebouncedCallback((value) => {
|
||||||
updateQuestion(question.id, question => {
|
updateQuestion(question.id, (question) => {
|
||||||
if (question.type !== "page") return;
|
if (question.type !== "page") return;
|
||||||
|
|
||||||
question.content.text = value;
|
question.content.text = value;
|
||||||
});
|
});
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function handleImageUpload(file: File) {
|
async function handleImageUpload(file: File) {
|
||||||
const url = await uploadQuestionImage(question.id, quizQid, file, (question, url) => {
|
const url = await uploadQuestionImage(question.id, quizQid, file, (question, url) => {
|
||||||
if (question.type !== "page") return;
|
if (question.type !== "page") return;
|
||||||
|
|
||||||
question.content.picture = url;
|
question.content.picture = url;
|
||||||
question.content.originalPicture = url;
|
question.content.originalPicture = url;
|
||||||
});
|
});
|
||||||
closeImageUploadModal();
|
closeImageUploadModal();
|
||||||
openCropModal(file, url);
|
openCropModal(file, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCropModalSaveClick(imageBlob: Blob) {
|
function handleCropModalSaveClick(imageBlob: Blob) {
|
||||||
uploadQuestionImage(question.id, quizQid, imageBlob, (question, url) => {
|
uploadQuestionImage(question.id, quizQid, imageBlob, (question, url) => {
|
||||||
if (question.type !== "page") return;
|
if (question.type !== "page") return;
|
||||||
|
|
||||||
question.content.picture = url;
|
question.content.picture = url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
console.log(question.content.useImage);
|
||||||
<>
|
|
||||||
<Box
|
return (
|
||||||
sx={{
|
<>
|
||||||
width: isTablet ? "auto" : "100%",
|
<Box
|
||||||
maxWidth: isFigmaTablet ? "549px" : "640px",
|
sx={{
|
||||||
display: "flex",
|
width: isTablet ? "auto" : "100%",
|
||||||
px: "20px",
|
maxWidth: isFigmaTablet ? "549px" : "640px",
|
||||||
flexDirection: "column",
|
display: "flex",
|
||||||
gap: isMobile ? "25px" : "20px",
|
px: "20px",
|
||||||
}}
|
flexDirection: "column",
|
||||||
|
gap: isMobile ? "25px" : "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box sx={{ display: disableInput ? "none" : "", mt: isMobile ? "15px" : "0px" }}>
|
||||||
|
<CustomTextField
|
||||||
|
placeholder={"Можно добавить текст"}
|
||||||
|
text={question.content.text}
|
||||||
|
onChange={({ target }) => setText(target.value)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
mb: "20px",
|
||||||
|
ml: isTablet ? "0px" : "60px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "28px",
|
||||||
|
justifyContent: isMobile ? "space-between" : null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
cursor: "pointer",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AddOrEditImageButton
|
||||||
|
imageSrc={question.content.picture}
|
||||||
|
onImageClick={() => {
|
||||||
|
if (question.content.picture) {
|
||||||
|
return openCropModal(question.content.picture, question.content.originalPicture);
|
||||||
|
}
|
||||||
|
|
||||||
|
openImageUploadModal();
|
||||||
|
}}
|
||||||
|
onPlusClick={() => {
|
||||||
|
openImageUploadModal();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
display: isMobile ? "none" : "block",
|
||||||
|
fontWeight: 400,
|
||||||
|
fontSize: "16px",
|
||||||
|
lineHeight: "18.96px",
|
||||||
|
color: question.content.useImage ? "#7E2AEA" : "#9A9AAF",
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
updateQuestion(question.id, (question) => ((question as QuizQuestionPage).content.useImage = true))
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: disableInput ? "none" : "", mt: isMobile ? "15px" : "0px" }}>
|
Изображение
|
||||||
<CustomTextField
|
</Typography>
|
||||||
placeholder={"Можно добавить текст"}
|
</Box>
|
||||||
text={question.content.text}
|
<UploadImageModal
|
||||||
onChange={({ target }) => setText(target.value)}
|
isOpen={isImageUploadOpen}
|
||||||
/>
|
onClose={closeImageUploadModal}
|
||||||
</Box>
|
handleImageChange={handleImageUpload}
|
||||||
|
/>
|
||||||
|
<CropModal
|
||||||
|
isOpen={isCropModalOpen}
|
||||||
|
imageBlob={imageBlob}
|
||||||
|
originalImageUrl={originalImageUrl}
|
||||||
|
setCropModalImageBlob={setCropModalImageBlob}
|
||||||
|
onClose={closeCropModal}
|
||||||
|
onSaveImageClick={handleCropModalSaveClick}
|
||||||
|
/>
|
||||||
|
<Typography> или</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
cursor: "pointer",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isMobile ? (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "120px",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
mb: "20px",
|
width: "100%",
|
||||||
ml: isTablet ? "0px" : "60px",
|
background: "#EEE4FC",
|
||||||
display: "flex",
|
height: "40px",
|
||||||
alignItems: "center",
|
display: "flex",
|
||||||
gap: "28px",
|
alignItems: "center",
|
||||||
justifyContent: isMobile ? "space-between" : null,
|
justifyContent: "center",
|
||||||
}}
|
borderTopLeftRadius: "4px",
|
||||||
|
borderBottomLeftRadius: "4px",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<VideofileIcon
|
||||||
sx={{
|
style={{
|
||||||
cursor: "pointer",
|
color: "#7E2AEA",
|
||||||
display: "flex",
|
fontSize: "20px",
|
||||||
alignItems: "center",
|
}}
|
||||||
gap: "20px",
|
/>
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AddOrEditImageButton
|
|
||||||
imageSrc={question.content.picture}
|
|
||||||
onImageClick={() => {
|
|
||||||
if (question.content.picture) {
|
|
||||||
return openCropModal(
|
|
||||||
question.content.picture,
|
|
||||||
question.content.originalPicture
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
openImageUploadModal();
|
|
||||||
}}
|
|
||||||
onPlusClick={() => {
|
|
||||||
openImageUploadModal();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
display: isMobile ? "none" : "block",
|
|
||||||
fontWeight: 400,
|
|
||||||
fontSize: "16px",
|
|
||||||
lineHeight: "18.96px",
|
|
||||||
color: theme.palette.grey2.main,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Изображение
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<UploadImageModal
|
|
||||||
isOpen={isImageUploadOpen}
|
|
||||||
onClose={closeImageUploadModal}
|
|
||||||
handleImageChange={handleImageUpload}
|
|
||||||
/>
|
|
||||||
<CropModal
|
|
||||||
isOpen={isCropModalOpen}
|
|
||||||
imageBlob={imageBlob}
|
|
||||||
originalImageUrl={originalImageUrl}
|
|
||||||
setCropModalImageBlob={setCropModalImageBlob}
|
|
||||||
onClose={closeCropModal}
|
|
||||||
onSaveImageClick={handleCropModalSaveClick}
|
|
||||||
/>
|
|
||||||
<Typography> или</Typography>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "10px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isMobile ? (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
width: "120px",
|
|
||||||
position: "relative",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
background: "#EEE4FC",
|
|
||||||
height: "40px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
borderTopLeftRadius: "4px",
|
|
||||||
borderBottomLeftRadius: "4px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<VideofileIcon
|
|
||||||
style={{
|
|
||||||
color: "#7E2AEA",
|
|
||||||
fontSize: "20px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
width: "20px",
|
|
||||||
background: "#EEE4FC",
|
|
||||||
height: "40px",
|
|
||||||
color: "white",
|
|
||||||
backgroundColor: "#7E2AEA",
|
|
||||||
borderTopRightRadius: "4px",
|
|
||||||
borderBottomRightRadius: "4px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "60px",
|
|
||||||
height: "40px",
|
|
||||||
background: "#EEE4FC",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", width: "100%" }}>
|
|
||||||
<VideofileIcon fontSize="22px" color="#7E2AEA" />
|
|
||||||
</Box>
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
background: "#7E2AEA",
|
|
||||||
height: "100%",
|
|
||||||
width: "25px",
|
|
||||||
color: "white",
|
|
||||||
fontSize: "15px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</span>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
display: isMobile ? "none" : "block",
|
|
||||||
fontWeight: 400,
|
|
||||||
fontSize: "16px",
|
|
||||||
lineHeight: "18.96px",
|
|
||||||
color: theme.palette.grey2.main,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Видео
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<UploadVideoModal
|
|
||||||
open={openVideoModal}
|
|
||||||
onClose={() => setOpenVideoModal(false)}
|
|
||||||
video={question.content.video}
|
|
||||||
onUpload={(url) => {
|
|
||||||
updateQuestion(question.id, question => {
|
|
||||||
if (question.type !== "page") return;
|
|
||||||
|
|
||||||
question.content.video = url;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
<Box
|
||||||
<ButtonsOptions switchState={switchState} SSHC={SSHC} question={question} />
|
sx={{
|
||||||
<SwitchPageOptions switchState={switchState} question={question} />
|
display: "flex",
|
||||||
</>
|
justifyContent: "center",
|
||||||
);
|
alignItems: "center",
|
||||||
|
width: "20px",
|
||||||
|
background: "#EEE4FC",
|
||||||
|
height: "40px",
|
||||||
|
color: "white",
|
||||||
|
backgroundColor: "#7E2AEA",
|
||||||
|
borderTopRightRadius: "4px",
|
||||||
|
borderBottomRightRadius: "4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "60px",
|
||||||
|
height: "40px",
|
||||||
|
background: "#EEE4FC",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", width: "100%" }}>
|
||||||
|
<VideofileIcon fontSize="22px" color="#7E2AEA" />
|
||||||
|
</Box>
|
||||||
|
<span
|
||||||
|
onClick={() => setOpenVideoModal(true)}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
background: "#7E2AEA",
|
||||||
|
height: "100%",
|
||||||
|
width: "25px",
|
||||||
|
color: "white",
|
||||||
|
fontSize: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</span>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
display: isMobile ? "none" : "block",
|
||||||
|
fontWeight: 400,
|
||||||
|
fontSize: "16px",
|
||||||
|
lineHeight: "18.96px",
|
||||||
|
color: question.content.useImage ? "#9A9AAF" : "#7E2AEA",
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
updateQuestion(question.id, (question) => ((question as QuizQuestionPage).content.useImage = false))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Видео
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<UploadVideoModal
|
||||||
|
open={openVideoModal}
|
||||||
|
onClose={() => setOpenVideoModal(false)}
|
||||||
|
video={question.content.video}
|
||||||
|
onUpload={(url) => {
|
||||||
|
updateQuestion(question.id, (question) => {
|
||||||
|
if (question.type !== "page") return;
|
||||||
|
|
||||||
|
question.content.video = url;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<ButtonsOptions switchState={switchState} SSHC={SSHC} question={question} />
|
||||||
|
<SwitchPageOptions switchState={switchState} question={question} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
import {
|
import { Box, Button, ButtonBase, Modal, Typography, useTheme } from "@mui/material";
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
ButtonBase,
|
|
||||||
Modal,
|
|
||||||
Typography,
|
|
||||||
useTheme,
|
|
||||||
} from "@mui/material";
|
|
||||||
import SelectableButton from "@ui_kit/SelectableButton";
|
import SelectableButton from "@ui_kit/SelectableButton";
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
@ -22,14 +15,8 @@ type HelpQuestionsProps = {
|
|||||||
onUpload: (number: string) => void;
|
onUpload: (number: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UploadVideoModal = ({
|
export const UploadVideoModal = ({ open, onClose, video, onUpload }: HelpQuestionsProps) => {
|
||||||
open,
|
const [backgroundTypeModal, setBackgroundTypeModal] = useState<BackgroundTypeModal>("linkVideo");
|
||||||
onClose,
|
|
||||||
video,
|
|
||||||
onUpload,
|
|
||||||
}: HelpQuestionsProps) => {
|
|
||||||
const [backgroundTypeModal, setBackgroundTypeModal] =
|
|
||||||
useState<BackgroundTypeModal>("linkVideo");
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
|
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
|
||||||
@ -42,12 +29,7 @@ export const UploadVideoModal = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal open={open} onClose={onClose} aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description">
|
||||||
open={open}
|
|
||||||
onClose={onClose}
|
|
||||||
aria-labelledby="modal-modal-title"
|
|
||||||
aria-describedby="modal-modal-description"
|
|
||||||
>
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
@ -70,10 +52,11 @@ export const UploadVideoModal = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography sx={{ color: "#9A9AAF" }}>
|
<Typography sx={{ color: "#9A9AAF" }}>
|
||||||
Видео можно вставить с любого хостинга: YouTube, Vimeo или загрузить
|
Видео можно вставить с любого хостинга: YouTube, Vimeo или загрузить собственное
|
||||||
собственное
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button variant="contained">Готово</Button>
|
<Button onClick={onClose} variant="contained">
|
||||||
|
Готово
|
||||||
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ padding: "20px", gap: "10px", display: "flex" }}>
|
<Box sx={{ padding: "20px", gap: "10px", display: "flex" }}>
|
||||||
<SelectableButton
|
<SelectableButton
|
||||||
@ -93,9 +76,7 @@ export const UploadVideoModal = ({
|
|||||||
</Box>
|
</Box>
|
||||||
{backgroundTypeModal === "linkVideo" ? (
|
{backgroundTypeModal === "linkVideo" ? (
|
||||||
<Box sx={{ padding: "20px" }}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
<Typography sx={{ paddingBottom: "15px", fontWeight: "500" }}>
|
<Typography sx={{ paddingBottom: "15px", fontWeight: "500" }}>Ссылка на видео</Typography>
|
||||||
Ссылка на видео
|
|
||||||
</Typography>
|
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"http://example.com"}
|
placeholder={"http://example.com"}
|
||||||
text={video}
|
text={video}
|
||||||
@ -104,13 +85,8 @@ export const UploadVideoModal = ({
|
|||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Box sx={{ padding: "20px" }}>
|
<Box sx={{ padding: "20px" }}>
|
||||||
<Typography sx={{ paddingBottom: "15px", fontWeight: "500" }}>
|
<Typography sx={{ paddingBottom: "15px", fontWeight: "500" }}>Загрузите видео</Typography>
|
||||||
Загрузите видео
|
<ButtonBase component="label" sx={{ justifyContent: "flex-start", width: "100%" }}>
|
||||||
</Typography>
|
|
||||||
<ButtonBase
|
|
||||||
component="label"
|
|
||||||
sx={{ justifyContent: "flex-start", width: "100%" }}
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
onChange={({ target }) => {
|
onChange={({ target }) => {
|
||||||
if (target.files?.length) {
|
if (target.files?.length) {
|
||||||
@ -123,9 +99,7 @@ export const UploadVideoModal = ({
|
|||||||
type="file"
|
type="file"
|
||||||
/>
|
/>
|
||||||
<Box
|
<Box
|
||||||
onDragOver={(event: DragEvent<HTMLDivElement>) =>
|
onDragOver={(event: DragEvent<HTMLDivElement>) => event.preventDefault()}
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
onDrop={handleDrop}
|
onDrop={handleDrop}
|
||||||
sx={{
|
sx={{
|
||||||
width: "580px",
|
width: "580px",
|
||||||
@ -140,12 +114,8 @@ export const UploadVideoModal = ({
|
|||||||
>
|
>
|
||||||
<UploadIcon />
|
<UploadIcon />
|
||||||
<Box sx={{ color: "#9A9AAF" }}>
|
<Box sx={{ color: "#9A9AAF" }}>
|
||||||
<Typography sx={{ fontWeight: "500" }}>
|
<Typography sx={{ fontWeight: "500" }}>Добавить видео</Typography>
|
||||||
Добавить видео
|
<Typography sx={{ fontSize: "16px" }}>Принимает .mp4 и .mov формат — максимум 100мб</Typography>
|
||||||
</Typography>
|
|
||||||
<Typography sx={{ fontSize: "16px" }}>
|
|
||||||
Принимает .mp4 и .mov формат — максимум 100мб
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
|
@ -6,90 +6,87 @@ import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict";
|
|||||||
import SwitchAnswerOptions from "./switchAnswerOptions";
|
import SwitchAnswerOptions from "./switchAnswerOptions";
|
||||||
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
|
import type { QuizQuestionVariant } from "../../../model/questionTypes/variant";
|
||||||
import { addQuestionVariant } from "@root/questions/actions";
|
import { addQuestionVariant } from "@root/questions/actions";
|
||||||
|
import { useAddAnswer } from "../../../utils/hooks/useAddAnswer";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
question: QuizQuestionVariant;
|
question: QuizQuestionVariant;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AnswerOptions({ question }: Props) {
|
export default function AnswerOptions({ question }: Props) {
|
||||||
const [switchState, setSwitchState] = useState("setting");
|
const onClickAddAnAnswer = useAddAnswer();
|
||||||
const theme = useTheme();
|
const [switchState, setSwitchState] = useState("setting");
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const theme = useTheme();
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
|
|
||||||
const SSHC = (data: string) => {
|
const SSHC = (data: string) => {
|
||||||
setSwitchState(data);
|
setSwitchState(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ padding: "0 20px 20px 20px" }}>
|
<Box sx={{ padding: "0 20px 20px 20px" }}>
|
||||||
{question.content.variants.length === 0 ? (
|
{question.content.variants.length === 0 ? (
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
padding: "0 0 33px 80px",
|
padding: "0 0 33px 80px",
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
fontSize: "18px",
|
fontSize: "18px",
|
||||||
lineHeight: "21.33px",
|
lineHeight: "21.33px",
|
||||||
color: theme.palette.grey2.main,
|
color: theme.palette.grey2.main,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Добавьте ответ
|
Добавьте ответ
|
||||||
</Typography>
|
</Typography>
|
||||||
) : (
|
) : (
|
||||||
<AnswerDraggableList question={question} />
|
<AnswerDraggableList question={question} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
marginBottom: "17px",
|
marginBottom: "17px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
component="button"
|
component="button"
|
||||||
variant="body2"
|
variant="body2"
|
||||||
sx={{
|
sx={{
|
||||||
color: theme.palette.brightPurple.main,
|
color: theme.palette.brightPurple.main,
|
||||||
fontWeight: "400",
|
fontWeight: "400",
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
mr: "4px",
|
mr: "4px",
|
||||||
height: "19px",
|
height: "19px",
|
||||||
}}
|
}}
|
||||||
onClick={() => addQuestionVariant(question.id)}
|
onClick={() => onClickAddAnAnswer(question)}
|
||||||
>
|
>
|
||||||
Добавьте ответ
|
Добавьте ответ
|
||||||
</Link>
|
</Link>
|
||||||
{isMobile ? null : (
|
{isMobile ? null : (
|
||||||
<>
|
<>
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
lineHeight: "21.33px",
|
lineHeight: "21.33px",
|
||||||
color: theme.palette.grey2.main,
|
color: theme.palette.grey2.main,
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
или нажмите Enter
|
или нажмите Enter
|
||||||
</Typography>
|
</Typography>
|
||||||
<EnterIcon
|
<EnterIcon
|
||||||
style={{
|
style={{
|
||||||
color: "#7E2AEA",
|
color: "#7E2AEA",
|
||||||
fontSize: "24px",
|
fontSize: "24px",
|
||||||
marginLeft: "6px",
|
marginLeft: "6px",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<ButtonsOptionsAndPict
|
<ButtonsOptionsAndPict switchState={switchState} SSHC={SSHC} question={question} />
|
||||||
switchState={switchState}
|
<SwitchAnswerOptions switchState={switchState} question={question} />
|
||||||
SSHC={SSHC}
|
</>
|
||||||
question={question}
|
);
|
||||||
/>
|
|
||||||
<SwitchAnswerOptions switchState={switchState} question={question} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -12,45 +12,48 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
import { WhenCard } from "./cards/WhenCard";
|
import { WhenCard } from "./cards/WhenCard";
|
||||||
import { ResultCard, checkEmptyData } from "./cards/ResultCard";
|
import { ResultCard, checkEmptyData } from "./cards/ResultCard";
|
||||||
import { EmailSettingsCard } from "./cards/EmailSettingsCard";
|
import { EmailSettingsCard } from "./cards/EmailSettingsCard";
|
||||||
import { useCurrentQuiz } from "@root/quizes/hooks"
|
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||||
import { useQuestionsStore } from "@root/questions/store";
|
import { useQuestionsStore } from "@root/questions/store";
|
||||||
import { createFrontResult, deleteQuestion } from "@root/questions/actions";
|
import { createFrontResult, deleteQuestion } from "@root/questions/actions";
|
||||||
import { QuizQuestionResult } from "@model/questionTypes/result";
|
import { QuizQuestionResult } from "@model/questionTypes/result";
|
||||||
|
|
||||||
export const ResultSettings = () => {
|
export const ResultSettings = () => {
|
||||||
const { questions } = useQuestionsStore()
|
const { questions } = useQuestionsStore();
|
||||||
const quiz = useCurrentQuiz()
|
const quiz = useCurrentQuiz();
|
||||||
const results = useQuestionsStore().questions.filter((q): q is QuizQuestionResult => q.type === "result")
|
const results = useQuestionsStore().questions.filter((q): q is QuizQuestionResult => q.type === "result");
|
||||||
const [quizExpand, setQuizExpand] = useState(true)
|
const [quizExpand, setQuizExpand] = useState(true);
|
||||||
const [resultContract, setResultContract] = useState(true)
|
const [resultContract, setResultContract] = useState(true);
|
||||||
const isReadyToLeaveRef = useRef(true);
|
const isReadyToLeaveRef = useRef(true);
|
||||||
|
|
||||||
useEffect(function calcIsReadyToLeave(){
|
useEffect(
|
||||||
let isReadyToLeave = true;
|
function calcIsReadyToLeave() {
|
||||||
results.forEach((result) => {
|
let isReadyToLeave = true;
|
||||||
if (checkEmptyData({ resultData: result })) {
|
results.forEach((result) => {
|
||||||
isReadyToLeave = false;
|
if (checkEmptyData({ resultData: result })) {
|
||||||
}
|
isReadyToLeave = false;
|
||||||
});
|
}
|
||||||
isReadyToLeaveRef.current = isReadyToLeave;
|
});
|
||||||
}, [results])
|
isReadyToLeaveRef.current = isReadyToLeave;
|
||||||
|
},
|
||||||
|
[results]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
if (isReadyToLeaveRef.current === false) alert("Пожалуйста, проверьте, что вы заполнили все результаты");
|
if (isReadyToLeaveRef.current === false) alert("Пожалуйста, проверьте, что вы заполнили все результаты");
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ maxWidth: "796px" }}>
|
<Box sx={{ maxWidth: "796px" }}>
|
||||||
<Box sx={{
|
<Box
|
||||||
display: "flex",
|
sx={{
|
||||||
alignItems: "center",
|
display: "flex",
|
||||||
margin: "60px 0 40px 0",
|
alignItems: "center",
|
||||||
}}>
|
margin: "60px 0 40px 0",
|
||||||
<Typography variant="h5">
|
}}
|
||||||
Настройки результатов
|
>
|
||||||
</Typography>
|
<Typography variant="h5">Настройки результатов</Typography>
|
||||||
<Info />
|
<Info />
|
||||||
<Button
|
<Button
|
||||||
disableRipple
|
disableRipple
|
||||||
@ -73,14 +76,10 @@ export const ResultSettings = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
<WhenCard quizExpand={quizExpand} />
|
<WhenCard quizExpand={quizExpand} />
|
||||||
{quiz.config.resultInfo.when === "email" && <EmailSettingsCard quizExpand={quizExpand} />}
|
{quiz.config.resultInfo.when === "email" && <EmailSettingsCard quizExpand={quizExpand} />}
|
||||||
|
|
||||||
|
<Box sx={{ display: "flex", alignItems: "center", mb: "15px", mt: "15px" }}>
|
||||||
<Box
|
|
||||||
sx={{ display: "flex", alignItems: "center", mb: "15px", mt: "15px" }}
|
|
||||||
>
|
|
||||||
<Typography variant="p1" sx={{ color: "#4D4D4D", fontSize: "14px" }}>
|
<Typography variant="p1" sx={{ color: "#4D4D4D", fontSize: "14px" }}>
|
||||||
Создайте результат
|
Создайте результат
|
||||||
</Typography>
|
</Typography>
|
||||||
@ -105,9 +104,9 @@ export const ResultSettings = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{
|
{results.map((resultQuestion) => (
|
||||||
results.map((resultQuestion) => <ResultCard resultContract={resultContract} resultData={resultQuestion} key={resultQuestion.id} />)
|
<ResultCard resultContract={resultContract} resultData={resultQuestion} key={resultQuestion.id} />
|
||||||
}
|
))}
|
||||||
<Modal
|
<Modal
|
||||||
open={false}
|
open={false}
|
||||||
// onClose={handleClose}
|
// onClose={handleClose}
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import { Box, Button, IconButton, SxProps, Theme, Typography, useTheme, useMediaQuery } from "@mui/material";
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
IconButton,
|
|
||||||
SxProps,
|
|
||||||
Theme,
|
|
||||||
Typography,
|
|
||||||
useTheme,
|
|
||||||
useMediaQuery,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { SwitchSetting } from "./SwichResult";
|
import { SwitchSetting } from "./SwichResult";
|
||||||
|
|
||||||
import Info from "@icons/Info";
|
import Info from "@icons/Info";
|
||||||
@ -92,13 +83,7 @@ export const SettingForm = () => {
|
|||||||
Показывать результат
|
Показывать результат
|
||||||
</Typography>
|
</Typography>
|
||||||
<IconButton>
|
<IconButton>
|
||||||
<svg
|
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="30"
|
|
||||||
height="30"
|
|
||||||
viewBox="0 0 30 30"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<rect width="30" height="30" rx="6" fill="#EEE4FC" />
|
<rect width="30" height="30" rx="6" fill="#EEE4FC" />
|
||||||
<path
|
<path
|
||||||
d="M22.5 11.25L15 18.75L7.5 11.25"
|
d="M22.5 11.25L15 18.75L7.5 11.25"
|
||||||
@ -136,27 +121,16 @@ export const SettingForm = () => {
|
|||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
{typeActive === "e-mail" ? (
|
{typeActive === "e-mail" ? (
|
||||||
<SwitchSetting
|
<SwitchSetting icon={listChecks} text="Показывать несколько результатов" />
|
||||||
icon={listChecks}
|
|
||||||
text="Показывать несколько результатов"
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<SwitchSetting
|
<SwitchSetting icon={listChecks} text="Показывать несколько результатов" />
|
||||||
icon={listChecks}
|
|
||||||
text="Показывать несколько результатов"
|
|
||||||
/>
|
|
||||||
<SwitchSetting icon={ShareNetwork} text="Поделиться результатами" />
|
<SwitchSetting icon={ShareNetwork} text="Поделиться результатами" />
|
||||||
<SwitchSetting
|
<SwitchSetting icon={ArrowCounterClockWise} text="Кнопка `Пройти тест заново`" />
|
||||||
icon={ArrowCounterClockWise}
|
|
||||||
text="Кнопка `Пройти тест заново`"
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box sx={{ display: "flex", alignItems: "center", mb: "15px", mt: "15px" }}>
|
||||||
sx={{ display: "flex", alignItems: "center", mb: "15px", mt: "15px" }}
|
|
||||||
>
|
|
||||||
<Typography variant="p1" sx={{ color: "#4D4D4D", fontSize: "14px" }}>
|
<Typography variant="p1" sx={{ color: "#4D4D4D", fontSize: "14px" }}>
|
||||||
Создайте результат
|
Создайте результат
|
||||||
</Typography>
|
</Typography>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import { getQuestionByContentId, updateQuestion, uploadQuestionImage } from "@root/questions/actions"
|
import { getQuestionByContentId, updateQuestion, uploadQuestionImage } from "@root/questions/actions";
|
||||||
import { useCurrentQuiz } from "@root/quizes/hooks"
|
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||||
|
|
||||||
|
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
|
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
|
||||||
@ -20,7 +19,7 @@ import {
|
|||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
FormControl,
|
FormControl,
|
||||||
Popover
|
Popover,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const checkEmptyData = ({ resultData }: { resultData: QuizQuestionResult }) => {
|
export const checkEmptyData = ({ resultData }: { resultData: QuizQuestionResult }) => {
|
||||||
let check = true
|
let check = true;
|
||||||
if (
|
if (
|
||||||
resultData.title.length > 0 ||
|
resultData.title.length > 0 ||
|
||||||
resultData.description.length > 0 ||
|
resultData.description.length > 0 ||
|
||||||
@ -48,13 +47,14 @@ export const checkEmptyData = ({ resultData }: { resultData: QuizQuestionResult
|
|||||||
resultData.content.text.length > 0 ||
|
resultData.content.text.length > 0 ||
|
||||||
resultData.content.video.length > 0 ||
|
resultData.content.video.length > 0 ||
|
||||||
resultData.content.hint.text.length > 0
|
resultData.content.hint.text.length > 0
|
||||||
) check = false
|
)
|
||||||
return check
|
check = false;
|
||||||
}
|
return check;
|
||||||
|
};
|
||||||
|
|
||||||
const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
|
const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
|
||||||
const checkEmpty = checkEmptyData({ resultData })
|
const checkEmpty = checkEmptyData({ resultData });
|
||||||
const question = getQuestionByContentId(resultData.content.rule.parentId)
|
const question = getQuestionByContentId(resultData.content.rule.parentId);
|
||||||
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);
|
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);
|
||||||
|
|
||||||
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
@ -66,20 +66,18 @@ const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const open = Boolean(anchorEl);
|
const open = Boolean(anchorEl);
|
||||||
const id = open ? 'simple-popover' : undefined;
|
const id = open ? "simple-popover" : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Info
|
<Info
|
||||||
sx={{
|
sx={{
|
||||||
"MuiIconButton-root": {
|
"MuiIconButton-root": {
|
||||||
|
boxShadow: "0 0 10px 10px red",
|
||||||
boxShadow: "0 0 10px 10px red"
|
},
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
className={checkEmpty ? "blink" : ""}
|
className={checkEmpty ? "blink" : ""}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
id={id}
|
id={id}
|
||||||
@ -87,40 +85,35 @@ const InfoView = ({ resultData }: { resultData: QuizQuestionResult }) => {
|
|||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: 'bottom',
|
vertical: "bottom",
|
||||||
horizontal: 'left',
|
horizontal: "left",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Paper
|
<Paper
|
||||||
sx={{
|
sx={{
|
||||||
p: '20px',
|
p: "20px",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
flexDirection: "column"
|
flexDirection: "column",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography>
|
<Typography>
|
||||||
{resultData?.content.rule.parentId === "line" ? "Единый результат в конце прохождения опросника без ветвления"
|
{resultData?.content.rule.parentId === "line"
|
||||||
:
|
? "Единый результат в конце прохождения опросника без ветвления"
|
||||||
`Заголовок вопроса, после которого появится результат: "${question?.title || "нет заголовка"}"`
|
: `Заголовок вопроса, после которого появится результат: "${question?.title || "нет заголовка"}"`}
|
||||||
}
|
|
||||||
|
|
||||||
</Typography>
|
</Typography>
|
||||||
{checkEmpty &&
|
{checkEmpty && <Typography color="red">Вы не заполнили этот результат никакими данными</Typography>}
|
||||||
<Typography color="red">
|
|
||||||
Вы не заполнили этот результат никакими данными
|
|
||||||
</Typography>
|
|
||||||
}
|
|
||||||
|
|
||||||
</Paper>
|
</Paper>
|
||||||
</Popover>
|
</Popover>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ResultCard = ({ resultContract, resultData }: Props) => {
|
export const ResultCard = ({ resultContract, resultData }: Props) => {
|
||||||
console.log("resultData", resultData)
|
console.log("resultData", resultData);
|
||||||
|
|
||||||
|
console.log(resultData.content.video);
|
||||||
|
|
||||||
const quizQid = useCurrentQuiz()?.qid;
|
const quizQid = useCurrentQuiz()?.qid;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -128,30 +121,20 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(800));
|
const isTablet = useMediaQuery(theme.breakpoints.down(800));
|
||||||
|
|
||||||
const [expand, setExpand] = React.useState(true)
|
const [expand, setExpand] = React.useState(true);
|
||||||
const [resultCardSettings, setResultCardSettings] = React.useState(false)
|
const [resultCardSettings, setResultCardSettings] = React.useState(false);
|
||||||
const [buttonPlus, setButtonPlus] = React.useState(true)
|
const [buttonPlus, setButtonPlus] = React.useState(true);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setExpand(true)
|
setExpand(true);
|
||||||
}, [resultContract])
|
}, [resultContract]);
|
||||||
|
|
||||||
|
const { isCropModalOpen, openCropModal, closeCropModal, imageBlob, originalImageUrl, setCropModalImageBlob } =
|
||||||
const {
|
useCropModalState();
|
||||||
isCropModalOpen,
|
|
||||||
openCropModal,
|
|
||||||
closeCropModal,
|
|
||||||
imageBlob,
|
|
||||||
originalImageUrl,
|
|
||||||
setCropModalImageBlob,
|
|
||||||
} = useCropModalState();
|
|
||||||
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = useDisclosure();
|
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = useDisclosure();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function handleImageUpload(file: File) {
|
async function handleImageUpload(file: File) {
|
||||||
const url = await uploadQuestionImage(resultData.id, quizQid, file, (question, url) => {
|
const url = await uploadQuestionImage(resultData.id, quizQid, file, (question, url) => {
|
||||||
|
|
||||||
question.content.back = url;
|
question.content.back = url;
|
||||||
question.content.originalBack = url;
|
question.content.originalBack = url;
|
||||||
});
|
});
|
||||||
@ -165,9 +148,6 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
data-cy="quiz-question-card"
|
data-cy="quiz-question-card"
|
||||||
@ -178,7 +158,7 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
backgroundColor: expand ? "white" : "#EEE4FC",
|
backgroundColor: expand ? "white" : "#EEE4FC",
|
||||||
border: expand ? "none" : "1px solid #9A9AAF",
|
border: expand ? "none" : "1px solid #9A9AAF",
|
||||||
boxShadow: "0px 10px 30px #e7e7e7",
|
boxShadow: "0px 10px 30px #e7e7e7",
|
||||||
m: "20px 0"
|
m: "20px 0",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
@ -189,7 +169,6 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
flexDirection: isMobile ? "column" : null,
|
flexDirection: isMobile ? "column" : null,
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
minHeight: "40px",
|
minHeight: "40px",
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FormControl
|
<FormControl
|
||||||
@ -204,14 +183,14 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
<TextField
|
<TextField
|
||||||
value={resultData.title}
|
value={resultData.title}
|
||||||
placeholder={"Заголовок результата"}
|
placeholder={"Заголовок результата"}
|
||||||
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, question => question.title = target.value)}
|
onChange={({ target }: { target: HTMLInputElement }) =>
|
||||||
|
updateQuestion(resultData.id, (question) => (question.title = target.value))
|
||||||
|
}
|
||||||
sx={{
|
sx={{
|
||||||
margin: isMobile ? "10px 0" : 0,
|
margin: isMobile ? "10px 0" : 0,
|
||||||
"& .MuiInputBase-root": {
|
"& .MuiInputBase-root": {
|
||||||
color: "#000000",
|
color: "#000000",
|
||||||
backgroundColor: expand
|
backgroundColor: expand ? theme.palette.background.default : "transparent",
|
||||||
? theme.palette.background.default
|
|
||||||
: "transparent",
|
|
||||||
height: "48px",
|
height: "48px",
|
||||||
borderRadius: "10px",
|
borderRadius: "10px",
|
||||||
".MuiOutlinedInput-notchedOutline": {
|
".MuiOutlinedInput-notchedOutline": {
|
||||||
@ -292,7 +271,10 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
<CustomTextField
|
<CustomTextField
|
||||||
value={resultData.title}
|
value={resultData.title}
|
||||||
placeholder={"Заголовок результата"}
|
placeholder={"Заголовок результата"}
|
||||||
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, question => question.title = target.value)} />
|
onChange={({ target }: { target: HTMLInputElement }) =>
|
||||||
|
updateQuestion(resultData.id, (question) => (question.title = target.value))
|
||||||
|
}
|
||||||
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
sx={{ padding: "0", margin: "5px" }}
|
sx={{ padding: "0", margin: "5px" }}
|
||||||
disableRipple
|
disableRipple
|
||||||
@ -302,18 +284,18 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
<ExpandLessIconBG />
|
<ExpandLessIconBG />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<InfoView resultData={resultData} />
|
<InfoView resultData={resultData} />
|
||||||
|
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
margin: "20px 0"
|
margin: "20px 0",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
value={resultData.description}
|
value={resultData.description}
|
||||||
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.description = target.value)}
|
onChange={({ target }: { target: HTMLInputElement }) =>
|
||||||
|
updateQuestion(resultData.id, (question) => (question.description = target.value))
|
||||||
|
}
|
||||||
placeholder={"Заголовок пожирнее"}
|
placeholder={"Заголовок пожирнее"}
|
||||||
sx={{
|
sx={{
|
||||||
borderRadius: "8px",
|
borderRadius: "8px",
|
||||||
@ -324,9 +306,10 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
|
|
||||||
value={resultData.content.text}
|
value={resultData.content.text}
|
||||||
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.content.text = target.value)}
|
onChange={({ target }: { target: HTMLInputElement }) =>
|
||||||
|
updateQuestion(resultData.id, (question) => (question.content.text = target.value))
|
||||||
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="Описание"
|
placeholder="Описание"
|
||||||
multiline
|
multiline
|
||||||
@ -350,14 +333,12 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
mt: "20px",
|
mt: "20px",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
gap: "10px",
|
gap: "10px",
|
||||||
flexDirection: "column"
|
flexDirection: "column",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
@ -374,7 +355,7 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
variant="text"
|
variant="text"
|
||||||
onClick={() => updateQuestion(resultData.id, (question) => question.content.useImage = true)}
|
onClick={() => updateQuestion(resultData.id, (question) => (question.content.useImage = true))}
|
||||||
>
|
>
|
||||||
Изображение
|
Изображение
|
||||||
</Button>
|
</Button>
|
||||||
@ -387,7 +368,7 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
variant="text"
|
variant="text"
|
||||||
onClick={() => updateQuestion(resultData.id, (question) => question.content.useImage = false)}
|
onClick={() => updateQuestion(resultData.id, (question) => (question.content.useImage = false))}
|
||||||
>
|
>
|
||||||
Видео
|
Видео
|
||||||
</Button>
|
</Button>
|
||||||
@ -414,25 +395,21 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{
|
{resultData.content.useImage && (
|
||||||
resultData.content.useImage &&
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: "20px",
|
gap: "20px",
|
||||||
mb: "30px"
|
mb: "30px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AddOrEditImageButton
|
<AddOrEditImageButton
|
||||||
imageSrc={resultData.content.back}
|
imageSrc={resultData.content.back}
|
||||||
onImageClick={() => {
|
onImageClick={() => {
|
||||||
if (resultData.content.back) {
|
if (resultData.content.back) {
|
||||||
return openCropModal(
|
return openCropModal(resultData.content.back, resultData.content.originalBack);
|
||||||
resultData.content.back,
|
|
||||||
resultData.content.originalBack
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
openImageUploadModal();
|
openImageUploadModal();
|
||||||
@ -442,106 +419,99 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
)}
|
||||||
{
|
{!resultData.content.useImage && (
|
||||||
!resultData.content.useImage &&
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: "20px",
|
gap: "20px",
|
||||||
mb: "30px"
|
mb: "30px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder="URL видео"
|
placeholder="URL видео"
|
||||||
text={resultData.content.video ?? ""}
|
text={resultData.content.video ?? ""}
|
||||||
onChange={e => updateQuestion(resultData.id, q => {
|
onChange={(e) =>
|
||||||
q.content.video = e.target.value;
|
updateQuestion(resultData.id, (q) => {
|
||||||
})}
|
q.content.video = e.target.value;
|
||||||
|
})
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{buttonPlus ? (
|
||||||
|
<Button
|
||||||
{
|
onClick={() => {
|
||||||
buttonPlus ?
|
setButtonPlus(false);
|
||||||
<Button
|
}}
|
||||||
onClick={() => {
|
sx={{
|
||||||
setButtonPlus(false)
|
display: "inline flex",
|
||||||
}}
|
height: "48px",
|
||||||
sx={{
|
padding: "10px 20px",
|
||||||
display: "inline flex",
|
justifyContent: "center",
|
||||||
height: "48px",
|
alignItems: "center",
|
||||||
padding: "10px 20px",
|
gap: "8px",
|
||||||
justifyContent: "center",
|
flexShrink: 0,
|
||||||
alignItems: "center",
|
borderRadius: "8px",
|
||||||
gap: "8px",
|
border: "1px solid #9A9AAF",
|
||||||
flexShrink: 0,
|
background: " #F2F3F7",
|
||||||
borderRadius: "8px",
|
color: "#9A9AAF",
|
||||||
border: "1px solid #9A9AAF",
|
mb: "30px",
|
||||||
background: " #F2F3F7",
|
}}
|
||||||
color: "#9A9AAF",
|
>
|
||||||
mb: "30px"
|
Кнопка +
|
||||||
}}
|
</Button>
|
||||||
>
|
) : (
|
||||||
Кнопка +
|
<Box
|
||||||
</Button>
|
sx={{
|
||||||
:
|
mb: "30px",
|
||||||
<Box
|
}}
|
||||||
sx={{
|
>
|
||||||
mb: "30px"
|
<Box>
|
||||||
}}
|
<Typography component={"span"} sx={{ weight: "500", fontSize: "18px", mb: "10px" }}>
|
||||||
>
|
Призыв к действию
|
||||||
<Box>
|
</Typography>
|
||||||
<Typography component={"span"} sx={{ weight: "500", fontSize: "18px", mb: "10px" }}>
|
<IconButton
|
||||||
Призыв к действию
|
onClick={() => {
|
||||||
</Typography>
|
setButtonPlus(true);
|
||||||
<IconButton
|
updateQuestion(resultData.id, (q) => (q.content.hint.text = ""));
|
||||||
onClick={() => {
|
|
||||||
setButtonPlus(true)
|
|
||||||
updateQuestion(resultData.id, (q) => q.content.hint.text = "")
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Trash />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<TextField
|
|
||||||
value={resultData.content.hint.text}
|
|
||||||
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.content.hint.text = target.value)}
|
|
||||||
fullWidth
|
|
||||||
placeholder="Например: узнать подробнее"
|
|
||||||
sx={{
|
|
||||||
"& .MuiInputBase-root": {
|
|
||||||
backgroundColor: "#F2F3F7",
|
|
||||||
width: "409px",
|
|
||||||
height: "48px",
|
|
||||||
borderRadius: "8px",
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
inputProps={{
|
>
|
||||||
sx: {
|
<Trash />
|
||||||
height: "85px",
|
</IconButton>
|
||||||
borderRadius: "10px",
|
|
||||||
fontSize: "18px",
|
|
||||||
lineHeight: "21px",
|
|
||||||
py: 0,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
value={resultData.content.hint.text}
|
||||||
|
onChange={({ target }: { target: HTMLInputElement }) =>
|
||||||
|
updateQuestion(resultData.id, (question) => (question.content.hint.text = target.value))
|
||||||
|
}
|
||||||
|
fullWidth
|
||||||
|
placeholder="Например: узнать подробнее"
|
||||||
|
sx={{
|
||||||
|
"& .MuiInputBase-root": {
|
||||||
|
backgroundColor: "#F2F3F7",
|
||||||
|
width: "409px",
|
||||||
|
height: "48px",
|
||||||
|
borderRadius: "8px",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
inputProps={{
|
||||||
|
sx: {
|
||||||
|
height: "85px",
|
||||||
|
borderRadius: "10px",
|
||||||
|
fontSize: "18px",
|
||||||
|
lineHeight: "21px",
|
||||||
|
py: 0,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -561,50 +531,42 @@ export const ResultCard = ({ resultContract, resultData }: Props) => {
|
|||||||
>
|
>
|
||||||
<MiniButtonSetting
|
<MiniButtonSetting
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setResultCardSettings(!resultCardSettings)
|
setResultCardSettings(!resultCardSettings);
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor:
|
backgroundColor: resultCardSettings ? theme.palette.brightPurple.main : "transparent",
|
||||||
resultCardSettings
|
color: resultCardSettings ? "#ffffff" : theme.palette.grey3.main,
|
||||||
? theme.palette.brightPurple.main
|
|
||||||
: "transparent",
|
|
||||||
color:
|
|
||||||
resultCardSettings ? "#ffffff" : theme.palette.grey3.main,
|
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: resultCardSettings ? "#581CA7" : "#7E2AEA",
|
backgroundColor: resultCardSettings ? "#581CA7" : "#7E2AEA",
|
||||||
color: "white"
|
color: "white",
|
||||||
}
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SettingIcon
|
<SettingIcon color={resultCardSettings ? "#ffffff" : theme.palette.grey3.main} />
|
||||||
color={
|
|
||||||
resultCardSettings ? "#ffffff" : theme.palette.grey3.main
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{!isTablet && "Настройки"}
|
{!isTablet && "Настройки"}
|
||||||
</MiniButtonSetting>
|
</MiniButtonSetting>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
{
|
{resultCardSettings && (
|
||||||
resultCardSettings &&
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
p: "20px",
|
p: "20px",
|
||||||
borderRadius: "0 0 12px 12px"
|
borderRadius: "0 0 12px 12px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CustomTextField
|
<CustomTextField
|
||||||
placeholder={"Внутреннее описание вопроса"}
|
placeholder={"Внутреннее описание вопроса"}
|
||||||
value={resultData.innerName}
|
value={resultData.innerName}
|
||||||
onChange={({ target }: { target: HTMLInputElement; }) => updateQuestion(resultData.id, (question) => question.content.innerName = target.value)}
|
onChange={({ target }: { target: HTMLInputElement }) =>
|
||||||
|
updateQuestion(resultData.id, (question) => (question.content.innerName = target.value))
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)}
|
||||||
}
|
</Paper>
|
||||||
</Paper >
|
);
|
||||||
)
|
};
|
||||||
}
|
|
||||||
|
@ -46,7 +46,12 @@ export default function QuizCard({ quiz, openCount = 0, applicationCount = 0, co
|
|||||||
0px 2.76726px 8.55082px rgba(210, 208, 225, 0.0674749)`,
|
0px 2.76726px 8.55082px rgba(210, 208, 225, 0.0674749)`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="h5">{quiz.name}</Typography>
|
<Typography
|
||||||
|
sx={{ textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap", widows: "100%" }}
|
||||||
|
variant="h5"
|
||||||
|
>
|
||||||
|
{quiz.name}
|
||||||
|
</Typography>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
17
src/utils/hooks/useAddAnswer.ts
Normal file
17
src/utils/hooks/useAddAnswer.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { useSnackbar } from "notistack";
|
||||||
|
import { addQuestionVariant } from "@root/questions/actions";
|
||||||
|
import { QuizQuestionsWithVariants } from "@model/questionTypes/shared";
|
||||||
|
|
||||||
|
export const useAddAnswer = () => {
|
||||||
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
|
const onClickAddAnAnswer = (question: QuizQuestionsWithVariants) => {
|
||||||
|
if (question.content.variants.length >= 10) {
|
||||||
|
enqueueSnackbar("100 максимальное количество вопросов");
|
||||||
|
} else {
|
||||||
|
addQuestionVariant(question.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return onClickAddAnAnswer;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user