diff --git a/package.json b/package.json index cd513276..64e4ba21 100755 --- a/package.json +++ b/package.json @@ -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" } diff --git a/src/assets/icons/BackArrowIcon.tsx b/src/assets/icons/BackArrowIcon.tsx index b7c6bdf6..cbfef395 100755 --- a/src/assets/icons/BackArrowIcon.tsx +++ b/src/assets/icons/BackArrowIcon.tsx @@ -1,26 +1,26 @@ import { Box } from "@mui/material"; export default function BackArrowIcon({ color = "black" }: { color?: string }) { - return ( - - - - - - - ); - } \ No newline at end of file + return ( + + + + + + + ); +} diff --git a/src/assets/icons/Burger.tsx b/src/assets/icons/Burger.tsx index 60748139..eb247987 100644 --- a/src/assets/icons/Burger.tsx +++ b/src/assets/icons/Burger.tsx @@ -6,4 +6,4 @@ export const Burger: FC> = (props) => ( -); \ No newline at end of file +); diff --git a/src/assets/icons/ChartPieIcon.tsx b/src/assets/icons/ChartPieIcon.tsx index f9dd4254..6671f740 100755 --- a/src/assets/icons/ChartPieIcon.tsx +++ b/src/assets/icons/ChartPieIcon.tsx @@ -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 ( - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/addImage.tsx b/src/assets/icons/questionsPage/addImage.tsx index 25285ee7..3842072d 100644 --- a/src/assets/icons/questionsPage/addImage.tsx +++ b/src/assets/icons/questionsPage/addImage.tsx @@ -17,6 +17,7 @@ const AddImage: FC = ({ onClick, sx }) => { alignItems: "center", justifyContent: "center", cursor: "pointer", + ...sx, }} > diff --git a/src/assets/icons/questionsPage/plus.tsx b/src/assets/icons/questionsPage/plus.tsx new file mode 100644 index 00000000..eddbe273 --- /dev/null +++ b/src/assets/icons/questionsPage/plus.tsx @@ -0,0 +1,32 @@ +import { Box } from "@mui/material"; + +export default function Plus() { + return ( + + + + + + + ); +} diff --git a/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx b/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx index 5173ff5c..774e624e 100644 --- a/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx +++ b/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx @@ -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", + // }} > - {icon && icon} + {additionalContent} ), endAdornment: ( @@ -126,11 +149,13 @@ export const AnswerItem = ({ index, totalIndex, variants, variant, icon }: Answe + {additionalMobile} )} diff --git a/src/pages/Questions/AnswerDraggableList/index.tsx b/src/pages/Questions/AnswerDraggableList/index.tsx index 2c5b075f..7086c648 100644 --- a/src/pages/Questions/AnswerDraggableList/index.tsx +++ b/src/pages/Questions/AnswerDraggableList/index.tsx @@ -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} diff --git a/src/pages/Questions/ButtonsOptions.tsx b/src/pages/Questions/ButtonsOptions.tsx index f02d9c88..40f41b8f 100644 --- a/src/pages/Questions/ButtonsOptions.tsx +++ b/src/pages/Questions/ButtonsOptions.tsx @@ -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(false); + const { openedModalSettings, listQuestions } = questionStore(); + const [openedReallyChangingModal, setOpenedReallyChangingModal] = + useState(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: , + icon: ( + + ), title: "Настройки", value: "setting", }, { - icon: , + icon: ( + + ), title: "Подсказка", value: "help", }, { - icon: , + icon: ( + + ), title: "Ветвление", value: "branching", myFunc: openedModal, @@ -78,7 +105,7 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props) }} > {buttonSetting.map(({ icon, title, value, myFunc }) => ( - <> + {value === "branching" ? ( Будет показан при условии - Название + + Название + Условие 1, Условие 2 - Все условия обязательны + + Все условия обязательны + } > @@ -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} )} - + ))} setOpenedReallyChangingModal(true)} @@ -188,13 +230,35 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props) - copyQuestion(quizId, totalIndex)}> - + copyQuestion(quizId, totalIndex)} + > + - removeQuestion(quizId, totalIndex)}> - + { + 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, + }); + }} + > + ); -} +} \ No newline at end of file diff --git a/src/pages/Questions/ButtonsOptionsAndPict.tsx b/src/pages/Questions/ButtonsOptionsAndPict.tsx index 9fd0d430..1f4d714d 100644 --- a/src/pages/Questions/ButtonsOptionsAndPict.tsx +++ b/src/pages/Questions/ButtonsOptionsAndPict.tsx @@ -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(""); const quizId = Number(useParams().quizId); - const { openedModalSettings } = questionStore(); + const { listQuestions } = questionStore(); + const [openedReallyChangingModal, setOpenedReallyChangingModal] = + useState(false); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isIconMobile = useMediaQuery(theme.breakpoints.down(1050)); - const [openedReallyChangingModal, setOpenedReallyChangingModal] = useState(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 : "Изображение"} - setOpenedReallyChangingModal(true)} sx={{ @@ -243,12 +256,37 @@ export default function ButtonsOptionsAndPict({ SSHC, switchState, totalIndex }: removeQuestion(quizId, totalIndex)} + onClick={() => copyQuestion(quizId, totalIndex)} + > + + + { + 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, + }); + }} > - setOpenedReallyChangingModal(false)} /> + setOpenedReallyChangingModal(false)} + /> ); } diff --git a/src/pages/Questions/DataOptions/settingData.tsx b/src/pages/Questions/DataOptions/settingData.tsx index 0359855f..6d0ca794 100644 --- a/src/pages/Questions/DataOptions/settingData.tsx +++ b/src/pages/Questions/DataOptions/settingData.tsx @@ -57,7 +57,7 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) { }} /> { @@ -92,8 +92,9 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) { }); }} /> - + { diff --git a/src/pages/Questions/DraggableList/ChooseAnswerModal.tsx b/src/pages/Questions/DraggableList/ChooseAnswerModal.tsx index 90e10705..17d70e6b 100644 --- a/src/pages/Questions/DraggableList/ChooseAnswerModal.tsx +++ b/src/pages/Questions/DraggableList/ChooseAnswerModal.tsx @@ -11,6 +11,7 @@ import { ClickAwayListener, Modal, Button, + useTheme, } from "@mui/material"; import { @@ -27,6 +28,7 @@ type ChooseAnswerModalProps = { onClose: () => void; anchorRef: RefObject; totalIndex: number; + switchState: string; }; export const ChooseAnswerModal = ({ @@ -34,11 +36,13 @@ export const ChooseAnswerModal = ({ onClose, anchorRef, totalIndex, + switchState, }: ChooseAnswerModalProps) => { const [openModal, setOpenModal] = useState(false); const [selectedValue, setSelectedValue] = useState(""); 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 }) => ( { - onClose(); - setOpenModal(true); - setSelectedValue(value); - }} sx={{ display: "flex", gap: "10px" }} + {...(value !== switchState && { + onClick: () => { + onClose(); + setOpenModal(true); + setSelectedValue(value); + }, + })} > {icon} - {title} + + {title} + ))} diff --git a/src/pages/Questions/DraggableList/DraggableListItem.tsx b/src/pages/Questions/DraggableList/DraggableListItem.tsx index 1f0fb7dd..de222151 100644 --- a/src/pages/Questions/DraggableList/DraggableListItem.tsx +++ b/src/pages/Questions/DraggableList/DraggableListItem.tsx @@ -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) => ( - - {(provided) => ( - - - - - - )} - -); + questionData +}: DraggableListItemProps) => { + const quizId = Number(useParams().quizId); + const theme = useTheme(); + console.log("Мой индекс "+index) + console.log(questionData) + + return ( + + {(provided) => ( + + {questionData.deleted ? ( + + + Вопрос удалён. + + { + updateQuestionsList(quizId, index, { + ...questionData, + deleted: false, + }); + }} + sx={{ + cursor: "pointer", + fontSize: "16px", + textDecoration: "underline", + color: theme.palette.brightPurple.main, + textDecorationColor: theme.palette.brightPurple.main, + }} + > + Восстановить? + + + ) : ( + + + + )} + + )} + + ); +}); diff --git a/src/pages/Questions/DraggableList/QuestionPageCard.tsx b/src/pages/Questions/DraggableList/QuestionPageCard.tsx index 51d80a8f..ddcf5acb 100644 --- a/src/pages/Questions/DraggableList/QuestionPageCard.tsx +++ b/src/pages/Questions/DraggableList/QuestionPageCard.tsx @@ -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 ( <> setOpen(false)} anchorRef={anchorRef} totalIndex={totalIndex} + switchState={switchState} /> ), @@ -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, + }); + }} > diff --git a/src/pages/Questions/DraggableList/index.tsx b/src/pages/Questions/DraggableList/index.tsx index 4eeb5631..7ff2474c 100644 --- a/src/pages/Questions/DraggableList/index.tsx +++ b/src/pages/Questions/DraggableList/index.tsx @@ -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) => ( {listQuestions[quizId]?.map((_, index) => ( - + ))} {provided.placeholder} diff --git a/src/pages/Questions/DropDown/DropDown.tsx b/src/pages/Questions/DropDown/DropDown.tsx index 751b2849..eb2ee558 100644 --- a/src/pages/Questions/DropDown/DropDown.tsx +++ b/src/pages/Questions/DropDown/DropDown.tsx @@ -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) { )} - + ); diff --git a/src/pages/Questions/Emoji/Emoji.tsx b/src/pages/Questions/Emoji/Emoji.tsx index 325fa31c..9333a810 100644 --- a/src/pages/Questions/Emoji/Emoji.tsx +++ b/src/pages/Questions/Emoji/Emoji.tsx @@ -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("setting"); + const [open, setOpen] = useState(false); + const [anchorElement, setAnchorElement] = useState( + null + ); + const [currentIndex, setCurrentIndex] = useState(0); const { listQuestions } = questionStore(); const quizId = Number(useParams().quizId); const theme = useTheme(); @@ -42,7 +50,7 @@ export default function Emoji({ totalIndex }: Props) { return ( <> - + {/* )} - + */} + + ( + <> + {!isTablet && ( + + { + setAnchorElement(currentTarget); + setCurrentIndex(index); + setOpen(true); + }} + > + + {variant.emoji ? ( + + {variant.emoji} + + + + + ) : ( + + )} + + + + )} + + )} + additionalMobile={(variant, index) => ( + <> + {isTablet && ( + { + setAnchorElement(currentTarget); + setCurrentIndex(index); + setOpen(true); + }} + sx={{ + display: "flex", + alignItems: "center", + m: "8px", + position: "relative", + }} + > + + {variant.emoji ? ( + + {variant.emoji} + + ) : ( + + )} + + + + + + )} + + )} + /> + event.stopPropagation()} + onClose={() => setOpen(false)} + anchorOrigin={{ + vertical: "bottom", + horizontal: "right", + }} + sx={{ + ".MuiPaper-root.MuiPaper-rounded": { + borderRadius: "10px", + }, + }} + > + { + 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, + }, + }); + }} + /> + + { - 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) { > Добавьте ответ - {isMobile ? null : ( + {!isTablet && ( <> - + ); diff --git a/src/pages/Questions/Emoji/settingEmoji.tsx b/src/pages/Questions/Emoji/settingEmoji.tsx index ce644239..6732d8b4 100644 --- a/src/pages/Questions/Emoji/settingEmoji.tsx +++ b/src/pages/Questions/Emoji/settingEmoji.tsx @@ -59,7 +59,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) { }} /> { @@ -85,6 +85,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) { Настройки вопросов { @@ -95,6 +96,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) { /> { diff --git a/src/pages/Questions/OptionsAndPicture/OptionsAndPicture.tsx b/src/pages/Questions/OptionsAndPicture/OptionsAndPicture.tsx index f3a0594e..a9843cf2 100644 --- a/src/pages/Questions/OptionsAndPicture/OptionsAndPicture.tsx +++ b/src/pages/Questions/OptionsAndPicture/OptionsAndPicture.tsx @@ -54,6 +54,7 @@ export default function OptionsAndPicture({ totalIndex }: Props) { > {listQuestions[quizId][totalIndex].content.variants.map((_, index) => ( - - - + + @@ -205,10 +212,25 @@ export default function OptionsAndPicture({ totalIndex }: Props) { /> {isMobile && ( - - + + { + const clonContent = listQuestions[quizId][totalIndex].content; + clonContent.variants.push({ answer: "", hints: "", emoji: "" }); + + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} > Добавьте ответ @@ -265,7 +293,11 @@ export default function OptionsAndPicture({ totalIndex }: Props) { )} - + ); diff --git a/src/pages/Questions/OptionsPicture/OptionsPicture.tsx b/src/pages/Questions/OptionsPicture/OptionsPicture.tsx index c63e865f..645849d3 100644 --- a/src/pages/Questions/OptionsPicture/OptionsPicture.tsx +++ b/src/pages/Questions/OptionsPicture/OptionsPicture.tsx @@ -53,6 +53,7 @@ export default function OptionsPicture({ totalIndex }: Props) { } }; + return ( <> @@ -95,7 +96,6 @@ export default function OptionsPicture({ totalIndex }: Props) { + - - - + + @@ -192,10 +199,25 @@ export default function OptionsPicture({ totalIndex }: Props) { /> {isMobile && ( - - + + - - + + ); } diff --git a/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx b/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx index 91f40993..3463c4e8 100644 --- a/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx +++ b/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx @@ -147,19 +147,22 @@ export default function SettingOpytionsPict({ totalIndex }: SettingOpytionsPictP }) } /> - - updateQuestionsList(quizId, totalIndex, { - content: { - ...listQuestions[quizId][totalIndex].content, - largeCheck: target.checked, - }, - }) - } - /> + {listQuestions[quizId][totalIndex].content.xy !== "1:1" && + listQuestions[quizId][totalIndex].content.format !== "masonry" && ( + + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + largeCheck: target.checked, + }, + }) + } + /> + )} - - + { diff --git a/src/pages/Questions/QuestionsPage.tsx b/src/pages/Questions/QuestionsPage.tsx index 1ecb607c..a712be3e 100755 --- a/src/pages/Questions/QuestionsPage.tsx +++ b/src/pages/Questions/QuestionsPage.tsx @@ -77,7 +77,6 @@ export default function QuestionsPage() { { createQuestion(quizId); - console.log(listQuestions); }} > diff --git a/src/pages/Questions/RatingOptions/RatingOptions.tsx b/src/pages/Questions/RatingOptions/RatingOptions.tsx index 1eca0c72..c36cffa3 100644 --- a/src/pages/Questions/RatingOptions/RatingOptions.tsx +++ b/src/pages/Questions/RatingOptions/RatingOptions.tsx @@ -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(""); + const [positiveText, setPositiveText] = useState(""); + const [negativeTextWidth, setNegativeTextWidth] = useState(0); + const [positiveTextWidth, setPositiveTextWidth] = useState(0); const quizId = Number(useParams().quizId); const { listQuestions } = questionStore(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(790)); + const negativeRef = useRef(null); + const positiveRef = useRef(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: }, @@ -51,42 +96,43 @@ export default function RatingOptions({ totalIndex }: Props) { <> + negativeTextWidth + positiveTextWidth + ? listQuestions[quizId][totalIndex].content.steps * 44 + : negativeTextWidth + positiveTextWidth + 20 + }px`, + minWidth: "300px", + maxWidth: "440px", display: "flex", px: "20px", flexDirection: "column", gap: "20px", }} > - - {Array.from({ length: listQuestions[quizId][totalIndex].content.steps }, (_, index) => index).map( - (itemNumber) => ( - { - 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} - - ) - )} + + {Array.from( + { length: listQuestions[quizId][totalIndex].content.steps }, + (_, index) => index + ).map((itemNumber) => ( + + { + buttonRatingForm.find( + ({ name }) => + listQuestions[quizId][totalIndex].content.form === name + )?.icon + } + + ))} - Негативно + {negativeText} - { + if (target.value.length <= 15) { + setNegativeText(target.value); + debounceNegativeDescription(target.value); + } }} - > - Позитивно - - - {listQuestions[quizId][totalIndex].content.ratingExpanded && - (listQuestions[quizId][totalIndex].content.ratingDescription ? ( - {listQuestions[quizId][totalIndex].content.ratingDescription} - ) : ( - { - 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", + }, + }, + }} + /> + + {positiveText} + + { + 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", + }, + }, + }} + /> + diff --git a/src/pages/Questions/RatingOptions/settingRating.tsx b/src/pages/Questions/RatingOptions/settingRating.tsx index ffd1e864..b46ba1ac 100644 --- a/src/pages/Questions/RatingOptions/settingRating.tsx +++ b/src/pages/Questions/RatingOptions/settingRating.tsx @@ -120,15 +120,18 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) { { - 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, + }, + }); }} /> @@ -157,7 +160,13 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) { }); }} /> - + { 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) { { const clonContent = listQuestions[quizId][totalIndex].content; @@ -167,7 +191,16 @@ export default function SliderOptions({ totalIndex }: Props) { /> - Шаг + + Шаг + { - 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) { - + ); diff --git a/src/pages/Questions/SliderOptions/settingSlider.tsx b/src/pages/Questions/SliderOptions/settingSlider.tsx index 34b23649..e4bf757e 100644 --- a/src/pages/Questions/SliderOptions/settingSlider.tsx +++ b/src/pages/Questions/SliderOptions/settingSlider.tsx @@ -81,7 +81,13 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) { }); }} /> - + { - console.log(value); updateQuestionsList(quizId, totalIndex, { type: value }); }} icon={icon} diff --git a/src/pages/Questions/answerOptions/AnswerOptions.tsx b/src/pages/Questions/answerOptions/AnswerOptions.tsx index 45c2483f..f3c26c52 100755 --- a/src/pages/Questions/answerOptions/AnswerOptions.tsx +++ b/src/pages/Questions/answerOptions/AnswerOptions.tsx @@ -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) { )} - + ); diff --git a/src/pages/Questions/branchingQuestions.tsx b/src/pages/Questions/branchingQuestions.tsx index 4b8fa004..7db88e1c 100644 --- a/src/pages/Questions/branchingQuestions.tsx +++ b/src/pages/Questions/branchingQuestions.tsx @@ -32,12 +32,12 @@ const ANSWERS = ["Ответ 1", "Ответ 2", "Ответ 3"]; const CONDITIONS = ["Все условия обязательны", "Обязательно хотя бы одно условие"]; export default function BranchingQuestions({ totalIndex }: BranchingQuestionsProps) { - const [title, setTitle] = useState("Заголовок вопроса"); + const theme = useTheme(); const [titleInputWidth, setTitleInputWidth] = useState(0); const quizId = Number(useParams().quizId); const { openedModalSettings, listQuestions } = questionStore(); - const theme = useTheme(); const titleRef = useRef(null); + const [title, setTitle] = useState(listQuestions[quizId][totalIndex].title) useEffect(() => { setTitleInputWidth(titleRef.current?.offsetWidth || 0); @@ -96,15 +96,18 @@ export default function BranchingQuestions({ totalIndex }: BranchingQuestionsPro diff --git a/src/pages/startPage/Sidebar/icons/ChartLineUp.tsx b/src/pages/startPage/Sidebar/icons/ChartLineUp.tsx index 43828861..acef1b80 100644 --- a/src/pages/startPage/Sidebar/icons/ChartLineUp.tsx +++ b/src/pages/startPage/Sidebar/icons/ChartLineUp.tsx @@ -12,4 +12,4 @@ export const ChartLineUp: FC> = (props) => ( /> -); \ No newline at end of file +); diff --git a/src/pages/startPage/Sidebar/icons/Pencil.tsx b/src/pages/startPage/Sidebar/icons/Pencil.tsx index 10d6fa61..c2db708d 100644 --- a/src/pages/startPage/Sidebar/icons/Pencil.tsx +++ b/src/pages/startPage/Sidebar/icons/Pencil.tsx @@ -13,4 +13,4 @@ export const Pencil: FC> = (props) => ( -); \ No newline at end of file +); diff --git a/src/pages/startPage/Sidebar/icons/People.tsx b/src/pages/startPage/Sidebar/icons/People.tsx index 7a4566a5..d880126d 100644 --- a/src/pages/startPage/Sidebar/icons/People.tsx +++ b/src/pages/startPage/Sidebar/icons/People.tsx @@ -7,4 +7,4 @@ export const People: FC> = (props) => ( fill="currentColor" /> -); \ No newline at end of file +); diff --git a/src/pages/startPage/Sidebar/icons/Question.tsx b/src/pages/startPage/Sidebar/icons/Question.tsx index 5a743b3d..69989347 100644 --- a/src/pages/startPage/Sidebar/icons/Question.tsx +++ b/src/pages/startPage/Sidebar/icons/Question.tsx @@ -11,4 +11,4 @@ export const Question: FC> = (props) => ( /> -); \ No newline at end of file +); diff --git a/src/pages/startPage/Sidebar/icons/ReturnTime.tsx b/src/pages/startPage/Sidebar/icons/ReturnTime.tsx index a50b89c5..3724be6e 100644 --- a/src/pages/startPage/Sidebar/icons/ReturnTime.tsx +++ b/src/pages/startPage/Sidebar/icons/ReturnTime.tsx @@ -10,4 +10,4 @@ export const ReturnTime: FC> = (props) => ( stroke-linejoin="round" /> -); \ No newline at end of file +); diff --git a/src/pages/startPage/Sidebar/icons/Settings.tsx b/src/pages/startPage/Sidebar/icons/Settings.tsx index 27796802..d96c590b 100644 --- a/src/pages/startPage/Sidebar/icons/Settings.tsx +++ b/src/pages/startPage/Sidebar/icons/Settings.tsx @@ -21,4 +21,4 @@ export const Settings: FC> = (props) => ( strokeLinejoin="round" /> -); \ No newline at end of file +); diff --git a/src/pages/startPage/StartPage.tsx b/src/pages/startPage/StartPage.tsx index 3764fe17..a4037374 100755 --- a/src/pages/startPage/StartPage.tsx +++ b/src/pages/startPage/StartPage.tsx @@ -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(false); + const [mobileSidebar, setMobileSidebar] = useState(false); const handleNext = () => { updateQuizesList(params, { step: listQuizes[params].step + 1 }); diff --git a/src/pages/startPage/StartPageSettings.tsx b/src/pages/startPage/StartPageSettings.tsx index 113cd9b6..ec1239a1 100755 --- a/src/pages/startPage/StartPageSettings.tsx +++ b/src/pages/startPage/StartPageSettings.tsx @@ -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 }); diff --git a/src/pages/startPage/dropZone.tsx b/src/pages/startPage/dropZone.tsx index 3a4f785c..d354b077 100644 --- a/src/pages/startPage/dropZone.tsx +++ b/src/pages/startPage/dropZone.tsx @@ -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) => { 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) => { event.preventDefault(); - // console.log("onDragOver") }; return ( diff --git a/src/pages/startPage/dropfavicon.tsx b/src/pages/startPage/dropfavicon.tsx index 2d67ae07..2eace103 100644 --- a/src/pages/startPage/dropfavicon.tsx +++ b/src/pages/startPage/dropfavicon.tsx @@ -146,14 +146,11 @@ export default ({ text, sx, heightImg, widthImg }: Props) => { const [favList, setFavList] = useState([]); 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) => { 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) => { event.preventDefault(); - // console.log("onDragOver") }; return ( diff --git a/src/pages/startPage/stepOne.tsx b/src/pages/startPage/stepOne.tsx index e8cc287a..bf13c9c0 100755 --- a/src/pages/startPage/stepOne.tsx +++ b/src/pages/startPage/stepOne.tsx @@ -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 ( <> = { description: "", type: "", required: true, - deleted: true, + deleted: false, + deleteTimeoutId: 0, page: 0, content: { largeCheck: false, @@ -115,12 +118,13 @@ export const DEFAULT_QUESTION: Omit = { chooseRange: false, required: false, replText: "", - ratingExpanded: false, - ratingDescription: "", + ratingNegativeDescription: "", + ratingPositiveDescription: "", variants: [ { answer: "", hints: "", + emoji: "", }, ], hint: { @@ -145,15 +149,35 @@ export const DEFAULT_QUESTION: Omit = { expanded: false, }; +let isFirstPartialize = true; + export const questionStore = create()( persist( () => ({ 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 }); }; diff --git a/src/ui_kit/EmojiPicker.tsx b/src/ui_kit/EmojiPicker.tsx new file mode 100644 index 00000000..50714d45 --- /dev/null +++ b/src/ui_kit/EmojiPicker.tsx @@ -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) => ( + + + +); diff --git a/src/ui_kit/Modal/CropModal.tsx b/src/ui_kit/Modal/CropModal.tsx index 5c521398..6949edc1 100644 --- a/src/ui_kit/Modal/CropModal.tsx +++ b/src/ui_kit/Modal/CropModal.tsx @@ -155,9 +155,6 @@ export const CropModal: FC = ({ opened, onClose, picture }) => { const aspect = imageWidth / imageHeight; - console.log(aspect); - - console.log(width); if (aspect <= 1.333) { setWidth(240); diff --git a/src/ui_kit/Sidebar.tsx b/src/ui_kit/Sidebar.tsx index 0664f2e2..c84968b8 100755 --- a/src/ui_kit/Sidebar.tsx +++ b/src/ui_kit/Sidebar.tsx @@ -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(0); - const [progress, setProgress] = useState(1 / 6); + const theme = useTheme(); + const [isMenuCollapsed, setIsMenuCollapsed] = useState(false); + const [activeMenuItemIndex, setActiveMenuItemIndex] = useState(0); + const [progress, setProgress] = useState(1 / 6); - const handleMenuCollapseToggle = () => setIsMenuCollapsed(prev => !prev); - return ( - - - - {!isMenuCollapsed && - Создание квиза - } - - - - - - {createQuizMenuItems.map((menuItem, index) => { - const Icon = menuItem[0]; - return ( - setActiveMenuItemIndex(index)} - key={menuItem[1]} - text={menuItem[1]} - isCollapsed={isMenuCollapsed} - isActive={activeMenuItemIndex === index} - icon={} - /> - ); - })} - - {!isMenuCollapsed && - Настройки квиза - } - - {quizSettingsMenuItems.map((menuItem, index) => { - const Icon = menuItem[0]; - const totalIndex = index + createQuizMenuItems.length; - const isActive = activeMenuItemIndex === totalIndex; - return ( - setActiveMenuItemIndex(totalIndex)} - key={menuItem[1]} - text={menuItem[1]} - isActive={isActive} - isCollapsed={isMenuCollapsed} - icon={} - /> - ); - })} - - - - ) -} \ No newline at end of file + const handleMenuCollapseToggle = () => setIsMenuCollapsed((prev) => !prev); + return ( + + + {!isMenuCollapsed && ( + + Создание квиза + + )} + + + + + + {createQuizMenuItems.map((menuItem, index) => { + const Icon = menuItem[0]; + return ( + setActiveMenuItemIndex(index)} + key={menuItem[1]} + text={menuItem[1]} + isCollapsed={isMenuCollapsed} + isActive={activeMenuItemIndex === index} + icon={ + + } + /> + ); + })} + + {!isMenuCollapsed && ( + + Настройки квиза + + )} + + {quizSettingsMenuItems.map((menuItem, index) => { + const Icon = menuItem[0]; + const totalIndex = index + createQuizMenuItems.length; + const isActive = activeMenuItemIndex === totalIndex; + return ( + setActiveMenuItemIndex(totalIndex)} + key={menuItem[1]} + text={menuItem[1]} + isActive={isActive} + isCollapsed={isMenuCollapsed} + icon={ + + } + /> + ); + })} + + + ); +} diff --git a/src/ui_kit/reactImageFileResizer.ts b/src/ui_kit/reactImageFileResizer.ts index 0c2e8ebf..7b4b8498 100644 --- a/src/ui_kit/reactImageFileResizer.ts +++ b/src/ui_kit/reactImageFileResizer.ts @@ -51,7 +51,6 @@ class Resizer { Yoffset = Math.round((size - height) / 2) } - console.log(height, width) ctx.drawImage(image, Xoffset, Yoffset, width, height); diff --git a/yarn.lock b/yarn.lock index aaaf157b..87ce3a16 100755 --- a/yarn.lock +++ b/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"