diff --git a/src/AddQuestion/AddQuestion.jsx b/src/AddQuestion/AddQuestion.jsx
index 4658f5e..aec555b 100644
--- a/src/AddQuestion/AddQuestion.jsx
+++ b/src/AddQuestion/AddQuestion.jsx
@@ -1,13 +1,14 @@
import { useDropzone } from 'react-dropzone';
-import { FaTimes } from 'react-icons/fa';
+import { FaArrowLeft, FaTimes } from 'react-icons/fa';
import { IoCloudUploadOutline } from 'react-icons/io5';
import './AddQuestion.css';
import { useEffect, useState } from 'react';
import axios from 'axios';
import AlertModal from '../AlertModel/AlertModel';
import { useNavigate } from 'react-router-dom';
+import PropTypes from 'prop-types';
-const AddQuestion = () => {
+const AddQuestion = ({ questionData, onBack }) => {
const navigate = useNavigate();
const [isFlex, setIsFlex] = useState(true);
const [tags, setTags] = useState([]);
@@ -31,12 +32,30 @@ const AddQuestion = () => {
const [divTag, setDivTag] = useState([]);
const [images, setImages] = useState([]);
+ useEffect(() => {
+ if (questionData) {
+ // Populate form with existing data
+ setHeading(questionData.heading || '');
+ setDescription(questionData.description || '');
+ setDifficultyLevel(questionData.difficultyLevel || '');
+ setMarks(questionData.marks || '');
+ setOption(questionData.option || '');
+ setMcqOptions(questionData.mcqOptions || ['']);
+ setMcqAnswer(questionData.mcqAnswer || '');
+ setHours(questionData.expectedTime?.hours || '');
+ setMinutes(questionData.expectedTime?.minutes || '');
+ setTags(questionData.tags || []);
+ setDivTag(questionData.tags || []);
+ }
+ }, [questionData]);
+
useEffect(() => {
document.title = 'Add Questions | EduWiz';
}, []);
useEffect(() => {
setExpectedTime({ hours, minutes });
+ // console.log(expectedTime);
}, [hours, minutes]);
const onDrop = (acceptedFiles) => {
@@ -130,8 +149,15 @@ const AddQuestion = () => {
}
setLoading(true);
const teacherId = localStorage.getItem('teacherId');
+
try {
- const response = await axios.post('http://localhost:5000/question/addQuestion', {
+ const endpoint = questionData
+ ? `http://localhost:5000/question/updateQuestion/${questionData._id}`
+ : 'http://localhost:5000/question/addQuestion';
+
+ const method = questionData ? 'put' : 'post';
+
+ const response = await axios[method](endpoint, {
teacherId,
heading,
description,
@@ -143,10 +169,11 @@ const AddQuestion = () => {
expectedTime,
divTag,
});
+
if (response.status === 200) {
setModalIsError(false);
setModalIsOpen(true);
- setModalMessage(response.data.message);
+ setModalMessage(questionData ? 'Question updated successfully!' : 'Question added successfully!');
}
} catch (error) {
setModalIsError(true);
@@ -178,9 +205,15 @@ const AddQuestion = () => {
return (
+
- Question Upload
+ {questionData ? 'Edit Question' : 'Add Question'}
@@ -206,6 +238,7 @@ const AddQuestion = () => {
@@ -456,7 +494,19 @@ const AddQuestion = () => {
-
+
@@ -466,6 +516,7 @@ const AddQuestion = () => {
isOpen={modalIsOpen}
onClose={() => {
setModalIsOpen(false);
+ if (!modalIsError) onBack();
navigate('/questions-upload');
}}
isError={modalIsError}
@@ -475,4 +526,27 @@ const AddQuestion = () => {
);
};
+AddQuestion.propTypes = {
+ questionData: PropTypes.shape({
+ _id: PropTypes.string,
+ heading: PropTypes.string,
+ description: PropTypes.string,
+ difficultyLevel: PropTypes.string,
+ marks: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ option: PropTypes.string,
+ mcqOptions: PropTypes.arrayOf(PropTypes.string),
+ mcqAnswer: PropTypes.string,
+ expectedTime: PropTypes.shape({
+ hours: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ minutes: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ }),
+ tags: PropTypes.arrayOf(PropTypes.string),
+ }),
+ onBack: PropTypes.func.isRequired,
+};
+
+AddQuestion.defaultProps = {
+ questionData: null,
+};
+
export default AddQuestion;
diff --git a/src/App.jsx b/src/App.jsx
index 9e28fec..85c49fe 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -16,7 +16,7 @@ import UploadOmr from './UploadOMR/UploadOmr.jsx';
import SubmitPage from './Submit/SubmitPage.jsx';
import IHaveAPasscode from './IHaveAPasscode/IHaveAPasscode.jsx';
import QuestionsUpload from './QuestionsUpload/QuestionsUpload.jsx';
-import AddQuestion from './AddQuestion/AddQuestion.jsx';
+// import AddQuestion from './AddQuestion/AddQuestion.jsx';
const App = () => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
@@ -76,7 +76,7 @@ const App = () => {
} />
} />
} />
- } />
+ {/* } /> */}
} />
)}
diff --git a/src/QuestionsUpload/QuestionsUpload.css b/src/QuestionsUpload/QuestionsUpload.css
index 8ee897d..048adfe 100644
--- a/src/QuestionsUpload/QuestionsUpload.css
+++ b/src/QuestionsUpload/QuestionsUpload.css
@@ -82,9 +82,17 @@
.dark .questionupload-hr {
color: #ffffff4b;
}
+.question-upload-main-div {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-right: 20px;
+}
+.question_uploadfirst_hr {
+ transform: translateX(-10px);
+}
.question-upload-marks {
- position: absolute;
- top: 15px;
+ top: 60px;
right: 20px;
background-color: rgba(0, 255, 255, 0.253);
color: #1e3a8a;
diff --git a/src/QuestionsUpload/QuestionsUpload.jsx b/src/QuestionsUpload/QuestionsUpload.jsx
index b3ceb94..d370948 100644
--- a/src/QuestionsUpload/QuestionsUpload.jsx
+++ b/src/QuestionsUpload/QuestionsUpload.jsx
@@ -1,16 +1,50 @@
-import { useNavigate } from 'react-router-dom';
+// import { useNavigate } from 'react-router-dom';
import './QuestionsUpload.css';
import { useContext, useEffect, useState } from 'react';
-import { FaPlus } from 'react-icons/fa';
+import { FaEdit, FaPlus, FaTrash } from 'react-icons/fa';
import axios from 'axios';
import { SiLevelsdotfyi } from 'react-icons/si';
import { FaRegClock, FaTag } from 'react-icons/fa6';
import { ThemeContext } from '../contexts/ThemeContext';
import { GoDotFill } from 'react-icons/go';
import questionImage from '../assets/user-photo-default.jpg';
+import AddQuestion from '../AddQuestion/AddQuestion';
+import PropTypes from 'prop-types';
+import SuccessModal from '../AlertModel/AlertModel';
+
+const Question = PropTypes.shape({
+ _id: PropTypes.string.isRequired,
+ heading: PropTypes.string.isRequired,
+ description: PropTypes.string.isRequired,
+ difficultyLevel: PropTypes.string.isRequired,
+ marks: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
+ option: PropTypes.string.isRequired,
+ mcqOptions: PropTypes.arrayOf(PropTypes.string),
+ mcqAnswer: PropTypes.string,
+ expectedTime: PropTypes.shape({
+ hours: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ minutes: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ }).isRequired,
+ tags: PropTypes.arrayOf(PropTypes.string),
+});
const QuestionsUpload = () => {
const { theme } = useContext(ThemeContext);
+ const [questions, setQuestions] = useState([]);
+ const [isEditing, setIsEditing] = useState(false);
+ const [editQuestionData, setEditQuestionData] = useState(null);
+ const [isDeleting, setIsDeleting] = useState(false);
+
+ //for modal
+ const [confirmModal, setConfirmModal] = useState({
+ isOpen: false,
+ questionIdToDelete: null,
+ });
+ const [resultModal, setResultModal] = useState({
+ isOpen: false,
+ isError: false,
+ message: '',
+ });
const lightColors = {
'#1e3a8a': 'rgba(0, 255, 255, 0.253)',
@@ -25,8 +59,76 @@ const QuestionsUpload = () => {
const colorKeysLight = Object.keys(lightColors);
const colorKeysDark = Object.keys(darkColors);
- const navigate = useNavigate();
- const [questions, setQuestions] = useState([]);
+ // const navigate = useNavigate();
+
+ const handleEdit = (question) => {
+ setEditQuestionData(question);
+ setIsEditing(true);
+ };
+
+ const handleAddNewQuestion = () => {
+ setEditQuestionData(null);
+ setIsEditing(true);
+ };
+
+ const handleBack = () => {
+ setIsEditing(false);
+ setEditQuestionData(null);
+ // Refresh questions list after edit
+ axios
+ .post('http://localhost:5000/question/getQuestionDetailsByTeacherId', {
+ teacherId: localStorage.getItem('teacherId'),
+ })
+ .then((response) => {
+ setQuestions(response.data.questions);
+ })
+ .catch((err) => {
+ console.error(err?.response?.data.error || 'Server Error');
+ });
+ };
+
+ const initiateDelete = (questionId) => {
+ setConfirmModal({
+ isOpen: true,
+ questionIdToDelete: questionId,
+ });
+ };
+
+ const handleDelete = async () => {
+ const questionId = confirmModal.questionIdToDelete;
+
+ try {
+ setIsDeleting(true);
+ const response = await axios.delete(`http://localhost:5000/question/deleteQuestion/${questionId}`, {
+ data: {
+ teacherId: localStorage.getItem('teacherId'),
+ },
+ });
+
+ if (response.status === 200) {
+ // Update the local state to remove the deleted question
+ setQuestions((prevQuestions) => prevQuestions.filter((q) => q._id !== questionId));
+
+ // Show success modal
+ setResultModal({
+ isOpen: true,
+ isError: false,
+ message: 'Question deleted successfully',
+ });
+ }
+ } catch (error) {
+ console.error('Error deleting question:', error);
+ // Show error modal
+ setResultModal({
+ isOpen: true,
+ isError: true,
+ message: error.response?.data?.message || 'Failed to delete question',
+ });
+ } finally {
+ setIsDeleting(false);
+ setConfirmModal({ isOpen: false, questionIdToDelete: null });
+ }
+ };
useEffect(() => {
axios
@@ -42,36 +144,61 @@ const QuestionsUpload = () => {
document.title = 'Upload Questions | EduWiz';
}, []);
+ if (isEditing) {
+ return ;
+ }
+
return (
<>
Questions
{
- navigate('/add-question');
- }}
+ onClick={handleAddNewQuestion}
+ // onClick={() => {
+ // navigate('/add-question');
+ // }}
>
Add Question
-
+
{questions.map((question, key) => (
-
-
-
-
{question.difficultyLevel}
+
+
+
+
-
-
+
- Expected Time: {question.expectedTime.hours} Hours
- {Number(question.expectedTime.minutes)} Minutes
+
+
+
{question.difficultyLevel}
+
+
+
+
+ Expected Time: {question.expectedTime.hours} Hours
+ {Number(question.expectedTime.minutes)} Minutes
+
+
+
Marks: {question.marks}
-
Marks: {question.marks}
-
+
+
{question.heading}
@@ -134,8 +261,33 @@ const QuestionsUpload = () => {
))}
+ {/* Confirmation Modal */}
+
setConfirmModal({ isOpen: false, questionIdToDelete: null })}
+ message="Are you sure you want to delete this question?"
+ isError={false}
+ isConfirm={true}
+ onConfirm={handleDelete}
+ />
+
+ {/* Result Modal */}
+ setResultModal({ isOpen: false, isError: false, message: '' })}
+ message={resultModal.message}
+ isError={resultModal.isError}
+ />
>
);
};
+QuestionsUpload.propTypes = {
+ questions: PropTypes.arrayOf(Question),
+};
+
+QuestionsUpload.defaultProps = {
+ questions: [],
+};
+
export default QuestionsUpload;
diff --git a/src/Sidebar/Sidebar.jsx b/src/Sidebar/Sidebar.jsx
index c86c91c..2444b2f 100644
--- a/src/Sidebar/Sidebar.jsx
+++ b/src/Sidebar/Sidebar.jsx
@@ -74,7 +74,7 @@ const Sidebar = () => {
{'EduWiz'}
diff --git a/src/Test Schedule Card/TestScheduleCard.jsx b/src/Test Schedule Card/TestScheduleCard.jsx
index b995c68..c3fa190 100644
--- a/src/Test Schedule Card/TestScheduleCard.jsx
+++ b/src/Test Schedule Card/TestScheduleCard.jsx
@@ -4,7 +4,7 @@ import { FaEdit, FaCopy, FaTrash } from 'react-icons/fa';
import { useState } from 'react';
const TestScheduleCard = (props) => {
- console.log(props);
+ // console.log(props);
const [hover, setHover] = useState(false);
// const formattedDate = new Date(props.test.scheduleDate).toLocaleString();