create exam api | 400

main
alireza khaji 2 years ago
parent a6478f5679
commit 093924033b
  1. 20
      src/redux/actions/exam.js
  2. 22
      src/redux/actions/examQuestion.js
  3. 2
      src/redux/actions/index.js
  4. 411
      src/redux/reducers/exam.js
  5. 8
      src/redux/reducers/exam2.js
  6. 30
      src/redux/reducers/examQuestion.js
  7. 2
      src/redux/reducers/index.js
  8. 160
      src/view/addExam/components/addQuestion.js
  9. 43
      src/view/addExam/components/question.js
  10. 215
      src/view/addExam/views/AddQuestionsFromBank.js
  11. 12
      src/view/addExam/views/ViewExam.js
  12. 40
      src/view/addExam/views/addQuestionnaireExam.js

@ -17,6 +17,10 @@ const exam = {
(data = {}) =>
async (dispatch) =>
await proxy.post("exam/subexamAdd", data, { dispatch }),
confirm:
(data = {}) =>
async (dispatch) =>
await proxy.put("exam/confirm", data, { dispatch }),
emptySubexamList: (data = {}) => {
return (dispatch) => {
dispatch({
@ -65,6 +69,14 @@ const exam = {
});
};
},
addExamQuestion2: (data = {}) => {
return (dispatch) => {
dispatch({
type: "ADD_EXAM_QUESTIONS2",
payload: data,
});
};
},
removeQuestionFromBank: (data = {}) => {
return (dispatch) => {
dispatch({
@ -97,6 +109,14 @@ const exam = {
});
};
},
addCustomQuestion: (data = {}) => {
return (dispatch) => {
dispatch({
type: "ADD_CUSTOM_QUESTION",
payload: data,
});
};
},
};
export default exam;

@ -0,0 +1,22 @@
import proxy from "../proxy";
const examQuestion = {
info:
(data = {}) =>
async (dispatch) =>
await proxy.get("examQuestion/info", data, { dispatch }),
list:
(data = {}) =>
async (dispatch) =>
await proxy.get("examQuestion/list", data, { dispatch }),
add:
(data = {}) =>
async (dispatch) =>
await proxy.post("examQuestion/add", data, { dispatch }),
delete:
(data = {}) =>
async (dispatch) =>
await proxy.delete("examQuestion/delete", data, { dispatch }),
};
export default examQuestion;

@ -18,6 +18,8 @@ export { default as examGroup } from "./examGroup";
export { default as lesson } from "./lesson";
export { default as question } from "./question";
export { default as category } from "./category";
export { default as examQuestion } from "./examQuestion";

@ -1,55 +1,46 @@
import { IoReturnUpBack } from "react-icons/io5"
import fizikpdf from '../../assets/fizik.pdf'
import samplePdf from '../../assets/sample.pdf'
import { IoReturnUpBack } from "react-icons/io5";
import fizikpdf from "../../assets/fizik.pdf";
import samplePdf from "../../assets/sample.pdf";
const initialState = {
grade: 8,
groupId: 0,
name: '',
name: "",
startDate: new Date(),
endDate: new Date(),
startTime: '19:0',
endTime: '',
description: '',
type: 'bank',
duration:null,
budgetFileId:null,
startTime: "19:0",
endTime: "",
description: "",
type: "bank",
duration: null,
budgetFileId: null,
questionnaires: [
{
id: 1,
name: 'عمومی',
fileUrl: fizikpdf,
courses: [
{
id: 0,
questionnaireId: 1,
name: 'دینی',
coefficient: 4,
questionStart: 1,
questionEnd: 21
},
],
answers:[
]
},
{
id: 2,
name: 'اختصاصی',
fileUrl: samplePdf,
courses: [],
answers:[
]
}
// {
// id: 1,
// name: "عمومی",
// fileUrl: fizikpdf,
// courses: [
// {
// id: 0,
// questionnaireId: 1,
// name: "دینی",
// coefficient: 4,
// questionStart: 1,
// questionEnd: 21,
// },
// ],
// answers: [],
// },
// {
// id: 2,
// name: "اختصاصی",
// fileUrl: samplePdf,
// courses: [],
// answers: [],
// },
],
answers: [
],
answers: [],
courseBank: [
// {
@ -71,143 +62,139 @@ const initialState = {
{
questionId: 1,
courseId: 2,
title: 'تترا فلورید اسید چنتا اسید داره؟',
answeredPercentage: '83%',
title: "تترا فلورید اسید چنتا اسید داره؟",
answeredPercentage: "83%",
score: 1,
options: [
{
id: 1,
title: 'تترا',
isAnswer: false
title: "تترا",
isAnswer: false,
},
{
id: 2,
title: 'سه ترا',
isAnswer: false
title: "سه ترا",
isAnswer: false,
},
{
id: 3,
title: 'هویج و گوجه فرنگی؟',
isAnswer: true
title: "هویج و گوجه فرنگی؟",
isAnswer: true,
},
{
id: 4,
title: 'فلور تا',
isAnswer: false
title: "فلور تا",
isAnswer: false,
},
]
],
},
{
questionId: 2,
courseId: 2,
title: 'asdaw dsfsdfiermc',
answeredPercentage: '83%',
title: "asdaw dsfsdfiermc",
answeredPercentage: "83%",
score: 1,
options: [
{
id: 1,
title: 'asdasd',
isAnswer: false
title: "asdasd",
isAnswer: false,
},
{
id: 2,
title: 'asdasd2',
isAnswer: false
title: "asdasd2",
isAnswer: false,
},
{
id: 3,
title: '',
isAnswer: true
title: "",
isAnswer: true,
},
{
id: 4,
title: 'asdasd4',
isAnswer: false
title: "asdasd4",
isAnswer: false,
},
]
],
},
{
questionId: 3,
courseId: 1,
title: 'برای حل مساءل مربوط به مساحت زیر نمودار باید از کدام مبحث ریاضی استفاده کرد؟',
answeredPercentage: '43%',
title:
"برای حل مساءل مربوط به مساحت زیر نمودار باید از کدام مبحث ریاضی استفاده کرد؟",
answeredPercentage: "43%",
score: 1,
options: [
{
id: 1,
title: 'لگاریتم طبیعی',
isAnswer: false
title: "لگاریتم طبیعی",
isAnswer: false,
},
{
id: 2,
title: 'حد و مشتق',
isAnswer: false
title: "حد و مشتق",
isAnswer: false,
},
{
id: 3,
title: 'قدر مطلق',
isAnswer: false
title: "قدر مطلق",
isAnswer: false,
},
{
id: 4,
title: 'نخوندم 🗿',
isAnswer: true
title: "نخوندم 🗿",
isAnswer: true,
},
]
],
},
{
questionId: 4,
courseId: 2,
title: 'asdaw dsfsdfisdfsdfsfsdfsfsdfsdfermc',
answeredPercentage: '83%',
title: "asdaw dsfsdfisdfsdfsfsdfsfsdfsdfermc",
answeredPercentage: "83%",
score: 1,
options: [
{
id: 1,
title: 'asdasd',
isAnswer: false
title: "asdasd",
isAnswer: false,
},
{
id: 2,
title: 'asdasd2',
isAnswer: false
title: "asdasd2",
isAnswer: false,
},
{
id: 3,
title: 'sdfsdfsdfsfd',
isAnswer: true
title: "sdfsdfsdfsfd",
isAnswer: true,
},
{
id: 4,
title: 'asdasd4',
isAnswer: false
},
]
title: "asdasd4",
isAnswer: false,
},
],
courses: [
],
questions: [
},
],
}
courses: [],
questions: [],
};
export const numOfinitQs = initialState.questionBank.length;
export default function addExamReduser(state = initialState, { type, payload }) {
export default function addExamReduser(
state = initialState,
{ type, payload }
) {
switch (type) {
case 'ADD_EXAM_GRADE_AND_GROUP':
case "ADD_EXAM_GRADE_AND_GROUP":
return {
...state,
grade: payload.grade,
groupId: payload.groupId
}
groupId: payload.groupId,
};
case 'ADD_EXAM_DESCRIPTION':
case "ADD_EXAM_DESCRIPTION":
return {
...state,
name: payload.name,
@ -223,52 +210,60 @@ export default function addExamReduser(state = initialState, { type, payload })
budgetFileId: payload.budgetFileId,
};
case 'ADD_EXAM_QUESTIONAIRES':
case "ADD_EXAM_QUESTIONAIRES":
return {
...state,
questionnaires: [...state.questionnaires, payload]
}
case 'ADD_QUESTIONNAIRE_COURSES':
console.log(payload)
let thisQ = state.questionnaires.find(itm => itm.id == payload.questionnaireId)
let otherQ = state.questionnaires.filter(itm => itm.id !== payload.questionnaireId)
questionnaires: [...state.questionnaires, payload],
};
case "ADD_QUESTIONNAIRE_COURSES":
console.log(payload);
let thisQ = state.questionnaires.find(
(itm) => itm.id == payload.questionnaireId
);
let otherQ = state.questionnaires.filter(
(itm) => itm.id !== payload.questionnaireId
);
thisQ = {
...thisQ,
courses: [ ...thisQ.courses,payload]
}
console.log(thisQ)
courses: [...thisQ.courses, payload],
};
console.log(thisQ);
return {
...state,
questionnaires: [...otherQ, thisQ]
}
case 'ADD_ANSWERS':
console.log(payload)
let thisQC = state.questionnaires.find(itm => itm.id == payload[0].questionnaierId)
let otherQC = state.questionnaires.filter(itm => itm.id !== payload[0].questionnaierId)
questionnaires: [...otherQ, thisQ],
};
case "ADD_ANSWERS":
console.log(payload);
let thisQC = state.questionnaires.find(
(itm) => itm.id == payload[0].questionnaierId
);
let otherQC = state.questionnaires.filter(
(itm) => itm.id !== payload[0].questionnaierId
);
thisQC = {
...thisQC,
answers: [ ...thisQC?.answers,...payload]
}
answers: [...thisQC?.answers, ...payload],
};
return {
...state,
questionnaires: [...otherQC, thisQC]
}
questionnaires: [...otherQC, thisQC],
};
case 'ADD_EXAM_COURSE':
case "ADD_EXAM_COURSE":
return {
...state,
courses: [...state.courses, { ...payload, selectedQuestions:[]}],
courses: [...state.courses, { ...payload, selectedQuestions: [] }],
};
case 'REMOVE_EXAM_COURSE':
case "REMOVE_EXAM_COURSE":
return {
...state,
courses: state.courses.filter(itm => itm.id !== payload.id)
}
courses: state.courses.filter((itm) => itm.id !== payload.id),
};
case 'ADD_EXAM_QUESTIONS':
case "ADD_EXAM_QUESTIONS":
console.log("??????????????");
console.log(payload)
console.log(payload);
console.log(state.courses);
const othercourses = state.courses.filter(
(itm) => itm.id !== payload.lessonId
@ -276,88 +271,132 @@ export default function addExamReduser(state = initialState, { type, payload })
const selectedC = state.courses.filter(
(itm) => itm.id == payload.lessonId
);
selectedC[0] = { ...selectedC[0], selectedQuestions: [payload, ...selectedC[0].selectedQuestions] }
const newCourses = [...othercourses, ...selectedC]
selectedC[0] = {
...selectedC[0],
selectedQuestions: [payload, ...selectedC[0].selectedQuestions],
};
const newCourses = [...othercourses, ...selectedC];
return {
...state,
courses: newCourses
courses: newCourses,
};
case "ADD_EXAM_QUESTIONS2":
let newList = state.questions;
let isNew = true;
for(let i=0;i<newList.length;i++){
if(newList[i].examId===payload.examId){
newList[i].list = [...newList[i].list, payload.item];
isNew=false
}
}
if(isNew){
newList.push({
examId: payload.examId,
list: [payload.item],
});
}
case 'REMOVE_EXAM_QUESTIONS':
const dontDeleteThese = state.courses.filter(itm => itm.id !== payload.courseId)
const courseForDelete = state.courses.filter(itm => itm.id == payload.courseId)
courseForDelete[0] = { ...courseForDelete[0], selectedQuestions: courseForDelete[0].selectedQuestions.filter(itm => itm.questionId !== payload.questionId) }
const newCoursesWithDeleted = [...dontDeleteThese, ...courseForDelete]
console.log(newCoursesWithDeleted)
console.log(courseForDelete)
console.log(dontDeleteThese)
console.log(payload)
return {
...state,
courses: newCoursesWithDeleted
questions: newList,
};
}
case 'REMOVE_QUESTION_FROM_BANK':
case "REMOVE_EXAM_QUESTIONS":
const dontDeleteThese = state.courses.filter(
(itm) => itm.id !== payload.courseId
);
const courseForDelete = state.courses.filter(
(itm) => itm.id == payload.courseId
);
courseForDelete[0] = {
...courseForDelete[0],
selectedQuestions: courseForDelete[0].selectedQuestions.filter(
(itm) => itm.questionId !== payload.questionId
),
};
const newCoursesWithDeleted = [...dontDeleteThese, ...courseForDelete];
console.log(newCoursesWithDeleted);
console.log(courseForDelete);
console.log(dontDeleteThese);
console.log(payload);
return {
...state,
questionBank: state.questionBank.filter(itm => itm.questionId !== payload.questionId)
}
case 'GET_QUESTION_BACK_TO_BANK':
courses: newCoursesWithDeleted,
};
case "REMOVE_QUESTION_FROM_BANK":
return {
...state,
questionBank: [payload, ...state.questionBank,]
}
questionBank: state.questionBank.filter(
(itm) => itm.questionId !== payload.questionId
),
};
case "GET_QUESTION_BACK_TO_BANK":
return {
...state,
questionBank: [payload, ...state.questionBank],
};
case 'CHANGE_QUESTION_ORDER':
const dontChangeThese = state.courses.filter(itm => itm.id !== payload[0].courseId)
const courseForChange = state.courses.filter(itm => itm.id == payload[0].courseId)
courseForChange[0] = { ...courseForChange[0], selectedQuestions: payload }
const newChangedCourseSort = [...dontChangeThese, ...courseForChange]
console.log(payload)
case "CHANGE_QUESTION_ORDER":
const dontChangeThese = state.courses.filter(
(itm) => itm.id !== payload[0].courseId
);
const courseForChange = state.courses.filter(
(itm) => itm.id == payload[0].courseId
);
courseForChange[0] = {
...courseForChange[0],
selectedQuestions: payload,
};
const newChangedCourseSort = [...dontChangeThese, ...courseForChange];
console.log(payload);
return {
...state,
courses: newChangedCourseSort
}
case 'CHANGE_COURSE_ORDER':
console.log(payload)
courses: newChangedCourseSort,
};
case "CHANGE_COURSE_ORDER":
console.log(payload);
return {
...state,
courses: payload
}
case 'ADD_CUSTOM_QUESTION':
const otherCourses = state.courses.filter(itm => itm.id !== payload.courseId)
const selectedc = state.courses.filter(itm => itm.id == payload.courseId)
selectedc[0] = { ...selectedc[0], selectedQuestions: [payload, ...selectedc[0].selectedQuestions] }
const newcourses = [...selectedc, ...otherCourses]
courses: payload,
};
case "ADD_CUSTOM_QUESTION":
const otherCourses = state.courses.filter(
(itm) => itm.id !== payload.courseId
);
const selectedc = state.courses.filter(
(itm) => itm.id == payload.courseId
);
selectedc[0] = {
...selectedc[0],
selectedQuestions: [payload, ...selectedc[0].selectedQuestions],
};
const newcourses = [...selectedc, ...otherCourses];
return {
...state,
courses: newcourses
courses: newcourses,
};
}
case 'CHANGE_COURSE_NUM_OF_OPTIONS':
const otherCourseS = state.courses.filter(itm => itm.id !== payload.courseId)
const seLectedC = state.courses.filter(itm => itm.id == payload.courseId)
seLectedC[0] = { ...seLectedC[0], numberOfOptions: payload.value }
const neWCourses = [...seLectedC, ...otherCourseS]
case "CHANGE_COURSE_NUM_OF_OPTIONS":
const otherCourseS = state.courses.filter(
(itm) => itm.id !== payload.courseId
);
const seLectedC = state.courses.filter(
(itm) => itm.id == payload.courseId
);
seLectedC[0] = { ...seLectedC[0], numberOfOptions: payload.value };
const neWCourses = [...seLectedC, ...otherCourseS];
return {
...state,
courses: neWCourses
}
courses: neWCourses,
};
case 'CHANGE_QUESTIONNAIRES_ORDER':
case "CHANGE_QUESTIONNAIRES_ORDER":
return {
...state,
questionnaires: payload
}
questionnaires: payload,
};
default:
return state;
}
}

