merge style in fixed
This commit is contained in:
commit
ed600b94a5
@ -17,6 +17,7 @@
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dnd": "^3.0.2",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"emoji-mart": "^5.5.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"html-to-image": "^1.11.11",
|
||||
"jszip": "^3.10.1",
|
||||
@ -71,6 +72,8 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emoji-mart/data": "^1.1.2",
|
||||
"@emoji-mart/react": "^1.1.1",
|
||||
"@types/react-beautiful-dnd": "^13.1.4",
|
||||
"craco-alias": "^3.0.1"
|
||||
}
|
||||
|
@ -1,26 +1,26 @@
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
export default function BackArrowIcon({ color = "black" }: { color?: string }) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
height: "24px",
|
||||
width: "24px",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M20.25 12H3.75" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path
|
||||
d="M10.5 5.25L3.75 12L10.5 18.75"
|
||||
stroke={color}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
height: "24px",
|
||||
width: "24px",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M20.25 12H3.75" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path
|
||||
d="M10.5 5.25L3.75 12L10.5 18.75"
|
||||
stroke={color}
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -6,4 +6,4 @@ export const Burger: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||
<path d="M28 16.1504H3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
|
||||
<path d="M28 24.1504H3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
);
|
||||
|
@ -1,30 +1,40 @@
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
|
||||
interface Props {
|
||||
height: string;
|
||||
width: string;
|
||||
color: string;
|
||||
height: string;
|
||||
width: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export default function ChartPieIcon({ height, width, color }: Props) {
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: "6px",
|
||||
height,
|
||||
width,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="35" height="35" viewBox="0 0 35 35" fill="none">
|
||||
<path d="M17.5 30.625C24.7487 30.625 30.625 24.7487 30.625 17.5C30.625 10.2513 24.7487 4.375 17.5 4.375C10.2513 4.375 4.375 10.2513 4.375 17.5C4.375 24.7487 10.2513 30.625 17.5 30.625Z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M17.5 17.5V4.375" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M28.8613 10.9375L6.13867 24.0625" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: "6px",
|
||||
height,
|
||||
width,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="35" height="35" viewBox="0 0 35 35" fill="none">
|
||||
<path
|
||||
d="M17.5 30.625C24.7487 30.625 30.625 24.7487 30.625 17.5C30.625 10.2513 24.7487 4.375 17.5 4.375C10.2513 4.375 4.375 10.2513 4.375 17.5C4.375 24.7487 10.2513 30.625 17.5 30.625Z"
|
||||
stroke={color}
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path d="M17.5 17.5V4.375" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path
|
||||
d="M28.8613 10.9375L6.13867 24.0625"
|
||||
stroke={color}
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ const AddImage: FC<Iprops> = ({ onClick, sx }) => {
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
cursor: "pointer",
|
||||
...sx,
|
||||
}}
|
||||
>
|
||||
<svg width="60" height="40" viewBox="0 0 60 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
32
src/assets/icons/questionsPage/plus.tsx
Normal file
32
src/assets/icons/questionsPage/plus.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
export default function Plus() {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
height: "30px",
|
||||
width: "20px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
width="20"
|
||||
height="30"
|
||||
viewBox="0 0 15 40"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M18 0H0V40H18C18.4602 40 20 39.1046 20 38V2C20 0.89543 18.4602 0 18 0Z"
|
||||
fill="#7E2AEA"
|
||||
/>
|
||||
<path
|
||||
d="M9.518 24.612C9.398 24.612 9.296 24.576 9.212 24.504C9.14 24.42 9.104 24.318 9.104 24.198V20.454H5.414C5.294 20.454 5.192 20.418 5.108 20.346C5.036 20.262 5 20.16 5 20.04V19.464C5 19.344 5.036 19.248 5.108 19.176C5.192 19.092 5.294 19.05 5.414 19.05H9.104V15.414C9.104 15.294 9.14 15.198 9.212 15.126C9.296 15.042 9.398 15 9.518 15H10.148C10.268 15 10.364 15.042 10.436 15.126C10.52 15.198 10.562 15.294 10.562 15.414V19.05H14.27C14.39 19.05 14.486 19.092 14.558 19.176C14.642 19.248 14.684 19.344 14.684 19.464V20.04C14.684 20.16 14.642 20.262 14.558 20.346C14.486 20.418 14.39 20.454 14.27 20.454H10.562V24.198C10.562 24.318 10.52 24.42 10.436 24.504C10.364 24.576 10.268 24.612 10.148 24.612H9.518Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</Box>
|
||||
);
|
||||
}
|
@ -1,7 +1,16 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useRef } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Draggable } from "react-beautiful-dnd";
|
||||
import { Box, TextField, FormControl, InputAdornment, IconButton, useTheme, useMediaQuery } from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
TextField,
|
||||
FormControl,
|
||||
InputAdornment,
|
||||
IconButton,
|
||||
Popover,
|
||||
useTheme,
|
||||
useMediaQuery,
|
||||
} from "@mui/material";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
@ -9,26 +18,34 @@ import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
|
||||
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
||||
import { MessageIcon } from "@icons/messagIcon";
|
||||
import Popover from "@mui/material/Popover";
|
||||
import TextareaAutosize from "@mui/base/TextareaAutosize";
|
||||
|
||||
import type { ChangeEvent, KeyboardEvent } from "react";
|
||||
import type { ChangeEvent, KeyboardEvent, ReactNode } from "react";
|
||||
import type { Variants } from "@root/questions";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
type AnswerItemProps = {
|
||||
index: number;
|
||||
totalIndex: number;
|
||||
variants: Variants[];
|
||||
variant: Variants;
|
||||
additionalContent?: ReactNode;
|
||||
additionalMobile?: ReactNode;
|
||||
icon?: ReactNode;
|
||||
};
|
||||
|
||||
export const AnswerItem = ({ index, totalIndex, variants, variant, icon }: AnswerItemProps) => {
|
||||
export const AnswerItem = ({
|
||||
index,
|
||||
totalIndex,
|
||||
variants,
|
||||
variant,
|
||||
additionalContent,
|
||||
additionalMobile,
|
||||
icon
|
||||
}: AnswerItemProps) => {
|
||||
const quizId = Number(useParams().quizId);
|
||||
const { listQuestions } = questionStore();
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
const isTablet = useMediaQuery(theme.breakpoints.down(790));
|
||||
const debounced = useDebouncedCallback((value) => {
|
||||
const answerNew = variants.slice();
|
||||
answerNew[index].answer = value;
|
||||
@ -55,7 +72,7 @@ export const AnswerItem = ({ index, totalIndex, variants, variant, icon }: Answe
|
||||
|
||||
const addNewAnswer = () => {
|
||||
const answerNew = variants.slice();
|
||||
answerNew.push({ answer: "", hints: "" });
|
||||
answerNew.push({ answer: "", hints: "", emoji: "" });
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
@ -97,7 +114,13 @@ export const AnswerItem = ({ index, totalIndex, variants, variant, icon }: Answe
|
||||
key={index}
|
||||
fullWidth
|
||||
variant="standard"
|
||||
sx={{ padding: isMobile ? " 20px 0 20px 0" : "0 0 18px 0" }}
|
||||
sx={{ padding: isTablet ? " 20px 0 20px 0" : "0 0 18px 0" }}
|
||||
// sx={{
|
||||
// margin: isTablet ? " 15px 0 20px 0" : "0 0 20px 0",
|
||||
// borderRadius: "10px",
|
||||
// border: "1px solid rgba(0, 0, 0, 0.23)",
|
||||
// background: "white",
|
||||
// }}
|
||||
>
|
||||
<TextField
|
||||
defaultValue={variant.answer}
|
||||
@ -117,7 +140,7 @@ export const AnswerItem = ({ index, totalIndex, variants, variant, icon }: Answe
|
||||
<InputAdornment {...provided.dragHandleProps} position="start">
|
||||
<PointsIcon style={{ color: "#9A9AAF", fontSize: "30px" }} />
|
||||
</InputAdornment>
|
||||
{icon && icon}
|
||||
{additionalContent}
|
||||
</>
|
||||
),
|
||||
endAdornment: (
|
||||
@ -126,11 +149,13 @@ export const AnswerItem = ({ index, totalIndex, variants, variant, icon }: Answe
|
||||
<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" }}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "left",
|
||||
}}
|
||||
>
|
||||
<TextareaAutosize
|
||||
style={{ margin: "10px" }}
|
||||
@ -147,17 +172,22 @@ export const AnswerItem = ({ index, totalIndex, variants, variant, icon }: Answe
|
||||
),
|
||||
}}
|
||||
sx={{
|
||||
padding: isTablet ? "10px 0px" : 0,
|
||||
"& .MuiInputBase-root": {
|
||||
padding: icon ? "5px 13.5px" : "13.5px 13.5px 13.5px 9px",
|
||||
borderRadius: "8px",
|
||||
height: "48px",
|
||||
background: "#ffffff",
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
border: "none",
|
||||
},
|
||||
},
|
||||
}}
|
||||
inputProps={{
|
||||
sx: { fontSize: "18px", lineHeight: "21px", py: 0, ml: "13px" },
|
||||
}}
|
||||
/>
|
||||
{additionalMobile}
|
||||
</FormControl>
|
||||
</Box>
|
||||
)}
|
||||
|
@ -8,20 +8,22 @@ import { updateVariants } from "@root/questions";
|
||||
|
||||
import { reorder } from "./helper";
|
||||
|
||||
import { ReactNode } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
import type { DropResult } from "react-beautiful-dnd";
|
||||
import type { Variants } from "@root/questions";
|
||||
|
||||
type AnswerDraggableListProps = {
|
||||
variants: Variants[];
|
||||
totalIndex: number;
|
||||
icon?: ReactNode;
|
||||
additionalContent?: (variant: Variants, index: number) => ReactNode;
|
||||
additionalMobile?: (variant: Variants, index: number) => ReactNode;
|
||||
};
|
||||
|
||||
export const AnswerDraggableList = ({
|
||||
variants,
|
||||
totalIndex,
|
||||
icon,
|
||||
additionalContent,
|
||||
additionalMobile,
|
||||
}: AnswerDraggableListProps) => {
|
||||
const quizId = Number(useParams().quizId);
|
||||
|
||||
@ -45,7 +47,8 @@ export const AnswerDraggableList = ({
|
||||
totalIndex={totalIndex}
|
||||
variants={variants}
|
||||
variant={variant}
|
||||
icon={icon}
|
||||
additionalContent={additionalContent?.(variant, index)}
|
||||
additionalMobile={additionalMobile?.(variant, index)}
|
||||
/>
|
||||
))}
|
||||
{provided.placeholder}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
||||
import { useParams } from "react-router-dom";
|
||||
import React from "react";
|
||||
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
|
||||
import Clue from "../../assets/icons/questionsPage/clue";
|
||||
import Branching from "../../assets/icons/questionsPage/branching";
|
||||
@ -8,7 +8,7 @@ import { Box, Typography, Tooltip, IconButton, useTheme, useMediaQuery } from "@
|
||||
import { HideIcon } from "../../assets/icons/questionsPage/hideIcon";
|
||||
import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon";
|
||||
|
||||
import { questionStore, resetSomeField, copyQuestion, removeQuestion } from "@root/questions";
|
||||
import { questionStore, resetSomeField, copyQuestion, removeQuestionForce, updateQuestionsList, removeQuestion } from "@root/questions";
|
||||
import { DoubleTick } from "@icons/questionsPage/DoubleTick";
|
||||
import { DoubleArrowRight } from "@icons/questionsPage/DoubleArrowRight";
|
||||
import { VectorQuestions } from "@icons/questionsPage/VectorQuestions";
|
||||
@ -20,15 +20,26 @@ interface Props {
|
||||
totalIndex: number;
|
||||
}
|
||||
|
||||
export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props) {
|
||||
export default function ButtonsOptions({
|
||||
SSHC,
|
||||
switchState,
|
||||
totalIndex,
|
||||
}: Props) {
|
||||
const quizId = Number(useParams().quizId);
|
||||
const { openedModalSettings } = questionStore();
|
||||
const [openedReallyChangingModal, setOpenedReallyChangingModal] = React.useState<boolean>(false);
|
||||
const { openedModalSettings, listQuestions } = questionStore();
|
||||
const [openedReallyChangingModal, setOpenedReallyChangingModal] =
|
||||
useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||
clearTimeout(listQuestions[quizId][totalIndex].deleteTimeoutId);
|
||||
}
|
||||
}, [listQuestions]);
|
||||
|
||||
const openedModal = () => {
|
||||
resetSomeField({ openedModalSettings: "open" });
|
||||
console.log(openedModalSettings);
|
||||
};
|
||||
|
||||
const theme = useTheme();
|
||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
@ -41,17 +52,33 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
|
||||
myFunc?: any;
|
||||
}[] = [
|
||||
{
|
||||
icon: <SettingIcon color={switchState === "setting" ? "#ffffff" : theme.palette.grey3.main} />,
|
||||
icon: (
|
||||
<SettingIcon
|
||||
color={
|
||||
switchState === "setting" ? "#ffffff" : theme.palette.grey3.main
|
||||
}
|
||||
/>
|
||||
),
|
||||
title: "Настройки",
|
||||
value: "setting",
|
||||
},
|
||||
{
|
||||
icon: <Clue color={switchState === "help" ? "#ffffff" : theme.palette.grey3.main} />,
|
||||
icon: (
|
||||
<Clue
|
||||
color={switchState === "help" ? "#ffffff" : theme.palette.grey3.main}
|
||||
/>
|
||||
),
|
||||
title: "Подсказка",
|
||||
value: "help",
|
||||
},
|
||||
{
|
||||
icon: <Branching color={switchState === "branching" ? "#ffffff" : theme.palette.grey3.main} />,
|
||||
icon: (
|
||||
<Branching
|
||||
color={
|
||||
switchState === "branching" ? "#ffffff" : theme.palette.grey3.main
|
||||
}
|
||||
/>
|
||||
),
|
||||
title: "Ветвление",
|
||||
value: "branching",
|
||||
myFunc: openedModal,
|
||||
@ -78,7 +105,7 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
|
||||
}}
|
||||
>
|
||||
{buttonSetting.map(({ icon, title, value, myFunc }) => (
|
||||
<>
|
||||
<Box key={value}>
|
||||
{value === "branching" ? (
|
||||
<Tooltip
|
||||
arrow
|
||||
@ -95,7 +122,9 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
|
||||
>
|
||||
Будет показан при условии
|
||||
</Typography>
|
||||
<Typography sx={{ fontWeight: "bold", fontSize: "12px" }}>Название</Typography>
|
||||
<Typography sx={{ fontWeight: "bold", fontSize: "12px" }}>
|
||||
Название
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
@ -105,7 +134,9 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
|
||||
>
|
||||
Условие 1, Условие 2
|
||||
</Typography>
|
||||
<Typography sx={{ color: "#7E2AEA", fontSize: "12px" }}>Все условия обязательны</Typography>
|
||||
<Typography sx={{ color: "#7E2AEA", fontSize: "12px" }}>
|
||||
Все условия обязательны
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
@ -116,10 +147,15 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
|
||||
myFunc();
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: switchState === value ? theme.palette.brightPurple.main : "transparent",
|
||||
color: switchState === value ? "#ffffff" : theme.palette.grey3.main,
|
||||
backgroundColor:
|
||||
switchState === value
|
||||
? theme.palette.brightPurple.main
|
||||
: "transparent",
|
||||
color:
|
||||
switchState === value
|
||||
? "#ffffff"
|
||||
: theme.palette.grey3.main,
|
||||
minWidth: isWrappMiniButtonSetting ? "30px" : "64px",
|
||||
|
||||
height: "30px",
|
||||
}}
|
||||
>
|
||||
@ -136,17 +172,23 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
|
||||
myFunc();
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: switchState === value ? theme.palette.brightPurple.main : "transparent",
|
||||
color: switchState === value ? "#ffffff" : theme.palette.grey3.main,
|
||||
minWidth: isMobile ? "30px" : "64px",
|
||||
backgroundColor:
|
||||
switchState === value
|
||||
? theme.palette.brightPurple.main
|
||||
: "transparent",
|
||||
color:
|
||||
switchState === value
|
||||
? "#ffffff"
|
||||
: theme.palette.grey3.main,
|
||||
minWidth: isWrappMiniButtonSetting ? "30px" : "64px",
|
||||
height: "30px",
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
{isMobile ? null : title}
|
||||
{isWrappMiniButtonSetting ? null : title}
|
||||
</MiniButtonSetting>
|
||||
)}
|
||||
</>
|
||||
</Box>
|
||||
))}
|
||||
<MiniButtonSetting
|
||||
onClick={() => setOpenedReallyChangingModal(true)}
|
||||
@ -188,13 +230,35 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props)
|
||||
<IconButton sx={{ borderRadius: "6px", padding: "2px" }}>
|
||||
<HideIcon style={{ color: "#4D4D4D" }} />
|
||||
</IconButton>
|
||||
<IconButton sx={{ borderRadius: "6px", padding: "2px" }} onClick={() => copyQuestion(quizId, totalIndex)}>
|
||||
<CopyIcon style={{ color: "#4D4D4D" }} />
|
||||
<IconButton
|
||||
sx={{ borderRadius: "6px", padding: "2px" }}
|
||||
onClick={() => copyQuestion(quizId, totalIndex)}
|
||||
>
|
||||
<CopyIcon color={"#4D4D4D"} />
|
||||
</IconButton>
|
||||
<IconButton sx={{ borderRadius: "6px", padding: "2px" }} onClick={() => removeQuestion(quizId, totalIndex)}>
|
||||
<DeleteIcon style={{ color: "#4D4D4D" }} />
|
||||
<IconButton
|
||||
sx={{ borderRadius: "6px", padding: "2px" }}
|
||||
onClick={() => {
|
||||
const removedId = listQuestions[quizId][totalIndex].id;
|
||||
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||
clearTimeout(listQuestions[quizId][totalIndex].deleteTimeoutId);
|
||||
}
|
||||
|
||||
removeQuestion(quizId, totalIndex);
|
||||
|
||||
const newTimeoutId = window.setTimeout(() => {
|
||||
removeQuestionForce(quizId, removedId);
|
||||
}, 5000);
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
...listQuestions[quizId][totalIndex],
|
||||
deleteTimeoutId: newTimeoutId,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<DeleteIcon color={"#4D4D4D"} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
||||
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
|
||||
import Clue from "../../assets/icons/questionsPage/clue";
|
||||
@ -9,7 +9,14 @@ import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon";
|
||||
import { DeleteIcon } from "../../assets/icons/questionsPage/deleteIcon";
|
||||
import ImgIcon from "../../assets/icons/questionsPage/imgIcon";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { questionStore, copyQuestion, removeQuestion, resetSomeField } from "@root/questions";
|
||||
import {
|
||||
questionStore,
|
||||
copyQuestion,
|
||||
removeQuestion,
|
||||
resetSomeField,
|
||||
removeQuestionForce,
|
||||
updateQuestionsList,
|
||||
} from "@root/questions";
|
||||
import { DoubleArrowRight } from "@icons/questionsPage/DoubleArrowRight";
|
||||
import { DoubleTick } from "@icons/questionsPage/DoubleTick";
|
||||
import { VectorQuestions } from "@icons/questionsPage/VectorQuestions";
|
||||
@ -26,12 +33,19 @@ interface Props {
|
||||
export default function ButtonsOptionsAndPict({ SSHC, switchState, totalIndex }: Props) {
|
||||
const [buttonHover, setButtonHover] = useState<string>("");
|
||||
const quizId = Number(useParams().quizId);
|
||||
const { openedModalSettings } = questionStore();
|
||||
const { listQuestions } = questionStore();
|
||||
const [openedReallyChangingModal, setOpenedReallyChangingModal] =
|
||||
useState<boolean>(false);
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
const isIconMobile = useMediaQuery(theme.breakpoints.down(1050));
|
||||
|
||||
const [openedReallyChangingModal, setOpenedReallyChangingModal] = useState<boolean>(false);
|
||||
useEffect(() => {
|
||||
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||
clearTimeout(listQuestions[quizId][totalIndex].deleteTimeoutId);
|
||||
}
|
||||
}, [listQuestions]);
|
||||
|
||||
const openedModal = () => {
|
||||
resetSomeField({ openedModalSettings: "open" });
|
||||
};
|
||||
@ -198,7 +212,6 @@ export default function ButtonsOptionsAndPict({ SSHC, switchState, totalIndex }:
|
||||
/>
|
||||
{isIconMobile ? null : "Изображение"}
|
||||
</MiniButtonSetting>
|
||||
|
||||
<MiniButtonSetting
|
||||
onClick={() => setOpenedReallyChangingModal(true)}
|
||||
sx={{
|
||||
@ -243,12 +256,37 @@ export default function ButtonsOptionsAndPict({ SSHC, switchState, totalIndex }:
|
||||
</IconButton>
|
||||
<IconButton
|
||||
sx={{ borderRadius: "6px", padding: " 0px 2px" }}
|
||||
onClick={() => removeQuestion(quizId, totalIndex)}
|
||||
onClick={() => copyQuestion(quizId, totalIndex)}
|
||||
>
|
||||
<CopyIcon color={"#4D4D4D"} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
sx={{ borderRadius: "6px", padding: "2px" }}
|
||||
onClick={() => {
|
||||
const removedId = listQuestions[quizId][totalIndex].id;
|
||||
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||
clearTimeout(listQuestions[quizId][totalIndex].deleteTimeoutId);
|
||||
}
|
||||
|
||||
removeQuestion(quizId, totalIndex);
|
||||
|
||||
const newTimeoutId = window.setTimeout(() => {
|
||||
removeQuestionForce(quizId, removedId);
|
||||
}, 5000);
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
...listQuestions[quizId][totalIndex],
|
||||
deleteTimeoutId: newTimeoutId,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<DeleteIcon style={{ color: "#4D4D4D" }} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<ReallyChangingModal opened={openedReallyChangingModal} onClose={() => setOpenedReallyChangingModal(false)} />
|
||||
<ReallyChangingModal
|
||||
opened={openedReallyChangingModal}
|
||||
onClose={() => setOpenedReallyChangingModal(false)}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
|
||||
}}
|
||||
/>
|
||||
<CustomCheckbox
|
||||
sx={{ display: "block" }}
|
||||
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
|
||||
label={"Выбор времени"}
|
||||
checked={listQuestions[quizId][totalIndex].content.time}
|
||||
handleChange={({ target }) => {
|
||||
@ -92,8 +92,9 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) {
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Box sx={{ width: isMobile ? "93%" : "auto", display: "flex", alignItems: "center" }}>
|
||||
<CustomCheckbox
|
||||
sx={{ mr: isMobile ? "0px" : "16px" }}
|
||||
label={"Внутреннее название вопроса"}
|
||||
checked={listQuestions[quizId][totalIndex].content.innerNameCheck}
|
||||
handleChange={(e) => {
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
ClickAwayListener,
|
||||
Modal,
|
||||
Button,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
|
||||
import {
|
||||
@ -27,6 +28,7 @@ type ChooseAnswerModalProps = {
|
||||
onClose: () => void;
|
||||
anchorRef: RefObject<HTMLDivElement>;
|
||||
totalIndex: number;
|
||||
switchState: string;
|
||||
};
|
||||
|
||||
export const ChooseAnswerModal = ({
|
||||
@ -34,11 +36,13 @@ export const ChooseAnswerModal = ({
|
||||
onClose,
|
||||
anchorRef,
|
||||
totalIndex,
|
||||
switchState,
|
||||
}: ChooseAnswerModalProps) => {
|
||||
const [openModal, setOpenModal] = useState<boolean>(false);
|
||||
const [selectedValue, setSelectedValue] = useState<string>("");
|
||||
const quizId = Number(useParams().quizId);
|
||||
const { listQuestions } = questionStore();
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -56,15 +60,26 @@ export const ChooseAnswerModal = ({
|
||||
{BUTTON_TYPE_QUESTIONS.map(({ icon, title, value }) => (
|
||||
<MenuItem
|
||||
key={value}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
setOpenModal(true);
|
||||
setSelectedValue(value);
|
||||
}}
|
||||
sx={{ display: "flex", gap: "10px" }}
|
||||
{...(value !== switchState && {
|
||||
onClick: () => {
|
||||
onClose();
|
||||
setOpenModal(true);
|
||||
setSelectedValue(value);
|
||||
},
|
||||
})}
|
||||
>
|
||||
<Box>{icon}</Box>
|
||||
<Typography>{title}</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
color:
|
||||
value === switchState
|
||||
? theme.palette.brightPurple.main
|
||||
: theme.palette.grey2.main,
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
|
@ -1,33 +1,88 @@
|
||||
import { memo } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Draggable } from "react-beautiful-dnd";
|
||||
import { Box, ListItem } from "@mui/material";
|
||||
import { Box, ListItem, Typography, useTheme } from "@mui/material";
|
||||
|
||||
import QuestionsPageCard from "./QuestionPageCard";
|
||||
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
|
||||
import {Question} from "@root/questions"
|
||||
|
||||
type DraggableListItemProps = {
|
||||
index: number;
|
||||
isDragging: boolean;
|
||||
questionData: Question;
|
||||
};
|
||||
|
||||
export const DraggableListItem = ({
|
||||
export default memo(({
|
||||
index,
|
||||
isDragging,
|
||||
}: DraggableListItemProps) => (
|
||||
<Draggable draggableId={String(index)} index={index}>
|
||||
{(provided) => (
|
||||
<ListItem
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
sx={{ userSelect: "none", padding: 0 }}
|
||||
>
|
||||
<Box sx={{ width: "100%", position: "relative" }}>
|
||||
<QuestionsPageCard
|
||||
key={index}
|
||||
totalIndex={index}
|
||||
draggableProps={provided.dragHandleProps}
|
||||
isDragging={isDragging}
|
||||
/>
|
||||
</Box>
|
||||
</ListItem>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
questionData
|
||||
}: DraggableListItemProps) => {
|
||||
const quizId = Number(useParams().quizId);
|
||||
const theme = useTheme();
|
||||
console.log("Мой индекс "+index)
|
||||
console.log(questionData)
|
||||
|
||||
return (
|
||||
<Draggable draggableId={String(index)} index={index}>
|
||||
{(provided) => (
|
||||
<ListItem
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
sx={{ userSelect: "none", padding: 0 }}
|
||||
>
|
||||
{questionData.deleted ? (
|
||||
<Box
|
||||
{...provided.dragHandleProps}
|
||||
sx={{
|
||||
width: "100%",
|
||||
maxWidth: "800px",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
marginBottom: "40px",
|
||||
gap: "5px",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
color: theme.palette.grey2.main,
|
||||
}}
|
||||
>
|
||||
Вопрос удалён.
|
||||
</Typography>
|
||||
<Typography
|
||||
onClick={() => {
|
||||
updateQuestionsList(quizId, index, {
|
||||
...questionData,
|
||||
deleted: false,
|
||||
});
|
||||
}}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
fontSize: "16px",
|
||||
textDecoration: "underline",
|
||||
color: theme.palette.brightPurple.main,
|
||||
textDecorationColor: theme.palette.brightPurple.main,
|
||||
}}
|
||||
>
|
||||
Восстановить?
|
||||
</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ width: "100%", position: "relative" }}>
|
||||
<QuestionsPageCard
|
||||
key={index}
|
||||
totalIndex={index}
|
||||
draggableProps={provided.dragHandleProps}
|
||||
isDragging={isDragging}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</ListItem>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import {
|
||||
Box,
|
||||
@ -18,7 +18,14 @@ import { ChooseAnswerModal } from "./ChooseAnswerModal";
|
||||
import TypeQuestions from "../TypeQuestions";
|
||||
import SwitchQuestionsPage from "../SwitchQuestionsPage";
|
||||
|
||||
import { questionStore, updateQuestionsList, createQuestion, copyQuestion, removeQuestion } from "@root/questions";
|
||||
import {
|
||||
questionStore,
|
||||
updateQuestionsList,
|
||||
createQuestion,
|
||||
copyQuestion,
|
||||
removeQuestion,
|
||||
removeQuestionForce,
|
||||
} from "@root/questions";
|
||||
|
||||
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
||||
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
||||
@ -91,6 +98,12 @@ export default function QuestionsPageCard({ totalIndex, draggableProps, isDraggi
|
||||
updateQuestionsList(quizId, totalIndex, { title });
|
||||
}, 1000);
|
||||
|
||||
useEffect(() => {
|
||||
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||
clearTimeout(listQuestions[quizId][totalIndex].deleteTimeoutId);
|
||||
}
|
||||
}, [listQuestions]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Paper
|
||||
@ -140,6 +153,7 @@ export default function QuestionsPageCard({ totalIndex, draggableProps, isDraggi
|
||||
onClose={() => setOpen(false)}
|
||||
anchorRef={anchorRef}
|
||||
totalIndex={totalIndex}
|
||||
switchState={switchState}
|
||||
/>
|
||||
</Box>
|
||||
),
|
||||
@ -226,7 +240,25 @@ export default function QuestionsPageCard({ totalIndex, draggableProps, isDraggi
|
||||
borderRadius: "6px",
|
||||
padding: "2px",
|
||||
}}
|
||||
onClick={() => removeQuestion(quizId, totalIndex)}
|
||||
onClick={() => {
|
||||
const removedId = listQuestions[quizId][totalIndex].id;
|
||||
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||
clearTimeout(
|
||||
listQuestions[quizId][totalIndex].deleteTimeoutId
|
||||
);
|
||||
}
|
||||
|
||||
removeQuestion(quizId, totalIndex);
|
||||
|
||||
const newTimeoutId = window.setTimeout(() => {
|
||||
removeQuestionForce(quizId, removedId);
|
||||
}, 5000);
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
...listQuestions[quizId][totalIndex],
|
||||
deleteTimeoutId: newTimeoutId,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<DeleteIcon style={{ color: "white" }} />
|
||||
</IconButton>
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Box } from "@mui/material";
|
||||
import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
||||
|
||||
import { DraggableListItem } from "./DraggableListItem";
|
||||
import DraggableListItem from "./DraggableListItem";
|
||||
|
||||
import { questionStore, updateQuestionsListDragAndDrop } from "@root/questions";
|
||||
|
||||
@ -17,7 +16,11 @@ export const DraggableList = () => {
|
||||
|
||||
const onDragEnd = ({ destination, source }: DropResult) => {
|
||||
if (destination) {
|
||||
const newItems = reorder(listQuestions[quizId], source.index, destination.index);
|
||||
const newItems = reorder(
|
||||
listQuestions[quizId],
|
||||
source.index,
|
||||
destination.index
|
||||
);
|
||||
|
||||
updateQuestionsListDragAndDrop(quizId, newItems);
|
||||
}
|
||||
@ -29,7 +32,12 @@ export const DraggableList = () => {
|
||||
{(provided, snapshot) => (
|
||||
<Box ref={provided.innerRef} {...provided.droppableProps}>
|
||||
{listQuestions[quizId]?.map((_, index) => (
|
||||
<DraggableListItem key={index} index={index} isDragging={snapshot.isDraggingOver} />
|
||||
<DraggableListItem
|
||||
key={index}
|
||||
index={index}
|
||||
isDragging={snapshot.isDraggingOver}
|
||||
questionData={_}
|
||||
/>
|
||||
))}
|
||||
{provided.placeholder}
|
||||
</Box>
|
||||
|
@ -27,7 +27,7 @@ export default function DropDown({ totalIndex }: Props) {
|
||||
|
||||
const addNewAnswer = () => {
|
||||
const answerNew = variants.slice();
|
||||
answerNew.push({ answer: "", hints: "" });
|
||||
answerNew.push({ answer: "", hints: "", emoji: "" });
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
@ -93,7 +93,11 @@ export default function DropDown({ totalIndex }: Props) {
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptions switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} />
|
||||
<ButtonsOptions
|
||||
switchState={switchState}
|
||||
SSHC={SSHC}
|
||||
totalIndex={totalIndex}
|
||||
/>
|
||||
<SwitchDropDown switchState={switchState} totalIndex={totalIndex} />
|
||||
</>
|
||||
);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import {
|
||||
Box,
|
||||
@ -14,22 +15,29 @@ import {
|
||||
import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon";
|
||||
import ButtonsOptions from "../ButtonsOptions";
|
||||
import SwitchEmoji from "./switchEmoji";
|
||||
import React from "react";
|
||||
import AddEmoji from "../../../assets/icons/questionsPage/addEmoji";
|
||||
import { AnswerDraggableList } from "../AnswerDraggableList";
|
||||
import { EmojiPicker } from "@ui_kit/EmojiPicker";
|
||||
import { EmojiIcons } from "@icons/EmojiIocns";
|
||||
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
|
||||
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
|
||||
import { MessageIcon } from "@icons/messagIcon";
|
||||
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
||||
import { ImageAddIcons } from "@icons/ImageAddIcons";
|
||||
import { EmojiIcons } from "@icons/EmojiIocns";
|
||||
import AddEmoji from "../../../assets/icons/questionsPage/addEmoji";
|
||||
import PlusImage from "../../../assets/icons/questionsPage/plus";
|
||||
|
||||
interface Props {
|
||||
totalIndex: number;
|
||||
}
|
||||
export default function Emoji({ totalIndex }: Props) {
|
||||
const [switchState, setSwitchState] = React.useState("setting");
|
||||
const [switchState, setSwitchState] = useState<string>("setting");
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const [anchorElement, setAnchorElement] = useState<HTMLDivElement | null>(
|
||||
null
|
||||
);
|
||||
const [currentIndex, setCurrentIndex] = useState<number>(0);
|
||||
const { listQuestions } = questionStore();
|
||||
const quizId = Number(useParams().quizId);
|
||||
const theme = useTheme();
|
||||
@ -42,7 +50,7 @@ export default function Emoji({ totalIndex }: Props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ padding: "0 20px 0px 20px" }}>
|
||||
{/* <Box sx={{ padding: "0 20px 0px 20px" }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
@ -148,14 +156,165 @@ export default function Emoji({ totalIndex }: Props) {
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", marginBottom: "20px" }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", marginBottom: "20px" }}> */}
|
||||
<Box sx={{ padding: "20px" }}>
|
||||
<AnswerDraggableList
|
||||
variants={listQuestions[quizId][totalIndex].content.variants}
|
||||
totalIndex={totalIndex}
|
||||
additionalContent={(variant, index) => (
|
||||
<>
|
||||
{!isTablet && (
|
||||
<Box sx={{ cursor: "pointer", margin: "0 15px 0 5px" }}>
|
||||
<Box
|
||||
onClick={({ currentTarget }) => {
|
||||
setAnchorElement(currentTarget);
|
||||
setCurrentIndex(index);
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "5px",
|
||||
}}
|
||||
>
|
||||
{variant.emoji ? (
|
||||
<Box
|
||||
sx={{
|
||||
width: "30px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
background: "#EEE4FC",
|
||||
borderRadius: "3px",
|
||||
marginRight: "15px",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ marginLeft: "3px" }}>{variant.emoji}</Box>
|
||||
<Box sx={{ marginLeft: "-3px" }}>
|
||||
<PlusImage />
|
||||
</Box>
|
||||
</Box>
|
||||
) : (
|
||||
<AddEmoji />
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
additionalMobile={(variant, index) => (
|
||||
<>
|
||||
{isTablet && (
|
||||
<Box
|
||||
onClick={({ currentTarget }) => {
|
||||
setAnchorElement(currentTarget);
|
||||
setCurrentIndex(index);
|
||||
setOpen(true);
|
||||
}}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
m: "8px",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
background: "#EEE4FC",
|
||||
height: "40px",
|
||||
}}
|
||||
/>
|
||||
{variant.emoji ? (
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
color: "#7E2AEA",
|
||||
fontSize: "20px",
|
||||
left: "45%",
|
||||
right: "55%",
|
||||
}}
|
||||
>
|
||||
{variant.emoji}
|
||||
</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);
|
||||
const cloneVariants = [
|
||||
...listQuestions[quizId][totalIndex].content.variants,
|
||||
];
|
||||
|
||||
cloneVariants[currentIndex] = {
|
||||
...cloneVariants[currentIndex],
|
||||
emoji: native,
|
||||
};
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
variants: cloneVariants,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Popover>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
||||
<Link
|
||||
component="button"
|
||||
variant="body2"
|
||||
sx={{ color: theme.palette.brightPurple.main }}
|
||||
onClick={() => {
|
||||
const answerNew = listQuestions[quizId][totalIndex].content.variants.slice();
|
||||
answerNew.push({ answer: "", hints: "" });
|
||||
const answerNew =
|
||||
listQuestions[quizId][totalIndex].content.variants.slice();
|
||||
answerNew.push({ answer: "", hints: "", emoji: "" });
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
@ -167,7 +326,7 @@ export default function Emoji({ totalIndex }: Props) {
|
||||
>
|
||||
Добавьте ответ
|
||||
</Link>
|
||||
{isMobile ? null : (
|
||||
{!isTablet && (
|
||||
<>
|
||||
<Typography
|
||||
sx={{
|
||||
@ -184,7 +343,11 @@ export default function Emoji({ totalIndex }: Props) {
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptions switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} />
|
||||
<ButtonsOptions
|
||||
switchState={switchState}
|
||||
SSHC={SSHC}
|
||||
totalIndex={totalIndex}
|
||||
/>
|
||||
<SwitchEmoji switchState={switchState} totalIndex={totalIndex} />
|
||||
</>
|
||||
);
|
||||
|
@ -59,7 +59,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
|
||||
}}
|
||||
/>
|
||||
<CustomCheckbox
|
||||
sx={{ mr: isMobile ? "0px" : "16px" }}
|
||||
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
|
||||
label={'Вариант "свой ответ"'}
|
||||
checked={listQuestions[quizId][totalIndex].content.own}
|
||||
handleChange={(e) => {
|
||||
@ -85,6 +85,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
|
||||
Настройки вопросов
|
||||
</Typography>
|
||||
<CustomCheckbox
|
||||
sx={{ mr: isMobile ? "0px" : "16px" }}
|
||||
label={"Необязательный вопрос"}
|
||||
checked={!listQuestions[quizId][totalIndex].required}
|
||||
handleChange={(e) => {
|
||||
@ -95,6 +96,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) {
|
||||
/>
|
||||
<Box sx={{ width: isMobile ? "90%" : "auto", display: "flex", alignItems: "center" }}>
|
||||
<CustomCheckbox
|
||||
sx={{ mr: isMobile ? "0px" : "16px" }}
|
||||
label={"Внутреннее название вопроса"}
|
||||
checked={listQuestions[quizId][totalIndex].content.innerNameCheck}
|
||||
handleChange={(e) => {
|
||||
|
@ -54,6 +54,7 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
||||
>
|
||||
{listQuestions[quizId][totalIndex].content.variants.map((_, index) => (
|
||||
<ButtonBase
|
||||
key={index}
|
||||
component="label"
|
||||
sx={{
|
||||
display: isTablet ? "none" : "flex",
|
||||
@ -107,7 +108,6 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
||||
+
|
||||
</span>
|
||||
</Box>
|
||||
|
||||
<Typography
|
||||
sx={{
|
||||
padding: "0 0 0 20px",
|
||||
@ -179,8 +179,15 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
||||
<IconButton sx={{ padding: "0" }} aria-describedby="my-popover-id">
|
||||
<MessageIcon style={{ color: "#9A9AAF", fontSize: "30px", marginRight: "6.5px" }} />
|
||||
</IconButton>
|
||||
<Popover id="my-popover-id" anchorOrigin={{ vertical: "bottom", horizontal: "left" }} open={false}>
|
||||
<TextareaAutosize style={{ margin: "10px" }} placeholder="Подсказка для этого ответа" />
|
||||
<Popover
|
||||
id="my-popover-id"
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
||||
open={false}
|
||||
>
|
||||
<TextareaAutosize
|
||||
style={{ margin: "10px" }}
|
||||
placeholder="Подсказка для этого ответа"
|
||||
/>
|
||||
</Popover>
|
||||
<IconButton sx={{ padding: "0" }}>
|
||||
<DeleteIcon style={{ color: theme.palette.grey2.main, marginRight: "-1px" }} />
|
||||
@ -205,10 +212,25 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
||||
/>
|
||||
|
||||
{isMobile && (
|
||||
<Box sx={{ display: "flex", alignItems: "center", m: "8px", position: "relative" }}>
|
||||
<Box sx={{ width: "100%", background: "#EEE4FC", height: "40px" }} />
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
m: "8px",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{ width: "100%", background: "#EEE4FC", height: "40px" }}
|
||||
/>
|
||||
<ImageAddIcons
|
||||
style={{ position: "absolute", color: "#7E2AEA", fontSize: "20px", left: "45%", right: "55%" }}
|
||||
style={{
|
||||
position: "absolute",
|
||||
color: "#7E2AEA",
|
||||
fontSize: "20px",
|
||||
left: "45%",
|
||||
right: "55%",
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
@ -245,6 +267,12 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
||||
mr: "4px",
|
||||
height: "19px",
|
||||
}}
|
||||
onClick={() => {
|
||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||
clonContent.variants.push({ answer: "", hints: "", emoji: "" });
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||
}}
|
||||
>
|
||||
Добавьте ответ
|
||||
</Link>
|
||||
@ -265,7 +293,11 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptionsAndPict switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} />
|
||||
<ButtonsOptionsAndPict
|
||||
switchState={switchState}
|
||||
SSHC={SSHC}
|
||||
totalIndex={totalIndex}
|
||||
/>
|
||||
<SwitchOptionsAndPict switchState={switchState} totalIndex={totalIndex} />
|
||||
</>
|
||||
);
|
||||
|
@ -53,6 +53,7 @@ export default function OptionsPicture({ totalIndex }: Props) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ pl: "20px", pr: "20px" }}>
|
||||
@ -95,7 +96,6 @@ export default function OptionsPicture({ totalIndex }: Props) {
|
||||
+
|
||||
</span>
|
||||
</Box>
|
||||
|
||||
<Typography
|
||||
sx={{
|
||||
padding: "0 0 0 20px",
|
||||
@ -166,8 +166,15 @@ export default function OptionsPicture({ totalIndex }: Props) {
|
||||
<IconButton sx={{ padding: "0" }} aria-describedby="my-popover-id">
|
||||
<MessageIcon style={{ color: "#9A9AAF", fontSize: "30px", marginRight: "6.5px" }} />
|
||||
</IconButton>
|
||||
<Popover id="my-popover-id" anchorOrigin={{ vertical: "bottom", horizontal: "left" }} open={false}>
|
||||
<TextareaAutosize style={{ margin: "10px" }} placeholder="Подсказка для этого ответа" />
|
||||
<Popover
|
||||
id="my-popover-id"
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
||||
open={false}
|
||||
>
|
||||
<TextareaAutosize
|
||||
style={{ margin: "10px" }}
|
||||
placeholder="Подсказка для этого ответа"
|
||||
/>
|
||||
</Popover>
|
||||
<IconButton sx={{ padding: "0" }}>
|
||||
<DeleteIcon style={{ color: theme.palette.grey2.main, marginRight: "-1px" }} />
|
||||
@ -192,10 +199,25 @@ export default function OptionsPicture({ totalIndex }: Props) {
|
||||
/>
|
||||
|
||||
{isMobile && (
|
||||
<Box sx={{ display: "flex", alignItems: "center", m: "8px", position: "relative" }}>
|
||||
<Box sx={{ width: "100%", background: "#EEE4FC", height: "40px" }} />
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
m: "8px",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{ width: "100%", background: "#EEE4FC", height: "40px" }}
|
||||
/>
|
||||
<ImageAddIcons
|
||||
style={{ position: "absolute", color: "#7E2AEA", fontSize: "20px", left: "45%", right: "55%" }}
|
||||
style={{
|
||||
position: "absolute",
|
||||
color: "#7E2AEA",
|
||||
fontSize: "20px",
|
||||
left: "45%",
|
||||
right: "55%",
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
@ -253,8 +275,15 @@ export default function OptionsPicture({ totalIndex }: Props) {
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptions switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} />
|
||||
<SwitchAnswerOptionsPict switchState={switchState} totalIndex={totalIndex} />
|
||||
<ButtonsOptions
|
||||
switchState={switchState}
|
||||
SSHC={SSHC}
|
||||
totalIndex={totalIndex}
|
||||
/>
|
||||
<SwitchAnswerOptionsPict
|
||||
switchState={switchState}
|
||||
totalIndex={totalIndex}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -147,19 +147,22 @@ export default function SettingOpytionsPict({ totalIndex }: SettingOpytionsPictP
|
||||
})
|
||||
}
|
||||
/>
|
||||
<CustomCheckbox
|
||||
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
|
||||
label={"Большие картинки"}
|
||||
checked={listQuestions[quizId][totalIndex].content.largeCheck}
|
||||
handleChange={({ target }) =>
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
largeCheck: target.checked,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
{listQuestions[quizId][totalIndex].content.xy !== "1:1" &&
|
||||
listQuestions[quizId][totalIndex].content.format !== "masonry" && (
|
||||
<CustomCheckbox
|
||||
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
|
||||
label={"Большие картинки"}
|
||||
checked={listQuestions[quizId][totalIndex].content.largeCheck}
|
||||
handleChange={({ target }) =>
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
largeCheck: target.checked,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<CustomCheckbox
|
||||
sx={{ display: "block", mr: isMobile ? "0px" : "16px" }}
|
||||
label={'Вариант "свой ответ"'}
|
||||
@ -174,7 +177,6 @@ export default function SettingOpytionsPict({ totalIndex }: SettingOpytionsPictP
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
pt: isMobile ? "0px" : "20px",
|
||||
@ -236,7 +238,13 @@ export default function SettingOpytionsPict({ totalIndex }: SettingOpytionsPictP
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Box sx={{ width: isMobile ? "90%" : "auto", display: "flex", alignItems: "center" }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: isMobile ? "90%" : "auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<CustomCheckbox
|
||||
label={"Внутреннее название вопроса"}
|
||||
checked={listQuestions[quizId][totalIndex].content.innerNameCheck}
|
||||
|
@ -1,5 +1,11 @@
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Box, Typography, useMediaQuery, useTheme, Tooltip } from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Tooltip,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import CustomCheckbox from "@ui_kit/CustomCheckbox";
|
||||
import CustomTextField from "@ui_kit/CustomTextField";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
@ -15,7 +21,6 @@ type SettingPageOptionsProps = {
|
||||
export default function SettingPageOptions({ totalIndex }: SettingPageOptionsProps) {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
|
||||
const quizId = Number(useParams().quizId);
|
||||
const { listQuestions } = questionStore();
|
||||
const debounced = useDebouncedCallback((value) => {
|
||||
|
@ -77,7 +77,6 @@ export default function QuestionsPage() {
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
createQuestion(quizId);
|
||||
console.log(listQuestions);
|
||||
}}
|
||||
>
|
||||
<AddPlus />
|
||||
|
@ -1,10 +1,16 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
TextField,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
import ButtonsOptions from "../ButtonsOptions";
|
||||
import SwitchRating from "./switchRating";
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
import CustomTextField from "@ui_kit/CustomTextField";
|
||||
|
||||
import TropfyIcon from "../../../assets/icons/questionsPage/tropfyIcon";
|
||||
import FlagIcon from "../../../assets/icons/questionsPage/FlagIcon";
|
||||
@ -25,10 +31,49 @@ export type ButtonRatingFrom = {
|
||||
|
||||
export default function RatingOptions({ totalIndex }: Props) {
|
||||
const [switchState, setSwitchState] = useState("setting");
|
||||
const [negativeText, setNegativeText] = useState<string>("");
|
||||
const [positiveText, setPositiveText] = useState<string>("");
|
||||
const [negativeTextWidth, setNegativeTextWidth] = useState<number>(0);
|
||||
const [positiveTextWidth, setPositiveTextWidth] = useState<number>(0);
|
||||
const quizId = Number(useParams().quizId);
|
||||
const { listQuestions } = questionStore();
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
const negativeRef = useRef<HTMLDivElement>(null);
|
||||
const positiveRef = useRef<HTMLDivElement>(null);
|
||||
const debounceNegativeDescription = useDebouncedCallback((value) => {
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
ratingNegativeDescription: value.substring(0, 15),
|
||||
},
|
||||
});
|
||||
}, 500);
|
||||
const debouncePositiveDescription = useDebouncedCallback((value) => {
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
ratingPositiveDescription: value.substring(0, 15),
|
||||
},
|
||||
});
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
setNegativeText(
|
||||
listQuestions[quizId][totalIndex].content.ratingNegativeDescription
|
||||
);
|
||||
setPositiveText(
|
||||
listQuestions[quizId][totalIndex].content.ratingPositiveDescription
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setNegativeTextWidth(negativeRef.current?.offsetWidth || 0);
|
||||
}, [negativeText]);
|
||||
|
||||
useEffect(() => {
|
||||
setPositiveTextWidth(positiveRef.current?.offsetWidth || 0);
|
||||
}, [positiveText]);
|
||||
|
||||
const buttonRatingForm: ButtonRatingFrom[] = [
|
||||
{ name: "star", icon: <StarIconMini width={"50px"} color={theme.palette.grey2.main} /> },
|
||||
@ -51,42 +96,43 @@ export default function RatingOptions({ totalIndex }: Props) {
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
width: isMobile ? "auto" : "100%",
|
||||
width: isMobile
|
||||
? "auto"
|
||||
: `${
|
||||
listQuestions[quizId][totalIndex].content.steps * 44 >
|
||||
negativeTextWidth + positiveTextWidth
|
||||
? listQuestions[quizId][totalIndex].content.steps * 44
|
||||
: negativeTextWidth + positiveTextWidth + 20
|
||||
}px`,
|
||||
minWidth: "300px",
|
||||
maxWidth: "440px",
|
||||
display: "flex",
|
||||
px: "20px",
|
||||
flexDirection: "column",
|
||||
gap: "20px",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", gap: isMobile ? "10px" : "15px" }}>
|
||||
{Array.from({ length: listQuestions[quizId][totalIndex].content.steps }, (_, index) => index).map(
|
||||
(itemNumber) => (
|
||||
<Box
|
||||
{...(itemNumber === 0 || itemNumber === listQuestions[quizId][totalIndex].content.steps - 1
|
||||
? {
|
||||
onClick: () => {
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
ratingExpanded: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
sx: {
|
||||
cursor: "pointer",
|
||||
transform: "scale(1.5)",
|
||||
":hover": {
|
||||
transform: "scale(1.7)",
|
||||
transition: "0.2s",
|
||||
},
|
||||
},
|
||||
}
|
||||
: { sx: { transform: "scale(1.5)" } })}
|
||||
>
|
||||
{buttonRatingForm.find(({ name }) => listQuestions[quizId][totalIndex].content.form === name)?.icon}
|
||||
</Box>
|
||||
)
|
||||
)}
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
padding: "0 10px",
|
||||
gap: isMobile ? "10px" : "15px",
|
||||
}}
|
||||
>
|
||||
{Array.from(
|
||||
{ length: listQuestions[quizId][totalIndex].content.steps },
|
||||
(_, index) => index
|
||||
).map((itemNumber) => (
|
||||
<Box key={itemNumber} sx={{ transform: "scale(1.5)" }}>
|
||||
{
|
||||
buttonRatingForm.find(
|
||||
({ name }) =>
|
||||
listQuestions[quizId][totalIndex].content.form === name
|
||||
)?.icon
|
||||
}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
@ -99,53 +145,106 @@ export default function RatingOptions({ totalIndex }: Props) {
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
ref={negativeRef}
|
||||
sx={{
|
||||
color: theme.palette.grey2.main,
|
||||
position: "absolute",
|
||||
opacity: 0,
|
||||
zIndex: "-100",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: "16px",
|
||||
fontWeight: 400,
|
||||
}}
|
||||
>
|
||||
Негативно
|
||||
{negativeText}
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
color: theme.palette.grey2.main,
|
||||
fontSize: "16px",
|
||||
fontWeight: 400,
|
||||
<TextField
|
||||
defaultValue={
|
||||
listQuestions[quizId][totalIndex].content
|
||||
.ratingNegativeDescription
|
||||
}
|
||||
value={negativeText}
|
||||
placeholder="Негативно"
|
||||
onChange={({ target }) => {
|
||||
if (target.value.length <= 15) {
|
||||
setNegativeText(target.value);
|
||||
debounceNegativeDescription(target.value);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Позитивно
|
||||
</Typography>
|
||||
</Box>
|
||||
{listQuestions[quizId][totalIndex].content.ratingExpanded &&
|
||||
(listQuestions[quizId][totalIndex].content.ratingDescription ? (
|
||||
<Typography>{listQuestions[quizId][totalIndex].content.ratingDescription}</Typography>
|
||||
) : (
|
||||
<CustomTextField
|
||||
placeholder={"Описание"}
|
||||
text={listQuestions[quizId][totalIndex].content.ratingDescription}
|
||||
onKeyDown={({ target, key }) => {
|
||||
if (key === "Enter") {
|
||||
const currentTarget = target as HTMLInputElement;
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
ratingDescription: currentTarget.value.substring(0, 20),
|
||||
},
|
||||
});
|
||||
}
|
||||
}}
|
||||
onBlur={({ target }) => {
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
ratingDescription: target.value.substring(0, 20),
|
||||
onBlur={({ target }) => debounceNegativeDescription(target.value)}
|
||||
sx={{
|
||||
width: negativeTextWidth + 10 + "px",
|
||||
background: "transparent",
|
||||
fontSize: "18px",
|
||||
minWidth: "95px",
|
||||
maxWidth: "230px",
|
||||
transition: "0.2s",
|
||||
"& .MuiInputBase-root": {
|
||||
"& .MuiInputBase-input": {
|
||||
color: theme.palette.grey2.main,
|
||||
fontSize: "16px",
|
||||
padding: "0 3px",
|
||||
borderRadius: "3px",
|
||||
border: "1px solid",
|
||||
borderColor: "transparent",
|
||||
"&:hover, &:focus": {
|
||||
borderColor: theme.palette.grey2.main,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
},
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
outline: "none",
|
||||
border: "none",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Typography
|
||||
ref={positiveRef}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
opacity: 0,
|
||||
zIndex: "-100",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: "16px",
|
||||
}}
|
||||
>
|
||||
{positiveText}
|
||||
</Typography>
|
||||
<TextField
|
||||
value={positiveText}
|
||||
placeholder="Позитивно"
|
||||
onChange={({ target }) => {
|
||||
if (target.value.length <= 15) {
|
||||
setPositiveText(target.value);
|
||||
debouncePositiveDescription(target.value);
|
||||
}
|
||||
}}
|
||||
onBlur={({ target }) => debouncePositiveDescription(target.value)}
|
||||
sx={{
|
||||
width: positiveTextWidth + 10 + "px",
|
||||
background: "transparent",
|
||||
fontSize: "18px",
|
||||
minWidth: "95px",
|
||||
maxWidth: "230px",
|
||||
transition: "0.2s",
|
||||
"& .MuiInputBase-root": {
|
||||
"& .MuiInputBase-input": {
|
||||
color: theme.palette.grey2.main,
|
||||
fontSize: "16px",
|
||||
padding: "0 3px",
|
||||
borderRadius: "3px",
|
||||
border: "1px solid",
|
||||
borderColor: "transparent",
|
||||
"&:hover, &:focus": {
|
||||
borderColor: theme.palette.grey2.main,
|
||||
},
|
||||
},
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
outline: "none",
|
||||
border: "none",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptions switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} />
|
||||
<SwitchRating switchState={switchState} totalIndex={totalIndex} />
|
||||
|
@ -120,15 +120,18 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
|
||||
</Typography>
|
||||
<Slider
|
||||
value={listQuestions[quizId][totalIndex].content.steps}
|
||||
min={1}
|
||||
min={2}
|
||||
max={10}
|
||||
aria-label="Default"
|
||||
valueLabelDisplay="auto"
|
||||
sx={{ color: theme.palette.brightPurple.main, padding: "0" }}
|
||||
onChange={(_, value) => {
|
||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||
clonContent.steps = Number(value) || 1;
|
||||
updateQuestionsList(quizId, totalIndex, { content: clonContent });
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
...listQuestions[quizId][totalIndex].content,
|
||||
steps: Number(value) || 1,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@ -157,7 +160,13 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Box sx={{ width: isMobile ? "90%" : "auto", display: "flex", alignItems: "center" }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: isMobile ? "90%" : "auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<CustomCheckbox
|
||||
sx={{ mr: isMobile ? "0px" : "16px" }}
|
||||
label={"Внутреннее название вопроса"}
|
||||
|
@ -47,10 +47,14 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
placeholder={"0"}
|
||||
min={0}
|
||||
max={99}
|
||||
value={listQuestions[quizId][totalIndex].content.range.split("—")[0]}
|
||||
value={
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[0]
|
||||
}
|
||||
onChange={({ target }) => {
|
||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||
clonContent.range = `${target.value}—${listQuestions[quizId][totalIndex].content.range.split("—")[1]}`;
|
||||
clonContent.range = `${target.value}—${
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[1]
|
||||
}`;
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: clonContent,
|
||||
});
|
||||
@ -58,12 +62,16 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
onBlur={({ target }) => {
|
||||
const start = listQuestions[quizId][totalIndex].content.start;
|
||||
const min = Number(target.value);
|
||||
const max = Number(listQuestions[quizId][totalIndex].content.range.split("—")[1]);
|
||||
const max = Number(
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[1]
|
||||
);
|
||||
|
||||
if (min >= max) {
|
||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||
clonContent.range = `${max - 1 >= 0 ? max - 1 : 0}—${
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[1]
|
||||
listQuestions[quizId][totalIndex].content.range.split(
|
||||
"—"
|
||||
)[1]
|
||||
}`;
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: clonContent,
|
||||
@ -86,10 +94,14 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
placeholder={"100"}
|
||||
min={0}
|
||||
max={100}
|
||||
value={listQuestions[quizId][totalIndex].content.range.split("—")[1]}
|
||||
value={
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[1]
|
||||
}
|
||||
onChange={({ target }) => {
|
||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||
clonContent.range = `${listQuestions[quizId][totalIndex].content.range.split("—")[0]}—${target.value}`;
|
||||
clonContent.range = `${
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[0]
|
||||
}—${target.value}`;
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: clonContent,
|
||||
});
|
||||
@ -97,15 +109,19 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
onBlur={({ target }) => {
|
||||
const start = listQuestions[quizId][totalIndex].content.start;
|
||||
const step = listQuestions[quizId][totalIndex].content.step;
|
||||
const min = Number(listQuestions[quizId][totalIndex].content.range.split("—")[0]);
|
||||
const min = Number(
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[0]
|
||||
);
|
||||
const max = Number(target.value);
|
||||
const range = max - min;
|
||||
|
||||
if (max <= min) {
|
||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||
clonContent.range = `${listQuestions[quizId][totalIndex].content.range.split("—")[0]}—${
|
||||
min + 1 >= 100 ? 100 : min + 1
|
||||
}`;
|
||||
clonContent.range = `${
|
||||
listQuestions[quizId][totalIndex].content.range.split(
|
||||
"—"
|
||||
)[0]
|
||||
}—${min + 1 >= 100 ? 100 : min + 1}`;
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: clonContent,
|
||||
});
|
||||
@ -129,7 +145,11 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
});
|
||||
|
||||
if (range % step) {
|
||||
setStepError(`Шаг должен делить без остатка диапазон ${max} - ${min} = ${max - min}`);
|
||||
setStepError(
|
||||
`Шаг должен делить без остатка диапазон ${max} - ${min} = ${
|
||||
max - min
|
||||
}`
|
||||
);
|
||||
} else {
|
||||
setStepError("");
|
||||
}
|
||||
@ -154,8 +174,12 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
<CustomNumberField
|
||||
sx={{ maxWidth: "310px", width: "100%" }}
|
||||
placeholder={"50"}
|
||||
min={Number(listQuestions[quizId][totalIndex].content.range.split("—")[0])}
|
||||
max={Number(listQuestions[quizId][totalIndex].content.range.split("—")[1])}
|
||||
min={Number(
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[0]
|
||||
)}
|
||||
max={Number(
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[1]
|
||||
)}
|
||||
value={String(listQuestions[quizId][totalIndex].content.start)}
|
||||
onChange={({ target }) => {
|
||||
const clonContent = listQuestions[quizId][totalIndex].content;
|
||||
@ -167,7 +191,16 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ width: "100%" }}>
|
||||
<Typography sx={{ fontWeight: "500", fontSize: "18px", color: "#4D4D4D", mb: "10px" }}>Шаг</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: "500",
|
||||
fontSize: "18px",
|
||||
color: "#4D4D4D",
|
||||
mb: "10px",
|
||||
}}
|
||||
>
|
||||
Шаг
|
||||
</Typography>
|
||||
<CustomNumberField
|
||||
sx={{ maxWidth: "310px", width: "100%" }}
|
||||
min={0}
|
||||
@ -183,8 +216,12 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
});
|
||||
}}
|
||||
onBlur={({ target }) => {
|
||||
const min = Number(listQuestions[quizId][totalIndex].content.range.split("—")[0]);
|
||||
const max = Number(listQuestions[quizId][totalIndex].content.range.split("—")[1]);
|
||||
const min = Number(
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[0]
|
||||
);
|
||||
const max = Number(
|
||||
listQuestions[quizId][totalIndex].content.range.split("—")[1]
|
||||
);
|
||||
const range = max - min;
|
||||
const step = Number(target.value);
|
||||
|
||||
@ -198,7 +235,11 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
}
|
||||
|
||||
if (range % step) {
|
||||
setStepError(`Шаг должен делить без остатка диапазон ${max} - ${min} = ${max - min}`);
|
||||
setStepError(
|
||||
`Шаг должен делить без остатка диапазон ${max} - ${min} = ${
|
||||
max - min
|
||||
}`
|
||||
);
|
||||
} else {
|
||||
setStepError("");
|
||||
}
|
||||
@ -207,7 +248,11 @@ export default function SliderOptions({ totalIndex }: Props) {
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptions switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} />
|
||||
<ButtonsOptions
|
||||
switchState={switchState}
|
||||
SSHC={SSHC}
|
||||
totalIndex={totalIndex}
|
||||
/>
|
||||
<SwitchSlider switchState={switchState} totalIndex={totalIndex} />
|
||||
</>
|
||||
);
|
||||
|
@ -81,7 +81,13 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) {
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Box sx={{ width: isMobile ? "90%" : "auto", display: "flex", alignItems: "center" }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: isMobile ? "90%" : "auto",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<CustomCheckbox
|
||||
sx={{ mr: isMobile ? "0px" : "16px", whiteSpace: isFigmaTablte ? "nowrap" : "" }}
|
||||
label={"Внутреннее название вопроса"}
|
||||
|
@ -101,7 +101,6 @@ export default function TypeQuestions({ totalIndex }: Props) {
|
||||
<QuestionsMiniButton
|
||||
key={title}
|
||||
onClick={() => {
|
||||
console.log(value);
|
||||
updateQuestionsList(quizId, totalIndex, { type: value });
|
||||
}}
|
||||
icon={icon}
|
||||
|
@ -25,7 +25,7 @@ export default function AnswerOptions({ totalIndex }: Props) {
|
||||
|
||||
const addNewAnswer = () => {
|
||||
const answerNew = variants.slice();
|
||||
answerNew.push({ answer: "", hints: "" });
|
||||
answerNew.push({ answer: "", hints: "", emoji: "" });
|
||||
|
||||
updateQuestionsList(quizId, totalIndex, {
|
||||
content: {
|
||||
@ -92,7 +92,11 @@ export default function AnswerOptions({ totalIndex }: Props) {
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptionsAndPict switchState={switchState} SSHC={SSHC} totalIndex={totalIndex} />
|
||||
<ButtonsOptionsAndPict
|
||||
switchState={switchState}
|
||||
SSHC={SSHC}
|
||||
totalIndex={totalIndex}
|
||||
/>
|
||||
<SwitchAnswerOptions switchState={switchState} totalIndex={totalIndex} />
|
||||
</>
|
||||
);
|
||||
|
@ -32,12 +32,12 @@ const ANSWERS = ["Ответ 1", "Ответ 2", "Ответ 3"];
|
||||
const CONDITIONS = ["Все условия обязательны", "Обязательно хотя бы одно условие"];
|
||||
|
||||
export default function BranchingQuestions({ totalIndex }: BranchingQuestionsProps) {
|
||||
const [title, setTitle] = useState<string>("Заголовок вопроса");
|
||||
const theme = useTheme();
|
||||
const [titleInputWidth, setTitleInputWidth] = useState<number>(0);
|
||||
const quizId = Number(useParams().quizId);
|
||||
const { openedModalSettings, listQuestions } = questionStore();
|
||||
const theme = useTheme();
|
||||
const titleRef = useRef<HTMLDivElement>(null);
|
||||
const [title, setTitle] = useState<string>(listQuestions[quizId][totalIndex].title)
|
||||
|
||||
useEffect(() => {
|
||||
setTitleInputWidth(titleRef.current?.offsetWidth || 0);
|
||||
@ -96,15 +96,18 @@ export default function BranchingQuestions({ totalIndex }: BranchingQuestionsPro
|
||||
<input
|
||||
type="text"
|
||||
value={title}
|
||||
placeholder="Заголовок вопроса"
|
||||
onChange={({ target }) => setTitle(target.value)}
|
||||
style={{
|
||||
width: titleInputWidth,
|
||||
width: titleInputWidth ? titleInputWidth : 170,
|
||||
outline: "none",
|
||||
background: "transparent",
|
||||
border: "none",
|
||||
fontSize: "18px",
|
||||
minWidth: "160px",
|
||||
minWidth: "50px",
|
||||
maxWidth: "500px",
|
||||
fontFamily: "Rubik",
|
||||
transition: ".2s",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
@ -12,4 +12,4 @@ export const ChartLineUp: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||
/>
|
||||
<path d="M19.5 9.75V6H15.75" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
);
|
||||
);
|
||||
|
@ -13,4 +13,4 @@ export const Pencil: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||
<path d="M8.95312 20.2031L3.79688 15.0469" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M3.5 23.5H21" stroke="currentColor" strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
);
|
||||
|
@ -7,4 +7,4 @@ export const People: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
);
|
||||
|
@ -11,4 +11,4 @@ export const Question: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||
/>
|
||||
<circle cx="10.8367" cy="15.5652" r="0.825" fill="currentColor" />
|
||||
</svg>
|
||||
);
|
||||
);
|
||||
|
@ -10,4 +10,4 @@ export const ReturnTime: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
);
|
||||
|
@ -21,4 +21,4 @@ export const Settings: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Stepper from "@ui_kit/Stepper";
|
||||
import SwitchStepPages from "@ui_kit/switchStepPages";
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import PenaLogo from "@ui_kit/PenaLogo";
|
||||
import { Box, Button, Container, FormControl, IconButton, TextField, useMediaQuery, useTheme } from "@mui/material";
|
||||
import BackArrowIcon from "@icons/BackArrowIcon";
|
||||
@ -22,7 +22,7 @@ export default function StartPage() {
|
||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(660));
|
||||
|
||||
const [mobileSidebar, setMobileSidebar] = React.useState<boolean>(false);
|
||||
const [mobileSidebar, setMobileSidebar] = useState<boolean>(false);
|
||||
|
||||
const handleNext = () => {
|
||||
updateQuizesList(params, { step: listQuizes[params].step + 1 });
|
||||
|
@ -68,7 +68,6 @@ export default function StartPageSettings({ handleNext }: HandleNext) {
|
||||
const theme = useTheme();
|
||||
const designType = listQuizes[params].startpage;
|
||||
const StartPageClone = listQuizes[params];
|
||||
console.log(StartPageClone);
|
||||
const [backgroundType, setBackgroundType] = useState(
|
||||
listQuizes[params].config.startpage.background.type
|
||||
);
|
||||
@ -616,7 +615,6 @@ export default function StartPageSettings({ handleNext }: HandleNext) {
|
||||
label="Кликабельный"
|
||||
checked={listQuizes[params].config.info.clickable}
|
||||
handleChange={(e) => {
|
||||
console.log(e.target.checked);
|
||||
let SPageClone = listQuizes[params].config;
|
||||
SPageClone.info.clickable = e.target.checked;
|
||||
updateQuizesList(params, { config: SPageClone });
|
||||
|
@ -28,22 +28,18 @@ export default ({ text, sx, heightImg, widthImg }: Props) => {
|
||||
const [ready, setReady] = useState(false);
|
||||
|
||||
const dragenterHC = () => {
|
||||
// console.log("onDragEnter")
|
||||
setReady(true);
|
||||
};
|
||||
|
||||
const dragexitHC = () => {
|
||||
// console.log("onDragExit")
|
||||
setReady(false);
|
||||
};
|
||||
|
||||
const dropHC = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
// console.log("onDrop")
|
||||
setReady(false);
|
||||
|
||||
const file = event.dataTransfer.files[0];
|
||||
console.log(event.dataTransfer.files[0]);
|
||||
if (file.size < 5242880) {
|
||||
setData(URL.createObjectURL(file));
|
||||
} else {
|
||||
@ -53,7 +49,6 @@ export default ({ text, sx, heightImg, widthImg }: Props) => {
|
||||
|
||||
const dragOverHC = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
// console.log("onDragOver")
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -146,14 +146,11 @@ export default ({ text, sx, heightImg, widthImg }: Props) => {
|
||||
const [favList, setFavList] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(favList);
|
||||
if (favList.length === 18) {
|
||||
console.log("сейчас я сработаю");
|
||||
|
||||
const zip = new JSZip(); //создание зип архива
|
||||
|
||||
favList.forEach((uri, i) => {
|
||||
console.log(i);
|
||||
const idx = uri.indexOf("base64,") + "base64,".length; //обработка строки картинки
|
||||
const content = uri.substring(idx); //обработка строки картинки
|
||||
zip.file(`fav${i}.jpg`, content, { base64: true }); //сохранение картинки в архив с именем "fav.jpg"
|
||||
@ -201,46 +198,26 @@ export default ({ text, sx, heightImg, widthImg }: Props) => {
|
||||
const [ready, setReady] = useState(false);
|
||||
|
||||
const dragenterHC = () => {
|
||||
// console.log("onDragEnter")
|
||||
setReady(true);
|
||||
};
|
||||
|
||||
const dragexitHC = () => {
|
||||
// console.log("onDragExit")
|
||||
setReady(false);
|
||||
};
|
||||
|
||||
const dropHC = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
// console.log("onDrop")
|
||||
setReady(false);
|
||||
const file = event.dataTransfer.files[0];
|
||||
console.log(event.dataTransfer.files[0]);
|
||||
if (file.size < 5242880) {
|
||||
setData(URL.createObjectURL(file));
|
||||
} else {
|
||||
enqueueSnackbar("Размер картинки слишком велик");
|
||||
}
|
||||
// try {
|
||||
// Resizer.imageFileResizer(
|
||||
// file,
|
||||
// 50,
|
||||
// 50,
|
||||
// "JPEG",
|
||||
// 100,
|
||||
// 0,
|
||||
// callback,
|
||||
// );
|
||||
//
|
||||
// } catch (err) {
|
||||
// console.log(err);
|
||||
// }
|
||||
//
|
||||
};
|
||||
|
||||
const dragOverHC = (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
// console.log("onDragOver")
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -13,10 +13,8 @@ export default function StepOne({ handleNext }: HandleNext) {
|
||||
const theme = useTheme();
|
||||
|
||||
const params = Number(useParams().quizId);
|
||||
console.log(params)
|
||||
|
||||
const {listQuizes, updateQuizesList,} = quizStore()
|
||||
console.log(listQuizes)
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
|
@ -4,6 +4,7 @@ import { persist } from "zustand/middleware";
|
||||
export type Variants = {
|
||||
answer: string;
|
||||
hints: string;
|
||||
emoji: string;
|
||||
};
|
||||
|
||||
type Hint = {
|
||||
@ -28,7 +29,8 @@ export interface Question {
|
||||
description: string;
|
||||
type: string;
|
||||
required: boolean;
|
||||
deleted: true;
|
||||
deleted: boolean;
|
||||
deleteTimeoutId: number;
|
||||
page: number;
|
||||
content: {
|
||||
variants: Variants[];
|
||||
@ -63,8 +65,8 @@ export interface Question {
|
||||
chooseRange: boolean;
|
||||
required: boolean;
|
||||
replText: string;
|
||||
ratingExpanded: boolean;
|
||||
ratingDescription: string;
|
||||
ratingNegativeDescription: string;
|
||||
ratingPositiveDescription: string;
|
||||
};
|
||||
version: number;
|
||||
parent_ids: number[];
|
||||
@ -83,7 +85,8 @@ export const DEFAULT_QUESTION: Omit<Question, "id"> = {
|
||||
description: "",
|
||||
type: "",
|
||||
required: true,
|
||||
deleted: true,
|
||||
deleted: false,
|
||||
deleteTimeoutId: 0,
|
||||
page: 0,
|
||||
content: {
|
||||
largeCheck: false,
|
||||
@ -115,12 +118,13 @@ export const DEFAULT_QUESTION: Omit<Question, "id"> = {
|
||||
chooseRange: false,
|
||||
required: false,
|
||||
replText: "",
|
||||
ratingExpanded: false,
|
||||
ratingDescription: "",
|
||||
ratingNegativeDescription: "",
|
||||
ratingPositiveDescription: "",
|
||||
variants: [
|
||||
{
|
||||
answer: "",
|
||||
hints: "",
|
||||
emoji: "",
|
||||
},
|
||||
],
|
||||
hint: {
|
||||
@ -145,15 +149,35 @@ export const DEFAULT_QUESTION: Omit<Question, "id"> = {
|
||||
expanded: false,
|
||||
};
|
||||
|
||||
let isFirstPartialize = true;
|
||||
|
||||
export const questionStore = create<QuestionStore>()(
|
||||
persist<QuestionStore>(
|
||||
() => ({
|
||||
listQuestions: {},
|
||||
openedModalSettings: "",
|
||||
}),
|
||||
|
||||
{
|
||||
name: "question",
|
||||
partialize: (state: QuestionStore) => {
|
||||
if (isFirstPartialize) {
|
||||
isFirstPartialize = false;
|
||||
|
||||
Object.keys(state.listQuestions).forEach((quizId) => {
|
||||
[...state.listQuestions[quizId]].forEach(({ id, deleted }) => {
|
||||
if (deleted) {
|
||||
const removedItemIndex = state.listQuestions[quizId].findIndex(
|
||||
(item) => item.id === id
|
||||
);
|
||||
|
||||
state.listQuestions[quizId].splice(removedItemIndex, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
@ -220,11 +244,18 @@ export const copyQuestion = (quizId: number, copiedQuestionIndex: number) => {
|
||||
questionStore.setState({ listQuestions });
|
||||
};
|
||||
|
||||
export const removeQuestionForce = (quizId: number, removedId: number) => {
|
||||
const questionListClone = { ...questionStore.getState()["listQuestions"] };
|
||||
const removedItemIndex = questionListClone[quizId].findIndex(
|
||||
({ id }) => id === removedId
|
||||
);
|
||||
questionListClone[quizId].splice(removedItemIndex, 1);
|
||||
questionStore.setState({ listQuestions: questionListClone });
|
||||
};
|
||||
|
||||
export const removeQuestion = (quizId: number, index: number) => {
|
||||
const questionListClone = { ...questionStore.getState()["listQuestions"] };
|
||||
|
||||
questionListClone[quizId].splice(index, 1);
|
||||
|
||||
questionListClone[quizId][index].deleted = true;
|
||||
questionStore.setState({ listQuestions: questionListClone });
|
||||
};
|
||||
|
||||
|
26
src/ui_kit/EmojiPicker.tsx
Normal file
26
src/ui_kit/EmojiPicker.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import EmojiPickerOriginal from "@emoji-mart/react";
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
type Emoji = {
|
||||
emoticons: string[];
|
||||
id: string;
|
||||
keywords: string[];
|
||||
name: string;
|
||||
native: string;
|
||||
shortcodes: string;
|
||||
unified: string;
|
||||
};
|
||||
|
||||
type EmojiPickerProps = {
|
||||
onEmojiSelect: (emoji: Emoji) => void;
|
||||
};
|
||||
|
||||
export const EmojiPicker = ({ onEmojiSelect }: EmojiPickerProps) => (
|
||||
<Box sx={{ minWidth: "352px" }}>
|
||||
<EmojiPickerOriginal
|
||||
onEmojiSelect={onEmojiSelect}
|
||||
theme="light"
|
||||
locale="ru"
|
||||
/>
|
||||
</Box>
|
||||
);
|
@ -155,9 +155,6 @@ export const CropModal: FC<Iprops> = ({ opened, onClose, picture }) => {
|
||||
|
||||
const aspect = imageWidth / imageHeight;
|
||||
|
||||
console.log(aspect);
|
||||
|
||||
console.log(width);
|
||||
|
||||
if (aspect <= 1.333) {
|
||||
setWidth(240);
|
||||
|
@ -15,139 +15,143 @@ import LayoutIcon from "../assets/icons/LayoutIcon";
|
||||
import MenuItem from "./MenuItem";
|
||||
|
||||
const createQuizMenuItems = [
|
||||
[LayoutIcon, "Стартовая страница"],
|
||||
[QuestionIcon, "Вопросы"],
|
||||
[ChartPieIcon, "Результаты"],
|
||||
[ContactBookIcon, "Форма контактов"],
|
||||
[FlowArrowIcon, "Установка квиза"],
|
||||
[MegaphoneIcon, "Запуск рекламы"],
|
||||
[LayoutIcon, "Стартовая страница"],
|
||||
[QuestionIcon, "Вопросы"],
|
||||
[ChartPieIcon, "Результаты"],
|
||||
[ContactBookIcon, "Форма контактов"],
|
||||
[FlowArrowIcon, "Установка квиза"],
|
||||
[MegaphoneIcon, "Запуск рекламы"],
|
||||
] as const;
|
||||
|
||||
const quizSettingsMenuItems = [
|
||||
[TagIcon, "Дополнения"],
|
||||
[PencilCircleIcon, "Дизайн"],
|
||||
[PuzzlePieceIcon, "Интеграции"],
|
||||
[GearIcon, "Настройки"],
|
||||
[TagIcon, "Дополнения"],
|
||||
[PencilCircleIcon, "Дизайн"],
|
||||
[PuzzlePieceIcon, "Интеграции"],
|
||||
[GearIcon, "Настройки"],
|
||||
] as const;
|
||||
|
||||
|
||||
export default function Sidebar() {
|
||||
const theme = useTheme();
|
||||
const [isMenuCollapsed, setIsMenuCollapsed] = useState(false);
|
||||
const [activeMenuItemIndex, setActiveMenuItemIndex] = useState<number>(0);
|
||||
const [progress, setProgress] = useState<number>(1 / 6);
|
||||
const theme = useTheme();
|
||||
const [isMenuCollapsed, setIsMenuCollapsed] = useState(false);
|
||||
const [activeMenuItemIndex, setActiveMenuItemIndex] = useState<number>(0);
|
||||
const [progress, setProgress] = useState<number>(1 / 6);
|
||||
|
||||
const handleMenuCollapseToggle = () => setIsMenuCollapsed(prev => !prev);
|
||||
return (
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: theme.palette.lightPurple.main,
|
||||
minWidth: isMenuCollapsed ? "80px" : "230px",
|
||||
width: isMenuCollapsed ? "80px" : "230px",
|
||||
height: 'calc(100vh - 80px)',
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
py: "19px",
|
||||
transitionProperty: "width, min-width",
|
||||
transitionDuration: "200ms",
|
||||
overflow: "hidden",
|
||||
whiteSpace: "nowrap",
|
||||
boxSizing: "border-box"
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
pl: isMenuCollapsed ? undefined : "16px",
|
||||
pr: isMenuCollapsed ? undefined : "8px",
|
||||
mb: isMenuCollapsed ? "5px" : undefined,
|
||||
alignItems: "center",
|
||||
justifyContent: isMenuCollapsed ? "center" : undefined,
|
||||
}}
|
||||
>
|
||||
{!isMenuCollapsed &&
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
lineHeight: "20px",
|
||||
fontWeight: 500,
|
||||
color: theme.palette.grey2.main,
|
||||
}}
|
||||
>Создание квиза</Typography>
|
||||
}
|
||||
<IconButton onClick={handleMenuCollapseToggle} sx={{ ml: isMenuCollapsed ? undefined : "auto" }}>
|
||||
<CollapseMenuIcon height="16px" width="16px" color={theme.palette.grey2.main} transform={isMenuCollapsed ? "rotate(180deg)" : ""} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<List disablePadding>
|
||||
{createQuizMenuItems.map((menuItem, index) => {
|
||||
const Icon = menuItem[0];
|
||||
return (
|
||||
<MenuItem
|
||||
onClick={() => setActiveMenuItemIndex(index)}
|
||||
key={menuItem[1]}
|
||||
text={menuItem[1]}
|
||||
isCollapsed={isMenuCollapsed}
|
||||
isActive={activeMenuItemIndex === index}
|
||||
icon={<Icon
|
||||
color={activeMenuItemIndex === index ?
|
||||
theme.palette.brightPurple.main
|
||||
:
|
||||
isMenuCollapsed ?
|
||||
"white"
|
||||
:
|
||||
theme.palette.grey2.main
|
||||
}
|
||||
height={isMenuCollapsed ? "35px" : "24px"}
|
||||
width={isMenuCollapsed ? "35px" : "24px"}
|
||||
/>}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
{!isMenuCollapsed &&
|
||||
<Typography
|
||||
sx={{
|
||||
px: "16px",
|
||||
mt: "16px",
|
||||
mb: "11px",
|
||||
fontSize: "14px",
|
||||
lineHeight: "20px",
|
||||
fontWeight: 500,
|
||||
color: theme.palette.grey2.main,
|
||||
}}
|
||||
>Настройки квиза</Typography>
|
||||
}
|
||||
<List disablePadding>
|
||||
{quizSettingsMenuItems.map((menuItem, index) => {
|
||||
const Icon = menuItem[0];
|
||||
const totalIndex = index + createQuizMenuItems.length;
|
||||
const isActive = activeMenuItemIndex === totalIndex;
|
||||
return (
|
||||
<MenuItem
|
||||
onClick={() => setActiveMenuItemIndex(totalIndex)}
|
||||
key={menuItem[1]}
|
||||
text={menuItem[1]}
|
||||
isActive={isActive}
|
||||
isCollapsed={isMenuCollapsed}
|
||||
icon={<Icon
|
||||
color={isActive ?
|
||||
theme.palette.brightPurple.main
|
||||
:
|
||||
isMenuCollapsed ?
|
||||
"white"
|
||||
:
|
||||
theme.palette.grey2.main
|
||||
}
|
||||
height={isMenuCollapsed ? "35px" : "24px"}
|
||||
width={isMenuCollapsed ? "35px" : "24px"}
|
||||
/>}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Box>
|
||||
|
||||
)
|
||||
}
|
||||
const handleMenuCollapseToggle = () => setIsMenuCollapsed((prev) => !prev);
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: theme.palette.lightPurple.main,
|
||||
minWidth: isMenuCollapsed ? "80px" : "230px",
|
||||
width: isMenuCollapsed ? "80px" : "230px",
|
||||
height: "calc(100vh - 80px)",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
py: "19px",
|
||||
transitionProperty: "width, min-width",
|
||||
transitionDuration: "200ms",
|
||||
overflow: "hidden",
|
||||
whiteSpace: "nowrap",
|
||||
boxSizing: "border-box",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
pl: isMenuCollapsed ? undefined : "16px",
|
||||
pr: isMenuCollapsed ? undefined : "8px",
|
||||
mb: isMenuCollapsed ? "5px" : undefined,
|
||||
alignItems: "center",
|
||||
justifyContent: isMenuCollapsed ? "center" : undefined,
|
||||
}}
|
||||
>
|
||||
{!isMenuCollapsed && (
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
lineHeight: "20px",
|
||||
fontWeight: 500,
|
||||
color: theme.palette.grey2.main,
|
||||
}}
|
||||
>
|
||||
Создание квиза
|
||||
</Typography>
|
||||
)}
|
||||
<IconButton onClick={handleMenuCollapseToggle} sx={{ ml: isMenuCollapsed ? undefined : "auto" }}>
|
||||
<CollapseMenuIcon
|
||||
height="16px"
|
||||
width="16px"
|
||||
color={theme.palette.grey2.main}
|
||||
transform={isMenuCollapsed ? "rotate(180deg)" : ""}
|
||||
/>
|
||||
</IconButton>
|
||||
</Box>
|
||||
<List disablePadding>
|
||||
{createQuizMenuItems.map((menuItem, index) => {
|
||||
const Icon = menuItem[0];
|
||||
return (
|
||||
<MenuItem
|
||||
onClick={() => setActiveMenuItemIndex(index)}
|
||||
key={menuItem[1]}
|
||||
text={menuItem[1]}
|
||||
isCollapsed={isMenuCollapsed}
|
||||
isActive={activeMenuItemIndex === index}
|
||||
icon={
|
||||
<Icon
|
||||
color={
|
||||
activeMenuItemIndex === index
|
||||
? theme.palette.brightPurple.main
|
||||
: isMenuCollapsed
|
||||
? "white"
|
||||
: theme.palette.grey2.main
|
||||
}
|
||||
height={isMenuCollapsed ? "35px" : "24px"}
|
||||
width={isMenuCollapsed ? "35px" : "24px"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
{!isMenuCollapsed && (
|
||||
<Typography
|
||||
sx={{
|
||||
px: "16px",
|
||||
mt: "16px",
|
||||
mb: "11px",
|
||||
fontSize: "14px",
|
||||
lineHeight: "20px",
|
||||
fontWeight: 500,
|
||||
color: theme.palette.grey2.main,
|
||||
}}
|
||||
>
|
||||
Настройки квиза
|
||||
</Typography>
|
||||
)}
|
||||
<List disablePadding>
|
||||
{quizSettingsMenuItems.map((menuItem, index) => {
|
||||
const Icon = menuItem[0];
|
||||
const totalIndex = index + createQuizMenuItems.length;
|
||||
const isActive = activeMenuItemIndex === totalIndex;
|
||||
return (
|
||||
<MenuItem
|
||||
onClick={() => setActiveMenuItemIndex(totalIndex)}
|
||||
key={menuItem[1]}
|
||||
text={menuItem[1]}
|
||||
isActive={isActive}
|
||||
isCollapsed={isMenuCollapsed}
|
||||
icon={
|
||||
<Icon
|
||||
color={
|
||||
isActive ? theme.palette.brightPurple.main : isMenuCollapsed ? "white" : theme.palette.grey2.main
|
||||
}
|
||||
height={isMenuCollapsed ? "35px" : "24px"}
|
||||
width={isMenuCollapsed ? "35px" : "24px"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ class Resizer {
|
||||
Yoffset = Math.round((size - height) / 2)
|
||||
}
|
||||
|
||||
console.log(height, width)
|
||||
|
||||
ctx.drawImage(image, Xoffset, Yoffset, width, height);
|
||||
|
||||
|
15
yarn.lock
15
yarn.lock
@ -1218,6 +1218,16 @@
|
||||
resolved "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz"
|
||||
integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==
|
||||
|
||||
"@emoji-mart/data@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@emoji-mart/data/-/data-1.1.2.tgz#777c976f8f143df47cbb23a7077c9ca9fe5fc513"
|
||||
integrity sha512-1HP8BxD2azjqWJvxIaWAMyTySeZY0Osr83ukYjltPVkNXeJvTz7yDrPLBtnrD5uqJ3tg4CcLuuBW09wahqL/fg==
|
||||
|
||||
"@emoji-mart/react@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@emoji-mart/react/-/react-1.1.1.tgz#ddad52f93a25baf31c5383c3e7e4c6e05554312a"
|
||||
integrity sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==
|
||||
|
||||
"@emotion/babel-plugin@^11.10.5":
|
||||
version "11.10.5"
|
||||
resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.5.tgz"
|
||||
@ -4163,6 +4173,11 @@ emittery@^0.8.1:
|
||||
resolved "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz"
|
||||
integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==
|
||||
|
||||
emoji-mart@^5.5.2:
|
||||
version "5.5.2"
|
||||
resolved "https://registry.yarnpkg.com/emoji-mart/-/emoji-mart-5.5.2.tgz#3ddbaf053139cf4aa217650078bc1c50ca8381af"
|
||||
integrity sha512-Sqc/nso4cjxhOwWJsp9xkVm8OF5c+mJLZJFoFfzRuKO+yWiN7K8c96xmtughYb0d/fZ8UC6cLIQ/p4BR6Pv3/A==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user