fix: Questions drag&drop

This commit is contained in:
IlyaDoronin 2023-08-08 14:01:37 +03:00
parent 2bb8eb20c3
commit 64ec511f21
5 changed files with 144 additions and 102 deletions

@ -1,23 +1,30 @@
import { Draggable } from "react-beautiful-dnd"; import { Draggable } from "react-beautiful-dnd";
import { ListItem } from "@mui/material"; import { ListItem } from "@mui/material";
import type { ReactNode } from "react"; import QuestionsPageCard from "../QuestionPageCard";
type DraggableListItemProps = { type DraggableListItemProps = {
item: ReactNode;
index: number; index: number;
onDelete: () => void;
}; };
export const DraggableListItem = ({ item, index }: DraggableListItemProps) => ( export const DraggableListItem = ({
index,
onDelete,
}: DraggableListItemProps) => (
<Draggable draggableId={String(index)} index={index}> <Draggable draggableId={String(index)} index={index}>
{(provided, snapshot) => ( {(provided, snapshot) => (
<ListItem <ListItem
ref={provided.innerRef} ref={provided.innerRef}
{...provided.draggableProps} {...provided.draggableProps}
{...provided.dragHandleProps}
sx={{ padding: 0 }} sx={{ padding: 0 }}
> >
{item} <QuestionsPageCard
key={index}
totalIndex={index}
DeleteClick={onDelete}
draggableProps={provided.dragHandleProps}
/>
</ListItem> </ListItem>
)} )}
</Draggable> </Draggable>

@ -7,11 +7,15 @@ import { DraggableListItem } from "./DraggableListItem";
import { reorder } from "./helper"; import { reorder } from "./helper";
import type { ReactNode } from "react";
import type { DropResult } from "react-beautiful-dnd"; import type { DropResult } from "react-beautiful-dnd";
import type { Quizes } from "../../../stores/quizes";
export type ExtendedQuizes = Quizes & {
onDelete: () => void;
};
type DraggableListProps = { type DraggableListProps = {
items: ReactNode[]; items: ExtendedQuizes[];
}; };
export const DraggableList = ({ items }: DraggableListProps) => { export const DraggableList = ({ items }: DraggableListProps) => {
@ -34,8 +38,12 @@ export const DraggableList = ({ items }: DraggableListProps) => {
<StrictModeDroppable droppableId="droppable-list"> <StrictModeDroppable droppableId="droppable-list">
{(provided) => ( {(provided) => (
<Box ref={provided.innerRef} {...provided.droppableProps}> <Box ref={provided.innerRef} {...provided.droppableProps}>
{listItems.map((item, index) => ( {listItems.map(({ onDelete }, index) => (
<DraggableListItem key={index} item={item} index={index} /> <DraggableListItem
key={index}
index={index}
onDelete={onDelete}
/>
))} ))}
{provided.placeholder} {provided.placeholder}
</Box> </Box>

@ -1,7 +1,14 @@
import {Box, Checkbox, FormControlLabel, IconButton, Paper, useTheme} from "@mui/material"; import {
Box,
Checkbox,
FormControlLabel,
IconButton,
Paper,
useTheme,
} from "@mui/material";
import CustomTextField from "@ui_kit/CustomTextField"; import CustomTextField from "@ui_kit/CustomTextField";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import ExpandLessIcon from '@mui/icons-material/ExpandLess'; import ExpandLessIcon from "@mui/icons-material/ExpandLess";
import OneIcon from "@icons/questionsPage/OneIcon"; import OneIcon from "@icons/questionsPage/OneIcon";
import PointsIcon from "@icons/questionsPage/PointsIcon"; import PointsIcon from "@icons/questionsPage/PointsIcon";
import TypeQuestions from "./TypeQuestions"; import TypeQuestions from "./TypeQuestions";
@ -14,60 +21,68 @@ import CopyIcon from "@icons/questionsPage/CopyIcon";
import CrossedEyeIcon from "@icons/CrossedEyeIcon"; import CrossedEyeIcon from "@icons/CrossedEyeIcon";
import HideIcon from "@icons/questionsPage/hideIcon"; import HideIcon from "@icons/questionsPage/hideIcon";
import type { DraggableProvidedDragHandleProps } from "react-beautiful-dnd";
interface Props { interface Props {
DeleteClick: () => void; DeleteClick: () => void;
totalIndex: number totalIndex: number;
draggableProps: DraggableProvidedDragHandleProps | null | undefined;
} }
export default function QuestionsPageCard({totalIndex, DeleteClick}: Props) { export default function QuestionsPageCard({
totalIndex,
DeleteClick,
draggableProps,
}: Props) {
function onDragStart(event: any) { function onDragStart(event: any) {
event event.dataTransfer.setData("text", event.target.id);
.dataTransfer
.setData('text', event.target.id);
} }
const theme = useTheme(); const theme = useTheme();
const params = Number(useParams().quizId); const params = Number(useParams().quizId);
const {listQuestions, updateQuestionsList, createQuestion, removeQuestion} = questionStore() const { listQuestions, updateQuestionsList, createQuestion, removeQuestion } =
questionStore();
const [isExpanded, setIsExpanded] = useState<boolean>(false); const [isExpanded, setIsExpanded] = useState<boolean>(false);
const switchState = listQuestions[params][totalIndex].type const switchState = listQuestions[params][totalIndex].type;
return ( return (
<Paper <Paper
draggable="true"
id={String(totalIndex)} id={String(totalIndex)}
sx={{ sx={{
maxWidth: "796px", maxWidth: "796px",
width: "100%", width: "100%",
borderRadius: "12px", borderRadius: "12px",
marginBottom: "20px", marginBottom: "20px",
backgroundColor: isExpanded ? "white" : "#333647" backgroundColor: isExpanded ? "white" : "#333647",
}} }}
onDragStart={onDragStart} onDragStart={onDragStart}
> >
<Box <Box
sx={{ width: "100%", maxWidth: "760px", display: "flex", alignItems: "center", gap: "10px", padding: "20px" }} sx={{
width: "100%",
maxWidth: "760px",
display: "flex",
alignItems: "center",
gap: "10px",
padding: "20px",
}}
> >
<CustomTextField placeholder="Заголовок вопроса" text={""} <CustomTextField
onChange={e => {updateQuestionsList(params, totalIndex, {title: e.target.value}) placeholder="Заголовок вопроса"
console.log(listQuestions[params][totalIndex].title) text={""}
} onChange={(e) => {
}/> updateQuestionsList(params, totalIndex, { title: e.target.value });
console.log(listQuestions[params][totalIndex].title);
}}
/>
<IconButton onClick={() => setIsExpanded((prev) => !prev)}> <IconButton onClick={() => setIsExpanded((prev) => !prev)}>
{" "} {" "}
{isExpanded ? {isExpanded ? <ExpandMoreIcon /> : <ExpandLessIcon fill="#7E2AEA" />}
<ExpandMoreIcon />
:<ExpandLessIcon fill="#7E2AEA"/>
}
</IconButton> </IconButton>
<Box sx={{ display: "flex" }}> <Box sx={{ display: "flex" }}>
<FormControlLabel <FormControlLabel
control={ control={
<Checkbox <Checkbox icon={<HideIcon />} checkedIcon={<CrossedEyeIcon />} />
icon={<HideIcon/>} }
checkedIcon={<CrossedEyeIcon />}
/>}
label={""} label={""}
sx={{ sx={{
color: theme.palette.grey2.main, color: theme.palette.grey2.main,
@ -75,26 +90,38 @@ export default function QuestionsPageCard({totalIndex, DeleteClick}: Props) {
mr: 0, mr: 0,
userSelect: "none", userSelect: "none",
}} }}
/> />
<IconButton><CopyIcon/></IconButton> <IconButton>
<IconButton sx={{ borderRadius: "6px", padding: "2px" }} onClick={DeleteClick}> <CopyIcon />
</IconButton>
<IconButton
sx={{ borderRadius: "6px", padding: "2px" }}
onClick={DeleteClick}
>
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>
</Box> </Box>
<OneIcon /> <OneIcon />
<Box {...draggableProps}>
<PointsIcon /> <PointsIcon />
</Box>
</Box> </Box>
{isExpanded && ( {isExpanded && (
<Box sx={{display: "flex", flexDirection: "column", padding: 0, borderRadius: "12px"}}> <Box
{switchState.length === 0 ? sx={{
display: "flex",
flexDirection: "column",
padding: 0,
borderRadius: "12px",
}}
>
{switchState.length === 0 ? (
<TypeQuestions totalIndex={totalIndex} /> <TypeQuestions totalIndex={totalIndex} />
: ) : (
<SwitchQuestionsPage totalIndex={totalIndex}/>} <SwitchQuestionsPage totalIndex={totalIndex} />
</Box>) )}
} </Box>
)}
</Paper> </Paper>
);
)
} }

@ -12,12 +12,13 @@ import AddPlus from "../../assets/icons/questionsPage/addPlus";
import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft"; import ArrowLeft from "../../assets/icons/questionsPage/arrowLeft";
import { quizStore } from "@root/quizes"; import { quizStore } from "@root/quizes";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import QuestionsPageCard from "./QuestionPageCard";
import { questionStore } from "@root/questions"; import { questionStore } from "@root/questions";
// import { DraggableList } from "./DraggableList"; // import { DraggableList } from "./DraggableList";
import QuizCard from "../createQuize/QuizCard"; import QuizCard from "../createQuize/QuizCard";
import { DraggableList } from "./DraggableList"; import { DraggableList } from "./DraggableList";
import type { ExtendedQuizes } from "./DraggableList";
export default function QuestionsPage() { export default function QuestionsPage() {
const { listQuizes, updateQuizesList } = quizStore(); const { listQuizes, updateQuizesList } = quizStore();
const params = Number(useParams().quizId); const params = Number(useParams().quizId);
@ -59,13 +60,12 @@ export default function QuestionsPage() {
</Link> </Link>
</Box> </Box>
<DraggableList <DraggableList
items={Object.values(listQuestions[params]).map((_, index) => ( items={Object.values(listQuestions[params] as ExtendedQuizes[]).map(
<QuestionsPageCard (item, index) => ({
key={index} ...item,
totalIndex={index} onDelete: () => removeQuestion(params, index),
DeleteClick={() => removeQuestion(params, index)} })
/> )}
))}
/> />
<Box <Box
sx={{ sx={{

@ -8,7 +8,7 @@ interface QuizStore {
createBlank: () => void; createBlank: () => void;
} }
interface Quizes { export interface Quizes {
id: number, id: number,
qid: string, qid: string,
deleted: boolean, deleted: boolean,