mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
dragable question in Editor
This commit is contained in:
parent
5ff5b2018f
commit
11b719e2ca
4 changed files with 284 additions and 52 deletions
113
client/package-lock.json
generated
113
client/package-lock.json
generated
|
|
@ -28,6 +28,7 @@
|
||||||
"marked": "^14.1.2",
|
"marked": "^14.1.2",
|
||||||
"nanoid": "^5.1.2",
|
"nanoid": "^5.1.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-modal": "^3.16.3",
|
"react-modal": "^3.16.3",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.26.2",
|
||||||
|
|
@ -48,6 +49,7 @@
|
||||||
"@types/jest": "^29.5.13",
|
"@types/jest": "^29.5.13",
|
||||||
"@types/node": "^22.13.5",
|
"@types/node": "^22.13.5",
|
||||||
"@types/react": "^18.2.15",
|
"@types/react": "^18.2.15",
|
||||||
|
"@types/react-beautiful-dnd": "^13.1.8",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.7",
|
||||||
"@types/react-latex": "^2.0.3",
|
"@types/react-latex": "^2.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.25.0",
|
"@typescript-eslint/eslint-plugin": "^8.25.0",
|
||||||
|
|
@ -4555,6 +4557,15 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/hoist-non-react-statics": {
|
||||||
|
"version": "3.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
|
||||||
|
"integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/istanbul-lib-coverage": {
|
"node_modules/@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||||
|
|
@ -4695,6 +4706,15 @@
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-beautiful-dnd": {
|
||||||
|
"version": "13.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz",
|
||||||
|
"integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-dom": {
|
"node_modules/@types/react-dom": {
|
||||||
"version": "18.3.5",
|
"version": "18.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz",
|
||||||
|
|
@ -4715,6 +4735,17 @@
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-redux": {
|
||||||
|
"version": "7.1.34",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz",
|
||||||
|
"integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hoist-non-react-statics": "^3.3.0",
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
|
"redux": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-transition-group": {
|
"node_modules/@types/react-transition-group": {
|
||||||
"version": "4.4.12",
|
"version": "4.4.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
|
||||||
|
|
@ -5978,6 +6009,14 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/css-box-model": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tiny-invariant": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/css.escape": {
|
"node_modules/css.escape": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
|
||||||
|
|
@ -9945,6 +9984,11 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/memoize-one": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||||
|
},
|
||||||
"node_modules/merge-stream": {
|
"node_modules/merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
|
|
@ -11188,6 +11232,11 @@
|
||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/raf-schd": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ=="
|
||||||
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||||
|
|
@ -11200,6 +11249,25 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-beautiful-dnd": {
|
||||||
|
"version": "13.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz",
|
||||||
|
"integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==",
|
||||||
|
"deprecated": "react-beautiful-dnd is now deprecated. Context and options: https://github.com/atlassian/react-beautiful-dnd/issues/2672",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.9.2",
|
||||||
|
"css-box-model": "^1.2.0",
|
||||||
|
"memoize-one": "^5.1.1",
|
||||||
|
"raf-schd": "^4.0.2",
|
||||||
|
"react-redux": "^7.2.0",
|
||||||
|
"redux": "^4.0.4",
|
||||||
|
"use-memo-one": "^1.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.5 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
|
|
@ -11241,6 +11309,35 @@
|
||||||
"react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19"
|
"react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-redux": {
|
||||||
|
"version": "7.2.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz",
|
||||||
|
"integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.15.4",
|
||||||
|
"@types/react-redux": "^7.1.20",
|
||||||
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-is": "^17.0.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.3 || ^17 || ^18"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-redux/node_modules/react-is": {
|
||||||
|
"version": "17.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||||
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.30.0",
|
"version": "6.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz",
|
||||||
|
|
@ -11316,6 +11413,14 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/redux": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.9.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/reflect.getprototypeof": {
|
"node_modules/reflect.getprototypeof": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
||||||
|
|
@ -12841,6 +12946,14 @@
|
||||||
"requires-port": "^1.0.0"
|
"requires-port": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/use-memo-one": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/uuid": {
|
"node_modules/uuid": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
"marked": "^14.1.2",
|
"marked": "^14.1.2",
|
||||||
"nanoid": "^5.1.2",
|
"nanoid": "^5.1.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-modal": "^3.16.3",
|
"react-modal": "^3.16.3",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.26.2",
|
||||||
|
|
@ -52,6 +53,7 @@
|
||||||
"@types/jest": "^29.5.13",
|
"@types/jest": "^29.5.13",
|
||||||
"@types/node": "^22.13.5",
|
"@types/node": "^22.13.5",
|
||||||
"@types/react": "^18.2.15",
|
"@types/react": "^18.2.15",
|
||||||
|
"@types/react-beautiful-dnd": "^13.1.8",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.7",
|
||||||
"@types/react-latex": "^2.0.3",
|
"@types/react-latex": "^2.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.25.0",
|
"@typescript-eslint/eslint-plugin": "^8.25.0",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { TextField, Typography, IconButton, Box } from '@mui/material';
|
import { TextField, Typography, IconButton, Box, Collapse, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Button } from '@mui/material';
|
||||||
import DeleteIcon from '@mui/icons-material/Delete';
|
import DeleteIcon from '@mui/icons-material/Delete';
|
||||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||||
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||||
|
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
|
||||||
|
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
interface EditorProps {
|
interface EditorProps {
|
||||||
label: string;
|
label: string;
|
||||||
|
|
@ -11,6 +14,10 @@ interface EditorProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Editor: React.FC<EditorProps> = ({ label, values, onValuesChange, onFocusQuestion }) => {
|
const Editor: React.FC<EditorProps> = ({ label, values, onValuesChange, onFocusQuestion }) => {
|
||||||
|
const [collapsed, setCollapsed] = useState<boolean[]>(Array(values.length).fill(false));
|
||||||
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
|
const [deleteIndex, setDeleteIndex] = useState<number | null>(null);
|
||||||
|
|
||||||
const handleChange = (index: number) => (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleChange = (index: number) => (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const newValues = [...values];
|
const newValues = [...values];
|
||||||
newValues[index] = event.target.value;
|
newValues[index] = event.target.value;
|
||||||
|
|
@ -18,16 +25,67 @@ const Editor: React.FC<EditorProps> = ({ label, values, onValuesChange, onFocusQ
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteQuestion = (index: number) => () => {
|
const handleDeleteQuestion = (index: number) => () => {
|
||||||
const newValues = values.filter((_, i) => i !== index); // Remove the question at the specified index
|
if (values[index].trim() === '') {
|
||||||
|
const newValues = values.filter((_, i) => i !== index);
|
||||||
onValuesChange(newValues);
|
onValuesChange(newValues);
|
||||||
|
setCollapsed((prev) => prev.filter((_, i) => i !== index));
|
||||||
|
} else {
|
||||||
|
setDeleteIndex(index);
|
||||||
|
setDialogOpen(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfirmDelete = () => {
|
||||||
|
if (deleteIndex !== null) {
|
||||||
|
const newValues = values.filter((_, i) => i !== deleteIndex);
|
||||||
|
onValuesChange(newValues);
|
||||||
|
setCollapsed((prev) => prev.filter((_, i) => i !== deleteIndex));
|
||||||
|
}
|
||||||
|
setDialogOpen(false);
|
||||||
|
setDeleteIndex(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancelDelete = () => {
|
||||||
|
setDialogOpen(false);
|
||||||
|
setDeleteIndex(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFocusQuestion = (index: number) => () => {
|
const handleFocusQuestion = (index: number) => () => {
|
||||||
if (onFocusQuestion) {
|
if (onFocusQuestion) {
|
||||||
onFocusQuestion(index); // Call the focus function if provided
|
onFocusQuestion(index);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleToggleCollapse = (index: number) => () => {
|
||||||
|
setCollapsed((prev) => {
|
||||||
|
const newCollapsed = [...prev];
|
||||||
|
newCollapsed[index] = !newCollapsed[index];
|
||||||
|
return newCollapsed;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDragEnd = (result: any) => {
|
||||||
|
if (!result.destination) return;
|
||||||
|
|
||||||
|
const newValues = [...values];
|
||||||
|
const [reorderedItem] = newValues.splice(result.source.index, 1);
|
||||||
|
newValues.splice(result.destination.index, 0, reorderedItem);
|
||||||
|
onValuesChange(newValues);
|
||||||
|
|
||||||
|
const newCollapsed = [...collapsed];
|
||||||
|
const [reorderedCollapsed] = newCollapsed.splice(result.source.index, 1);
|
||||||
|
newCollapsed.splice(result.destination.index, 0, reorderedCollapsed);
|
||||||
|
setCollapsed(newCollapsed);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (collapsed.length !== values.length) {
|
||||||
|
setCollapsed((prev) => {
|
||||||
|
const newCollapsed = [...prev];
|
||||||
|
while (newCollapsed.length < values.length) newCollapsed.push(false);
|
||||||
|
while (newCollapsed.length > values.length) newCollapsed.pop();
|
||||||
|
return newCollapsed;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -35,26 +93,53 @@ const Editor: React.FC<EditorProps> = ({ label, values, onValuesChange, onFocusQ
|
||||||
{label}
|
{label}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
|
<Droppable droppableId="questions">
|
||||||
|
{(provided) => (
|
||||||
|
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||||
{values.map((value, index) => (
|
{values.map((value, index) => (
|
||||||
<Box key={index} style={{ marginBottom: '24px' }}>
|
<Draggable key={index} draggableId={`question-${index}`} index={index}>
|
||||||
|
{(provided) => (
|
||||||
|
<Box
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
sx={{
|
||||||
|
marginBottom: '24px',
|
||||||
|
boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)',
|
||||||
|
border: '1px solid rgba(0, 0, 0, 0.1)',
|
||||||
|
padding: '16px',
|
||||||
|
borderRadius: '4px',
|
||||||
|
...provided.draggableProps.style,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
<Typography variant="subtitle1" fontWeight="bold" style={{ marginBottom: '8px' }}>
|
<Typography variant="subtitle1" fontWeight="bold" style={{ marginBottom: '8px' }}>
|
||||||
Question {index + 1}
|
Question {index + 1}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box>
|
<Box>
|
||||||
{/* Focus (Eye) Button */}
|
<IconButton
|
||||||
|
onClick={handleToggleCollapse(index)}
|
||||||
|
aria-label="toggle collapse"
|
||||||
|
sx={{
|
||||||
|
color: 'gray',
|
||||||
|
'&:hover': { color: 'blue' },
|
||||||
|
mr: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{collapsed[index] ? <ExpandMoreIcon /> : <ExpandLessIcon />}
|
||||||
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={handleFocusQuestion(index)}
|
onClick={handleFocusQuestion(index)}
|
||||||
aria-label="focus question"
|
aria-label="focus question"
|
||||||
sx={{
|
sx={{
|
||||||
color: 'gray',
|
color: 'gray',
|
||||||
'&:hover': { color: 'blue' },
|
'&:hover': { color: 'blue' },
|
||||||
marginRight: '8px', // Space between eye and delete
|
mr: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<VisibilityIcon />
|
<VisibilityIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
{/* Delete Button */}
|
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={handleDeleteQuestion(index)}
|
onClick={handleDeleteQuestion(index)}
|
||||||
aria-label="delete"
|
aria-label="delete"
|
||||||
|
|
@ -67,6 +152,7 @@ const Editor: React.FC<EditorProps> = ({ label, values, onValuesChange, onFocusQ
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Collapse in={!collapsed[index]}>
|
||||||
<TextField
|
<TextField
|
||||||
value={value}
|
value={value}
|
||||||
onChange={handleChange(index)}
|
onChange={handleChange(index)}
|
||||||
|
|
@ -77,8 +163,39 @@ const Editor: React.FC<EditorProps> = ({ label, values, onValuesChange, onFocusQ
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
style={{ overflow: 'auto' }}
|
style={{ overflow: 'auto' }}
|
||||||
/>
|
/>
|
||||||
|
</Collapse>
|
||||||
</Box>
|
</Box>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
))}
|
))}
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</DragDropContext>
|
||||||
|
|
||||||
|
{/* Confirmation Dialog */}
|
||||||
|
<Dialog
|
||||||
|
open={dialogOpen}
|
||||||
|
onClose={handleCancelDelete}
|
||||||
|
aria-labelledby="delete-confirmation-title"
|
||||||
|
aria-describedby="delete-confirmation-description"
|
||||||
|
>
|
||||||
|
<DialogTitle id="delete-confirmation-title" sx={{ textAlign: 'center'}}>Suppression</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="delete-confirmation-description">
|
||||||
|
Confirmez vous la suppression de Question {deleteIndex !== null ? deleteIndex + 1 : ''} ?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions sx={{ justifyContent: 'center', pb: 2 }}>
|
||||||
|
<Button onClick={handleCancelDelete} color="primary" sx={{ mx: 1 }}>
|
||||||
|
Annuler
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleConfirmDelete} color="error" sx={{ mx: 1 }} autoFocus>
|
||||||
|
Supprimer
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,7 @@ const QuizForm: React.FC = () => {
|
||||||
|
|
||||||
<div className='edit'>
|
<div className='edit'>
|
||||||
<Editor
|
<Editor
|
||||||
label="Contenu GIFT de chaque question:"
|
label=""
|
||||||
values={values}
|
values={values}
|
||||||
onValuesChange={handleUpdatePreview}
|
onValuesChange={handleUpdatePreview}
|
||||||
onFocusQuestion={handleFocusQuestion} />
|
onFocusQuestion={handleFocusQuestion} />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue