feat: cancel questin deleting
This commit is contained in:
parent
0c1279b37d
commit
b4f1e4857d
@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
|
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
|
||||||
@ -20,6 +20,8 @@ import {
|
|||||||
resetSomeField,
|
resetSomeField,
|
||||||
copyQuestion,
|
copyQuestion,
|
||||||
removeQuestion,
|
removeQuestion,
|
||||||
|
removeQuestionForce,
|
||||||
|
updateQuestionsList,
|
||||||
} from "@root/questions";
|
} from "@root/questions";
|
||||||
import { DoubleTick } from "@icons/questionsPage/DoubleTick";
|
import { DoubleTick } from "@icons/questionsPage/DoubleTick";
|
||||||
import { DoubleArrowRight } from "@icons/questionsPage/DoubleArrowRight";
|
import { DoubleArrowRight } from "@icons/questionsPage/DoubleArrowRight";
|
||||||
@ -37,10 +39,16 @@ export default function ButtonsOptions({
|
|||||||
totalIndex,
|
totalIndex,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const quizId = Number(useParams().quizId);
|
const quizId = Number(useParams().quizId);
|
||||||
const { openedModalSettings } = questionStore();
|
const { openedModalSettings, listQuestions } = questionStore();
|
||||||
const [openedReallyChangingModal, setOpenedReallyChangingModal] =
|
const [openedReallyChangingModal, setOpenedReallyChangingModal] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||||
|
clearTimeout(listQuestions[quizId][totalIndex].deleteTimeoutId);
|
||||||
|
}
|
||||||
|
}, [listQuestions]);
|
||||||
|
|
||||||
const openedModal = () => {
|
const openedModal = () => {
|
||||||
resetSomeField({ openedModalSettings: "open" });
|
resetSomeField({ openedModalSettings: "open" });
|
||||||
console.log(openedModalSettings);
|
console.log(openedModalSettings);
|
||||||
@ -50,6 +58,7 @@ export default function ButtonsOptions({
|
|||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920));
|
const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920));
|
||||||
|
|
||||||
const buttonSetting: {
|
const buttonSetting: {
|
||||||
icon: JSX.Element;
|
icon: JSX.Element;
|
||||||
title: string;
|
title: string;
|
||||||
@ -241,7 +250,23 @@ export default function ButtonsOptions({
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
sx={{ borderRadius: "6px", padding: "2px" }}
|
sx={{ 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 color={"#4D4D4D"} />
|
<DeleteIcon color={"#4D4D4D"} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
import MiniButtonSetting from "@ui_kit/MiniButtonSetting";
|
||||||
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
|
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
|
||||||
import Clue from "../../assets/icons/questionsPage/clue";
|
import Clue from "../../assets/icons/questionsPage/clue";
|
||||||
@ -21,13 +21,14 @@ import {
|
|||||||
copyQuestion,
|
copyQuestion,
|
||||||
removeQuestion,
|
removeQuestion,
|
||||||
resetSomeField,
|
resetSomeField,
|
||||||
|
removeQuestionForce,
|
||||||
|
updateQuestionsList,
|
||||||
} from "@root/questions";
|
} from "@root/questions";
|
||||||
import { DoubleArrowRight } from "@icons/questionsPage/DoubleArrowRight";
|
import { DoubleArrowRight } from "@icons/questionsPage/DoubleArrowRight";
|
||||||
import { DoubleTick } from "@icons/questionsPage/DoubleTick";
|
import { DoubleTick } from "@icons/questionsPage/DoubleTick";
|
||||||
import { VectorQuestions } from "@icons/questionsPage/VectorQuestions";
|
import { VectorQuestions } from "@icons/questionsPage/VectorQuestions";
|
||||||
import { ReallyChangingModal } from "@ui_kit/Modal/ReallyChangingModal/ReallyChangingModal";
|
import { ReallyChangingModal } from "@ui_kit/Modal/ReallyChangingModal/ReallyChangingModal";
|
||||||
|
|
||||||
|
|
||||||
import "./ButtonsOptionsAndPict.css";
|
import "./ButtonsOptionsAndPict.css";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -43,12 +44,19 @@ export default function ButtonsOptionsAndPict({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
const [buttonHover, setButtonHover] = useState<string>("");
|
const [buttonHover, setButtonHover] = useState<string>("");
|
||||||
const quizId = Number(useParams().quizId);
|
const quizId = Number(useParams().quizId);
|
||||||
const { openedModalSettings } = questionStore();
|
const { listQuestions } = questionStore();
|
||||||
const [openedReallyChangingModal, setOpenedReallyChangingModal] = useState<boolean>(false);
|
const [openedReallyChangingModal, setOpenedReallyChangingModal] =
|
||||||
|
useState<boolean>(false);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||||
const isIconMobile = useMediaQuery(theme.breakpoints.down(1050));
|
const isIconMobile = useMediaQuery(theme.breakpoints.down(1050));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||||
|
clearTimeout(listQuestions[quizId][totalIndex].deleteTimeoutId);
|
||||||
|
}
|
||||||
|
}, [listQuestions]);
|
||||||
|
|
||||||
const openedModal = () => {
|
const openedModal = () => {
|
||||||
resetSomeField({ openedModalSettings: "open" });
|
resetSomeField({ openedModalSettings: "open" });
|
||||||
};
|
};
|
||||||
@ -280,13 +288,32 @@ export default function ButtonsOptionsAndPict({
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
sx={{ borderRadius: "6px", padding: "2px" }}
|
sx={{ 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 color={"#4D4D4D"} />
|
<DeleteIcon color={"#4D4D4D"} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<ReallyChangingModal opened={openedReallyChangingModal} onClose={() => setOpenedReallyChangingModal(false)} />
|
<ReallyChangingModal
|
||||||
|
opened={openedReallyChangingModal}
|
||||||
|
onClose={() => setOpenedReallyChangingModal(false)}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
import { useParams } from "react-router-dom";
|
||||||
import { Draggable } from "react-beautiful-dnd";
|
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 QuestionsPageCard from "./QuestionPageCard";
|
||||||
|
|
||||||
|
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||||
|
|
||||||
type DraggableListItemProps = {
|
type DraggableListItemProps = {
|
||||||
index: number;
|
index: number;
|
||||||
isDragging: boolean;
|
isDragging: boolean;
|
||||||
@ -11,23 +14,69 @@ type DraggableListItemProps = {
|
|||||||
export const DraggableListItem = ({
|
export const DraggableListItem = ({
|
||||||
index,
|
index,
|
||||||
isDragging,
|
isDragging,
|
||||||
}: DraggableListItemProps) => (
|
}: DraggableListItemProps) => {
|
||||||
<Draggable draggableId={String(index)} index={index}>
|
const quizId = Number(useParams().quizId);
|
||||||
{(provided) => (
|
const { listQuestions } = questionStore();
|
||||||
<ListItem
|
const theme = useTheme();
|
||||||
ref={provided.innerRef}
|
|
||||||
{...provided.draggableProps}
|
return (
|
||||||
sx={{ userSelect: "none", padding: 0 }}
|
<Draggable draggableId={String(index)} index={index}>
|
||||||
>
|
{(provided) => (
|
||||||
<Box sx={{ width: "100%", position: "relative" }}>
|
<ListItem
|
||||||
<QuestionsPageCard
|
ref={provided.innerRef}
|
||||||
key={index}
|
{...provided.draggableProps}
|
||||||
totalIndex={index}
|
sx={{ userSelect: "none", padding: 0 }}
|
||||||
draggableProps={provided.dragHandleProps}
|
>
|
||||||
isDragging={isDragging}
|
{listQuestions[quizId][index].deleted ? (
|
||||||
/>
|
<Box
|
||||||
</Box>
|
{...provided.dragHandleProps}
|
||||||
</ListItem>
|
sx={{
|
||||||
)}
|
width: "100%",
|
||||||
</Draggable>
|
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, {
|
||||||
|
...listQuestions[quizId][index],
|
||||||
|
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 { useParams } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@ -24,6 +24,7 @@ import {
|
|||||||
createQuestion,
|
createQuestion,
|
||||||
copyQuestion,
|
copyQuestion,
|
||||||
removeQuestion,
|
removeQuestion,
|
||||||
|
removeQuestionForce,
|
||||||
} from "@root/questions";
|
} from "@root/questions";
|
||||||
|
|
||||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
@ -157,6 +158,12 @@ export default function QuestionsPageCard({
|
|||||||
updateQuestionsList(quizId, totalIndex, { title });
|
updateQuestionsList(quizId, totalIndex, { title });
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (listQuestions[quizId][totalIndex].deleteTimeoutId) {
|
||||||
|
clearTimeout(listQuestions[quizId][totalIndex].deleteTimeoutId);
|
||||||
|
}
|
||||||
|
}, [listQuestions]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Paper
|
<Paper
|
||||||
@ -288,7 +295,25 @@ export default function QuestionsPageCard({
|
|||||||
borderRadius: "6px",
|
borderRadius: "6px",
|
||||||
padding: "2px",
|
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 color={"white"} />
|
<DeleteIcon color={"white"} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useState } from "react";
|
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
||||||
|
@ -29,7 +29,8 @@ export interface Question {
|
|||||||
description: string;
|
description: string;
|
||||||
type: string;
|
type: string;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
deleted: true;
|
deleted: boolean;
|
||||||
|
deleteTimeoutId: number;
|
||||||
page: number;
|
page: number;
|
||||||
content: {
|
content: {
|
||||||
variants: Variants[];
|
variants: Variants[];
|
||||||
@ -84,7 +85,8 @@ export const DEFAULT_QUESTION: Omit<Question, "id"> = {
|
|||||||
description: "",
|
description: "",
|
||||||
type: "",
|
type: "",
|
||||||
required: true,
|
required: true,
|
||||||
deleted: true,
|
deleted: false,
|
||||||
|
deleteTimeoutId: 0,
|
||||||
page: 0,
|
page: 0,
|
||||||
content: {
|
content: {
|
||||||
largeCheck: false,
|
largeCheck: false,
|
||||||
@ -147,15 +149,35 @@ export const DEFAULT_QUESTION: Omit<Question, "id"> = {
|
|||||||
expanded: false,
|
expanded: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let isFirstPartialize = true;
|
||||||
|
|
||||||
export const questionStore = create<QuestionStore>()(
|
export const questionStore = create<QuestionStore>()(
|
||||||
persist<QuestionStore>(
|
persist<QuestionStore>(
|
||||||
() => ({
|
() => ({
|
||||||
listQuestions: {},
|
listQuestions: {},
|
||||||
openedModalSettings: "",
|
openedModalSettings: "",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "question",
|
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;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -222,11 +244,18 @@ export const copyQuestion = (quizId: number, copiedQuestionIndex: number) => {
|
|||||||
questionStore.setState({ listQuestions });
|
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) => {
|
export const removeQuestion = (quizId: number, index: number) => {
|
||||||
const questionListClone = { ...questionStore.getState()["listQuestions"] };
|
const questionListClone = { ...questionStore.getState()["listQuestions"] };
|
||||||
|
questionListClone[quizId][index].deleted = true;
|
||||||
questionListClone[quizId].splice(index, 1);
|
|
||||||
|
|
||||||
questionStore.setState({ listQuestions: questionListClone });
|
questionStore.setState({ listQuestions: questionListClone });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user