@ -7,8 +7,9 @@ const initialState = {
error: null,
info: null,
lastExamAdd: null,
preview : null,
subExamList:[],
preview: null,
subExamList: [],
confirm:null
};
export default function exam2(state = initialState, action) {
let { type, data } = action;
@ -17,6 +18,9 @@ export default function exam2(state = initialState, action) {
return { ...state, loading: false, info: data, error: null };
case "exam/preview":
return { ...state, loading: false, preview: data, error: null };
case "exam/confirm":
toast.success("درخواست با موفقیت انجام شد");
return { ...state, loading: false, confirm: data, error: null };
case "exam/parentAdd":
toast.success("آزمون شما با موفقیت ثبت شد");
return { ...state, loading: false, error: null, lastExamAdd: data.id };

@ -0,0 +1,30 @@
import { toast } from "react-toastify";
const initialState = {
loading: false,
error: null,
info: null,
list: null,
lastAdd: null,
};
export default function examQuestion(state = initialState, action) {
let { type, data } = action;
switch (type) {
case "examQuestion/info":
return { ...state, loading: false, info: data, error: null };
case "examQuestion/add":
// toast.success("درخواست با موفقیت انجام شد");
return { ...state, loading: false, error: null, lastAdd: data };
case "examQuestion/list":
return { ...state, loading: false, error: null, list: data };
case "examQuestion/loading":
return { ...state, loading: true };
case "examQuestion/error":
toast.error(data.message);
return { ...state, loading: false, error: data.message };
default:
return state;
}
}

@ -18,4 +18,6 @@ export { default as examGroup } from "./examGroup";
export { default as lesson } from "./lesson";
export { default as question } from "./question";
export { default as category } from "./category";
export { default as examQuestion } from "./examQuestion";

@ -1,89 +1,153 @@
import React, { useEffect, useState } from "react";
import attachIcon from '../../../assets/img/attach-circle.svg';
const AddQuestionPopUp = ({ titlePass, scorePass, submitOnClick, cancelOnClick, passOptionTitle, setAsAnswer, options }) => {
const gozine = [
'الف',
'ب',
'ج',
'د',
'ه',
'ز',
]
import { connect } from "react-redux";
import attachIcon from "../../../assets/img/attach-circle.svg";
import { question } from "../../../redux/actions";
const AddQuestionPopUp = ({
titlePass,
scorePass,
submitOnClick,
cancelOnClick,
passOptionTitle,
setAsAnswer,
options,
submitQuestion,
}) => {
const gozine = ["الف", "ب", "ج", "د", "ه", "ز"];
return (
<div className="w-full z-10 fixed bg-black bg-opacity-20 h-screen backdrop-blur flex flex-col items-center top-0 left-0 justify-center">
<div className="w-1/2 flex flex-col items-center bg-white p-6 py-10 rounded-xl shadow-lg">
<div className="w-full">
<div className="w-8 h-8 text-white text-sm rounded-full cursor-pointer flex justify-center items-center bg-red52" onClick={cancelOnClick}>
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 15.044 15.044">
<g id="vuesax_linear_card-remove" data-name="vuesax/linear/card-remove" transform="translate(-252.46 -511.461)">
<div
className="w-8 h-8 text-white text-sm rounded-full cursor-pointer flex justify-center items-center bg-red52"
onClick={cancelOnClick}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="12"
height="12"
viewBox="0 0 15.044 15.044"
>
<g
id="vuesax_linear_card-remove"
data-name="vuesax/linear/card-remove"
transform="translate(-252.46 -511.461)"
>
<g id="card-remove" transform="translate(253.309 512.31)">
<path id="Vector" d="M0,13.347,13.347,0" fill="none" stroke="#fff" strokeLinecap="round" strokeWidth="2" />
<path id="Vector-2" data-name="Vector" d="M13.347,13.347,0,0" fill="none" stroke="#fff" strokeLinecap="round" strokeWidth="2" />
<path
id="Vector"
d="M0,13.347,13.347,0"
fill="none"
stroke="#fff"
strokeLinecap="round"
strokeWidth="2"
/>
<path
id="Vector-2"
data-name="Vector"
d="M13.347,13.347,0,0"
fill="none"
stroke="#fff"
strokeLinecap="round"
strokeWidth="2"
/>
</g>
</g>
</svg>
</div>
</div>
<div className='w-4/5 flex flex-col text-blue3A mt-4 mb-2 font-bold justify-between items-center'>
<div className='w-11/12 flex flex-col bg-white rounded-xl border border-gray-300 shadow-sm'>
<textarea className='w-full border-b border-gray-300 rounded-t-xl p-4 text-blue3A overflow-hideen text-right outline-none' placeholder="صورت سوال..." rows={1}
<div className="w-4/5 flex flex-col text-blue3A mt-4 mb-2 font-bold justify-between items-center">
<div className="w-11/12 flex flex-col bg-white rounded-xl border border-gray-300 shadow-sm">
<textarea
className="w-full border-b border-gray-300 rounded-t-xl p-4 text-blue3A overflow-hideen text-right outline-none"
placeholder="صورت سوال..."
rows={1}
onChange={(e) => titlePass(e.target.value)}
/>
<div className='w-full p-3 px-4 h-12 flex justify-between items-center'>
<div className="w-full p-3 px-4 h-12 flex justify-between items-center">
<div>
<p className='text-xs'>نمره :
<input type='number' className="w-6 h-6 border border-gray-200 mr-1 rounded"
<p className="text-xs">
نمره :
<input
type="number"
className="w-6 h-6 border border-gray-200 mr-1 rounded"
onChange={(e) => scorePass(e.target.value)}
/>
</p>
</div>
<input type='file' className="hidden" id="Add_Question_Add_Image" />
<label htmlFor="Add_Question_Add_Image" className="flex items-center">
<input
type="file"
className="hidden"
id="Add_Question_Add_Image"
/>
<label
htmlFor="Add_Question_Add_Image"
className="flex items-center"
>
<p className="text-gray-500 ml-1">آپلود</p>
<img src={attachIcon} className="h-full w-10" />
</label>
</div>
</div>
<div className='w-11/12 justify-between mt-4 flex flex-wrap'>
{
options?.map(
(item) => (
<div className='my-2 flex items-center justify-center shadow-sm' style={{width: 'calc(50% - 10px)'}} onClick={() => setAsAnswer(item.id) }>
<p className={` h-12 flex items-center justify-center w-16 rounded-lg rounded-l-none ${item.isAnswer ? 'text-white bg-green-400' : 'bg-gray-200 border border-gray-300'}`}>{gozine[item.id - 1]}</p>
<input className={` h-12 outline-none flex items-center justify-center p-2 w-full rounded-lg rounded-r-none ${item.isAnswer ? 'bg-green-200' : 'bg-white border border-gray-300'}`}
onChange={e => passOptionTitle(e.target.value, item.id)}
placeholder={`گزینه ${item.id}`}/>
<div className="w-11/12 justify-between mt-4 flex flex-wrap">
{options?.map((item) => (
<div
className="my-2 flex items-center justify-center shadow-sm"
style={{ width: "calc(50% - 10px)" }}
onClick={() => setAsAnswer(item.id)}
>
<p
className={` h-12 flex items-center justify-center w-16 rounded-lg rounded-l-none ${
item.isAnswer
? "text-white bg-green-400"
: "bg-gray-200 border border-gray-300"
}`}
>
{gozine[item.id - 1]}
</p>
<input
className={` h-12 outline-none flex items-center justify-center p-2 w-full rounded-lg rounded-r-none ${
item.isAnswer
? "bg-green-200"
: "bg-white border border-gray-300"
}`}
onChange={(e) => passOptionTitle(e.target.value, item.id)}
placeholder={`گزینه ${item.id}`}
/>
</div>
)
)
}
))}
</div>
<div className="w-11/12 flex justify-end">
<div className="w-1/3 mt-5 flex justify-between items-center">
<button className=" bg-white text-xl text-red-500 border-red-500 w-full h-12 mx-1 rounded-md border" onClick={cancelOnClick
}>
<button
className=" bg-white text-xl text-red-500 border-red-500 w-full h-12 mx-1 rounded-md border"
onClick={cancelOnClick}
>
انصراف
</button>
<button className=" bg-green-500 text-xl text-white border-green-500 w-full ml-0 mx-3 h-12 rounded-md border" onClick={
submitOnClick
}>
<button
className=" bg-green-500 text-xl text-white border-green-500 w-full ml-0 mx-3 h-12 rounded-md border"
onClick={submitOnClick}
>
ثبت سوال
</button>
</div>
</div>
</div>
</div>
</div>
);
};
const mapStateToProps = (state) => ({
});
)
}
const mapDispatchToProps = {
submitQuestion:question.add
};
export default AddQuestionPopUp;
export default connect(mapStateToProps, mapDispatchToProps)(AddQuestionPopUp);

@ -3,7 +3,7 @@ import React, { useEffect } from 'react';
let optionsList = [];
const Question = ({data}) => {
const Question = ({ data, mode }) => {
// useEffect(()=>{
// })
@ -13,19 +13,12 @@ const Question = ({data}) => {
}
// console.log("==|>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
// console.log(optionsList);
const gozine = [
'الف',
'ب',
'ج',
'د',
'ه',
'ز',
]
const gozine = ["الف", "ب", "ج", "د", "ه", "ز"];
return (
<div className="w-full flex flex-col text-blue3A mt-4 mb-2 font-bold justify-between items-center">
<div className="w-11/12 flex flex-col bg-white rounded-xl border border-gray-300">
<div className="w-full border-b border-gray-300 p-4 text-blue3A text-right">
{data?.text}
{mode === 2 ? data?.title : data?.text}
</div>
<div className="w-full p-3 px-4 flex justify-between items-center">
<div>
@ -37,7 +30,8 @@ const Question = ({data}) => {
</div>
</div>
<div className="w-full justify-center mt-4 flex flex-wrap">
{optionsList?.map((item,index) => (
{mode !== 2 &&
optionsList?.map((item, index) => (
<div className="w-2/5 mx-2 my-2 flex items-center justify-center">
<p
className={` h-12 flex items-center justify-center w-16 rounded-lg rounded-l-none ${
@ -59,11 +53,32 @@ const Question = ({data}) => {
</p>
</div>
))}
{mode === 2 &&
data?.options?.map((item, index) => (
<div className="w-2/5 mx-2 my-2 flex items-center justify-center">
<p
className={` h-12 flex items-center justify-center w-16 rounded-lg rounded-l-none ${
item.isAnswer
? "text-white bg-green-400"
: "bg-gray-200 border border-gray-300"
}`}
>
{gozine[index]}
</p>
<p
className={` h-12 flex items-center justify-center w-full rounded-lg rounded-r-none ${
item.isAnswer
? "bg-green-200"
: "bg-white border border-gray-300"
}`}
>
{item?.title}
</p>
</div>
))}
</div>
</div>
);
}
};
export default Question;

@ -11,12 +11,14 @@ import filterIcon from "../../../assets/img/filter.svg";
import Question from "../components/question";
import { numOfinitQs } from "../../../redux/reducers/exam";
import AddQuestionPopUp from "../components/addQuestion";
import { category, exam, lesson, question } from "../../../redux/actions";
import { category, exam, examQuestion, lesson, question } from "../../../redux/actions";
import { AiOutlineCloseCircle } from "react-icons/ai";
import loadingGiff from "../../../assets/img/Rolling-2s-223px.gif";
import { BsCheck2All } from "react-icons/bs";
let seCounter = 0;
let eqCounter = 0;
let eqCounter2 = 0;
const AddQuestionsFromBank = ({
grades,
addExamState,
@ -41,7 +43,17 @@ const AddQuestionsFromBank = ({
subExamList,
subExamLoading,
emptySubexamList,
addQuestion,
addExamQuestion2,
submitQuestion,
lastNewQustionAdd,
lastExamQuestion,
examSubmitLoading,
addCustomQuestion,
}) => {
console.log("--------------------------");
console.log(addExamState?.questions);
console.log(addExamState?.courses);
const [name, setName] = useState(null);
const [type, setType] = useState(null);
const [description, setDescription] = useState(null);
@ -62,15 +74,16 @@ const AddQuestionsFromBank = ({
});
const [subexamAddPermission, setSubexamAddPermission] = useState(0);
const [subexamAddPart, setSubexamAddPart] = useState(false);
const [SelectedCourseIndex, setSelectedCourseIndex] = useState(null);
// console.log(choosedQuestionaries)
// console.log(newQuestionaire)
// console.log(addExamState.questionnaires)
// console.log(newCourse)
// console.log(addExamState.questionairesCourses)
console.log(selectedCourse);
// console.log(selectedCourse);
// console.log(answers)
console.log(choosedQuestion);
console.log(selectedCourse.selectedQuestions);
// console.log(choosedQuestion);
// console.log(selectedCourse.selectedQuestions);
// useEffect(()=>{
// emptySubexamList();
@ -86,7 +99,17 @@ const AddQuestionsFromBank = ({
if (source.droppableId !== destination?.droppableId) {
if (destination?.droppableId == "Choosed_Questions_Form_Bank") {
// dispatch({ type: "ADD_EXAM_QUESTIONS", payload: choosedQuestion });
console.log(":u:");
console.log(choosedQuestion);
addExamQuestion(choosedQuestion);
addExamQuestion2({
examId: subExamList[SelectedCourseIndex],
item: { id: choosedQuestion.id, coefficient: 1 },
});
// addQuestion({
// examId: subExamList[SelectedCourseIndex],
// questions: choosedQuestion.id,
// });
// dispatch({
// type: "REMOVE_QUESTION_FROM_BANK",
// payload: choosedQuestion,
@ -119,10 +142,10 @@ const AddQuestionsFromBank = ({
aaa.splice(destination.index, 0, removed);
dispatch({ type: "CHANGE_QUESTION_ORDER", payload: aaa });
console.log(result);
console.log(source.index);
console.log(destination.index);
console.log(aaa);
// console.log(result);
// console.log(source.index);
// console.log(destination.index);
// console.log(aaa);
}
}
};
@ -135,10 +158,10 @@ const AddQuestionsFromBank = ({
useEffect(() => {
if (activeCourse) {
getQuestion({
// lessonId: activeCourse,
// gradeId: addExamState.grade,
lessonId: 3,
gradeId: 7,
lessonId: activeCourse,
gradeId: addExamState.grade,
// lessonId: 3,
// gradeId: 7,
});
}
}, [activeCourse]);
@ -170,11 +193,11 @@ const AddQuestionsFromBank = ({
});
}, [numberOfOptions]);
console.log(question);
console.log(
addExamState.courses.filter((itm) => itm.id == selectedCourse.id)[0]
?.selectedQuestions
);
// console.log(question);
// console.log(
// addExamState.courses.filter((itm) => itm.id == selectedCourse.id)[0]
// ?.selectedQuestions
// );
const addLessonHandler = () => {
setAddLessonPart(true);
@ -187,8 +210,8 @@ const AddQuestionsFromBank = ({
};
const submitLessons = () => {
console.log("aaaaaaaaaaaaaaaa");
console.log(addExamState?.courses);
// console.log("aaaaaaaaaaaaaaaa");
// console.log(addExamState?.courses);
for (let i = 0; i < addExamState?.courses?.length; i++) {
addCategory({
title: addExamState?.courses[i].name,
@ -201,10 +224,24 @@ const AddQuestionsFromBank = ({
setSubexamAddPart(true);
};
//
const addNewQustionhandler = () => {
setFakeState(fakeState + 5);
// setNumberOfOptions(selectedCourse.numberOfOptions);
setAddQuestionPopuo("component");
let lessonId = addExamState.courses[SelectedCourseIndex].id;
for (let i = 0; i < questionTypeList.length; i++) {
if (questionTypeList[i].lessonId === lessonId) {
setNumberOfOptions(questionTypeList[i].questionType);
}
}
};
// subexamAdd----------------------------------
const [questionTypeList, setQuestionTypeList] = useState([]);
const subexamAddHandler = (index) => {
let inputs = document.querySelectorAll(`.subexamAddPart-input-${index}`);
console.log(inputs[2].checked);
// console.log(inputs[2].checked);
seCounter = index;
addSubexam({
pid: examId,
@ -217,15 +254,48 @@ const AddQuestionsFromBank = ({
negativePoint: inputs[2].checked,
ord: Number(inputs[4].value),
});
setQuestionTypeList([
...questionTypeList,
{
questionType: Number(inputs[1].value),
lessonId: addExamState.courses[index].id,
},
]);
};
const subexamPartFinalSubmit=()=>{
const subexamPartFinalSubmit = () => {
setSubexamAddPart(false);
}
};
const nextStephandler = () => {
// submitHandler();
stepClick();
for (let i = 0; i < addExamState.questions.length; i++) {
addQuestion({
examId: addExamState.questions[i].examId,
questions: addExamState.questions[i].list,
});
eqCounter++;
}
// stepClick();
};
useEffect(() => {
if (lastExamQuestion !== null) {
eqCounter2++;
if (eqCounter2 === eqCounter) {
stepClick();
}
}
}, [lastExamQuestion]);
//addNewQuestionToQuestionState-----------------------------------------
useEffect(() => {
if (lastNewQustionAdd) {
addExamQuestion2({
examId: subExamList[SelectedCourseIndex],
item: { id: lastNewQustionAdd, coefficient: 1 },
});
}
}, [lastNewQustionAdd]);
return (
<div className="flex flex-col h-screen relative">
{questionarePopUp && (
@ -424,7 +494,11 @@ const AddQuestionsFromBank = ({
<div
className="w-40 h-14 flex items-center justify-center rounded-lg bg-red52 text-white mt-10 mx-auto cursor-pointer"
onClick={subexamPartFinalSubmit}
style={subExamList?.length!==addExamState.courses?.length ? {filter:"grayscale(100%)",pointerEvents:'none'}:null}
style={
subExamList?.length !== addExamState.courses?.length
? { filter: "grayscale(100%)", pointerEvents: "none" }
: null
}
>
ثبت نهایی
</div>
@ -458,10 +532,10 @@ const AddQuestionsFromBank = ({
aaa.splice(destination.index, 0, removed);
dispatch({ type: "CHANGE_COURSE_ORDER", payload: aaa });
console.log(result);
console.log(source.index);
console.log(destination.index);
console.log(aaa);
// console.log(result);
// console.log(source.index);
// console.log(destination.index);
// console.log(aaa);
}
}}
>
@ -480,7 +554,7 @@ const AddQuestionsFromBank = ({
{addExamState?.courses?.length > 0 &&
addExamState.courses.map((item, index) => (
<>
{console.log(item)}
{/* {console.log(item)} */}
<Draggable
draggableId={`COURSE_${item.id}`}
index={index}
@ -499,6 +573,7 @@ const AddQuestionsFromBank = ({
onClick={() => {
setSelectedCourse(item);
setActiveCourse(item.id);
setSelectedCourseIndex(index);
}}
>
<div
@ -568,7 +643,7 @@ const AddQuestionsFromBank = ({
<DragDropContext
onDragEnd={(result) => handleOnDragEnd(result)}
onDragStart={(result) => {
console.log(result);
// console.log(result);
if (result.source.droppableId == "Choosed_Questions_Form_Bank") {
seChoosedQuestion(
addExamState.courses.filter(
@ -576,8 +651,8 @@ const AddQuestionsFromBank = ({
)[0]?.selectedQuestions[result.source.index]
);
} else {
console.log("MMMMMMMMMMMMMMMMMMMM");
console.log(result);
// console.log("MMMMMMMMMMMMMMMMMMMM");
// console.log(result);
seChoosedQuestion(
questionList?.find((itm) => itm.id == result.source.index)
);
@ -642,7 +717,7 @@ const AddQuestionsFromBank = ({
<div
className="flex flex-col items-center overflow-x-hidden overflow-scroll"
style={{ height: "30vh" }}
style={{ height: "40vh" }}
>
<div className="w-11/12 ">
{addQuestionPopup === "component" && (
@ -702,11 +777,51 @@ const AddQuestionsFromBank = ({
}}
submitOnClick={() => {
setAddQuestionPopuo(false);
dispatch({
type: "ADD_CUSTOM_QUESTION",
payload: question,
console.log(">y<");
console.log(question);
addCustomQuestion(question);
// dispatch({
// type: "ADD_CUSTOM_QUESTION",
// payload: question,
// });
let answer = null;
for (
let i = 0;
i < question.options.length;
i++
) {
if (question.options[i].isAnswer) {
answer = question.options[i].title;
}
}
submitQuestion({
text: question.title,
type: numberOfOptions,
answer,
categoryId:
categoryAddList[SelectedCourseIndex],
option1:
question.options.length > 0
? question.options[0]?.title
: null,
option2:
question.options.length > 1
? question.options[1]?.title
: null,
option3:
question.options.length > 2
? question.options[2]?.title
: null,
option4:
question.options.length > 3
? question.options[3]?.title
: null,
option5:
question.options.length > 4
? question.options[4]?.title
: null,
});
setNumberOfOptions(null);
}}
cancelOnClick={() => setAddQuestionPopuo(false)}
@ -758,7 +873,7 @@ const AddQuestionsFromBank = ({
/>
</svg>
</div>
<Question data={item} />
<Question data={item} mode={2} />
</div>
)}
</Draggable>
@ -787,13 +902,7 @@ const AddQuestionsFromBank = ({
</label>
<button
className=" w-2/3 mr-1 bg-transparent text-xl text-blue3A border-gray-300 h-12 rounded-xl border mb-6"
onClick={() => {
setFakeState(fakeState + 5);
setNumberOfOptions(
selectedCourse.numberOfOptions
);
setAddQuestionPopuo("component");
}}
onClick={addNewQustionhandler}
>
اضافه کردن سوال جدید +
</button>
@ -928,11 +1037,18 @@ const AddQuestionsFromBank = ({
{" "}
بازگشت به مرحله قبل{" "}
</button>
{!examSubmitLoading && (
<Button
title="مرحله بعدی"
className="w-1/12"
onClick={nextStephandler}
/>
)}
{examSubmitLoading && (
<div className="w-1/12 h-12 rounded-lg bg-red52 flex items-center justify-center">
<img src={loadingGiff} alt="loadingGiff" className="h-9" />
</div>
)}
</div>
</div>
);
@ -947,6 +1063,9 @@ const mapStateToProps = (state) => ({
examId: state.exam2.lastExamAdd,
subExamList: state.exam2.subExamList,
subExamLoading: state.exam2.loading,
lastNewQustionAdd: state.question.lastAdd,
lastExamQuestion: state.examQuestion.lastAdd,
examSubmitLoading: state.examQuestion.loading
// lessonList: state.lesson.list
});
@ -956,13 +1075,17 @@ const mapDispatchToProps = {
removeExamCourse: exam.removeExamCourse,
getQuestion: question.list,
addExamQuestion: exam.addExamQuestion,
addExamQuestion2: exam.addExamQuestion2,
removeQuestionFromBank: exam.removeQuestionFromBank,
removeExamQuestions: exam.removeExamQuestions,
getQuestionBackToBank: exam.getQuestionBackToBank,
changeQuestionOrder: exam.changeQuestionOrder,
addCategory: category.add,
addSubexam: exam.subexamAdd,
emptySubexamList : exam.emptySubexamList
emptySubexamList: exam.emptySubexamList,
addQuestion: examQuestion.add,
submitQuestion: question.add,
addCustomQuestion : exam.addCustomQuestion
};
export default connect(

@ -21,6 +21,7 @@ const ViewExam = ({
examPreview,
examId,
getExamPreview,
examConfirm,
}) => {
useEffect(() => {
window.scrollTo(0, 0);
@ -71,7 +72,8 @@ const ViewExam = ({
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>");
console.log(addExamState.startDate.month);
const submitHandler = () => {
// stepClick();
examConfirm({id:examId});
stepClick();
};
const createOptions = (item) => {
@ -117,7 +119,10 @@ const ViewExam = ({
</div>
<div className="w-full mt-4">
{createOptions(item).map((choice, index2) => (
<div key={index2} className="w-full flex items-stretch mb-2">
<div
key={index2}
className="w-full flex items-stretch mb-2"
>
<div
className="w-12 py-3 rounded-r-md flex items-center justify-center bg-gray-300"
style={
@ -178,7 +183,8 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = {
parentAdd: exam.parentAdd,
getExamPreview : exam.preview
getExamPreview: exam.preview,
examConfirm : exam.confirm
};
export default connect(mapStateToProps, mapDispatchToProps)(ViewExam);

@ -68,6 +68,14 @@ const AddQuestionnaireExam = ({
}
}, [answers]);
const [noteFile,setNoteFile]=useState(null);
const noteChooseFile=()=>{
let input = document.querySelector("#add-note-input-file");
input.click();
setNoteFile(input);
setFakeState(fakeState + 15);
}
return (
<>
{questionarePopUp && (
@ -120,7 +128,7 @@ const AddQuestionnaireExam = ({
<input
type="text"
placeholder="نام دفترچه..."
className="w-4/5 p-4 ml-2 rounded border border-red52 h-12 text-red26 outline-none"
className="w-3/6 p-4 ml-2 rounded border border-red52 h-12 text-red26 outline-none"
onChange={(e) =>
setNewQuestionaire({
...newQuestionaire,
@ -128,10 +136,23 @@ const AddQuestionnaireExam = ({
})
}
/>
<div
className="w-[15%] h-12 flex items-center justify-center text-sm rounded bg-red52 text-white cursor-pointer"
onClick={noteChooseFile}
>
انتخاب فایل
</div>
<div className="w-[20%] h-12 rounded border border-red53 flex items-center ltr text-xs px-2 overflow-hidden text-left text-ellipsis whitespace-normal">
{noteFile!==null ? noteFile?.value : "فایلی اضافه نشده"}
</div>
<div className="w-[10%] h-12 flex items-center justify-center text-sm rounded bg-[#111] text-white cursor-pointer">
آپلود
</div>
<input
type="file"
placeholder="آپلود فایل دفترچه"
className="bg-white items-center flex h-12 text-red26 outline-none"
className="bg-white items-center flex h-12 text-red26 outline-none hidden"
id="add-note-input-file"
/>
</div>
<div className="flex w-full justify-end pt-2">
@ -239,6 +260,7 @@ const AddQuestionnaireExam = ({
}}
/>
)}
{/* ==============================top-part============================= */}
<div className="flex py-10 items-start px-10 border-b border-gray-300">
<div className="flex flex-col w-1/6">
<div className="text-blue3A text-lg font-bold text-right px-4 border-r-4 border-blue65">
@ -253,16 +275,8 @@ const AddQuestionnaireExam = ({
onDragEnd={(result) => {
const { source, destination } = result;
if (source.droppableId == "Choosed_Questionnaires") {
// const data = {
// startIndex: choosedQuestion,
// endIndex: destination.index
// }
// dispatch({type:'CHANGE_QUESTION_ORDER', payload : data})
// console.log(data)
const aaa = [...addExamState.questionnaires];
const [removed] = aaa.splice(source.index, 1);
aaa.splice(destination.index, 0, removed);
dispatch({ type: "CHANGE_QUESTIONNAIRES_ORDER", payload: aaa });
console.log(result);
@ -339,7 +353,7 @@ const AddQuestionnaireExam = ({
</div>
</div>
</div>
{/* ====================================================================== */}
<div className="w-full flex px-10">
<div className="w-1/2 border-l flex flex-col border-gray-300 py-10">
{selectedQuestionare.id !== null && (
@ -354,7 +368,7 @@ const AddQuestionnaireExam = ({
<div className="w-4/5 ">
{addExamState.questionnaires
.find((itm) => itm.id == selectedQuestionare.id)
?.courses.map((item,index) => (
?.courses.map((item, index) => (
<React.Fragment key={index}>
<SelectedCourse
title={item.name}
@ -425,5 +439,3 @@ const mapStateToProps = (state) => ({
});
export default connect(mapStateToProps)(AddQuestionnaireExam);

Loading…
Cancel
Save