add exam api | 300

main
alireza khaji 2 years ago
parent 3e9308ed62
commit 526abcc2ab
  1. 23
      src/redux/actions/category.js
  2. 12
      src/redux/actions/exam.js
  3. 1
      src/redux/actions/index.js
  4. 36
      src/redux/reducers/category.js
  5. 26
      src/redux/reducers/exam2.js
  6. 2
      src/redux/reducers/index.js
  7. 105
      src/view/addExam/views/AddDescription.js
  8. 169
      src/view/addExam/views/AddQuestionsFromBank.js
  9. 2
      src/view/addExam/views/addQuestionnaireExam.js
  10. 40
      src/view/addExam/views/addQuestions.js

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

@ -13,6 +13,18 @@ const exam = {
(data = {}) => (data = {}) =>
async (dispatch) => async (dispatch) =>
await proxy.get("exam/preview", data, { dispatch }), await proxy.get("exam/preview", data, { dispatch }),
subexamAdd:
(data = {}) =>
async (dispatch) =>
await proxy.post("exam/subexamAdd", data, { dispatch }),
emptySubexamList: (data = {}) => {
return (dispatch) => {
dispatch({
type: "empty_subexam_list",
payload: data,
});
};
},
addExamDescription: (data = {}) => { addExamDescription: (data = {}) => {
return (dispatch) => { return (dispatch) => {
dispatch({ dispatch({

@ -17,6 +17,7 @@ export { default as exam } from "./exam";
export { default as examGroup } from "./examGroup"; export { default as examGroup } from "./examGroup";
export { default as lesson } from "./lesson"; export { default as lesson } from "./lesson";
export { default as question } from "./question"; export { default as question } from "./question";
export { default as category } from "./category";

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

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

@ -17,5 +17,5 @@ export { default as exam2 } from "./exam2";
export { default as examGroup } from "./examGroup"; export { default as examGroup } from "./examGroup";
export { default as lesson } from "./lesson"; export { default as lesson } from "./lesson";
export { default as question } from "./question"; export { default as question } from "./question";
export { default as category } from "./category";

@ -10,7 +10,10 @@ import InputIcon from "react-multi-date-picker/components/input_icon"
import RangeDatePicker from "../../../components/RangeDatePicker"; import RangeDatePicker from "../../../components/RangeDatePicker";
import FileInput from "../../../components/fileInput"; import FileInput from "../../../components/fileInput";
import { exam, file } from "../../../redux/actions"; import { exam, file } from "../../../redux/actions";
import moment from "jalali-moment";
import loadingGiff from "../../../assets/img/Rolling-2s-223px.gif";
let oldExamAdd = null;
const AddExamDescription = ({ const AddExamDescription = ({
grades, grades,
addExamState, addExamState,
@ -21,6 +24,9 @@ const AddExamDescription = ({
loading, loading,
lastUploadId, lastUploadId,
addExamDescription, addExamDescription,
parentAdd,
lastExamAdd,
addExamLoading,
}) => { }) => {
const [name, setName] = useState(null); const [name, setName] = useState(null);
const [type, setType] = useState(null); const [type, setType] = useState(null);
@ -29,8 +35,22 @@ const AddExamDescription = ({
const [date, setDate] = useState({ format: "MM/DD/YYYY" }); const [date, setDate] = useState({ format: "MM/DD/YYYY" });
const [startDate, setStartDate] = useState(null); const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null); const [endDate, setEndDate] = useState(null);
const [questionCount, setQuestionCount] = useState(null);
// const [budgetFileId,setBudgetFileId]=useState(null); // const [budgetFileId,setBudgetFileId]=useState(null);
useEffect(() => {
oldExamAdd = lastExamAdd;
}, []);
useEffect(() => {
console.log("a1");
if (lastExamAdd && lastExamAdd !== oldExamAdd) {
console.log("a2");
addExamDescription(payload);
stepClick();
}
}, [lastExamAdd]);
const payload = { const payload = {
name: name, name: name,
description: description, description: description,
@ -78,6 +98,45 @@ const AddExamDescription = ({
// setUploadImgNumber(1); // setUploadImgNumber(1);
}; };
const submitHandler = () => {
// let questionCount = 0;
// for (let i = 0; i < addExamState.courses.length; i++) {
// questionCount += addExamState.courses[i].selectedQuestions.length;
// }
parentAdd({
name: name,
description: description,
// startDate: moment(
// `${addExamState.startDate?.year}/${addExamState.startDate?.month}/${addExamState.startDate?.day} ${addExamState.startDate?.hour}:${addExamState.startDate?.minute}`
// )
// .locale("en")
// .format("YYYY-MM-DD HH:mm"),
startDate: moment
.from(
`${startDate?.year}/${startDate?.month}/${startDate?.day} ${startDate?.hour}:${startDate?.minute}`,
"fa",
"YYYY/MM/DD HH:mm"
)
.format("YYYY-MM-DD HH:mm"),
endDate: moment
.from(
`${endDate?.year}/${endDate?.month}/${endDate?.day} ${endDate?.hour}:${endDate?.minute}`,
"fa",
"YYYY/MM/DD HH:mm"
)
.format("YYYY-MM-DD HH:mm"),
duration: duration || 60,
// duration:30,
type: type,
//questionCount: addExamState.questions.length,
questionCount: Number(questionCount),
examGroupId: addExamState.groupId,
levelCriterion: null,
budgetFileId: lastUploadId,
});
// stepClick();
};
// useEffect(() => {}, [lastUploadId]); // useEffect(() => {}, [lastUploadId]);
return ( return (
<> <>
@ -143,12 +202,20 @@ const AddExamDescription = ({
placeholder="توضیحات آزمون" placeholder="توضیحات آزمون"
onChange={(e) => setDescription(e.target.value)} onChange={(e) => setDescription(e.target.value)}
></textarea> ></textarea>
<input <div className="w-full flex items-center justify-between mt-6">
type="text" <input
placeholder="مدت زمان آزمون(دقیقه)" type="text"
className="w-1/3 bg-white px-4 h-14 border border-gray-300 rounded-lg text-blue3A outline-blue65 mt-6" placeholder="مدت زمان آزمون(دقیقه)"
onChange={(e) => setDuration(e.target.value)} className="w-1/3 bg-white px-4 h-14 border border-gray-300 rounded-lg text-blue3A outline-blue65"
/> onChange={(e) => setDuration(e.target.value)}
/>
<input
type="text"
placeholder="تعداد سؤالات آزمون"
className="w-1/3 bg-white px-4 h-14 border border-gray-300 rounded-lg text-blue3A outline-blue65"
onChange={(e) => setQuestionCount(e.target.value)}
/>
</div>
</div> </div>
</div> </div>
@ -215,15 +282,18 @@ const AddExamDescription = ({
{" "} {" "}
بازگشت به مرحله قبل{" "} بازگشت به مرحله قبل{" "}
</button> </button>
<Button {!addExamLoading && (
title="مرحله بعدی" <Button
className="w-1/12" title="مرحله بعدی"
onClick={() => { className="w-1/12"
// dispatch({ type: "ADD_EXAM_DESCRIPTION", payload }); onClick={submitHandler}
addExamDescription(payload); />
stepClick(); )}
}} {addExamLoading && (
/> <div className="w-1/12 h-12 flex items-center justify-center text-white bg-red52 rounded-lg">
<img src={loadingGiff} alt="loadingGiff" className="h-9" />
</div>
)}
</div> </div>
</div> </div>
</> </>
@ -235,11 +305,14 @@ const mapStateToProps = (state) => ({
addExamState: state.addExamReduser, addExamState: state.addExamReduser,
loading: state.file.loading, loading: state.file.loading,
lastUploadId: state.file.lastUpload, lastUploadId: state.file.lastUpload,
lastExamAdd: state.exam2.lastExamAdd,
addExamLoading: state.exam2.loading
}); });
const mapDispatchToProps = { const mapDispatchToProps = {
uploadImg: file.upload, uploadImg: file.upload,
addExamDescription : exam.addExamDescription addExamDescription : exam.addExamDescription,
parentAdd: exam.parentAdd
}; };
export default connect(mapStateToProps, mapDispatchToProps)(AddExamDescription); export default connect(mapStateToProps, mapDispatchToProps)(AddExamDescription);

@ -11,10 +11,12 @@ import filterIcon from "../../../assets/img/filter.svg";
import Question from "../components/question"; import Question from "../components/question";
import { numOfinitQs } from "../../../redux/reducers/exam"; import { numOfinitQs } from "../../../redux/reducers/exam";
import AddQuestionPopUp from "../components/addQuestion"; import AddQuestionPopUp from "../components/addQuestion";
import { exam, lesson, question } from "../../../redux/actions"; import { category, exam, lesson, question } from "../../../redux/actions";
import { AiOutlineCloseCircle } from "react-icons/ai"; import { AiOutlineCloseCircle } from "react-icons/ai";
import loadingGiff from "../../../assets/img/Rolling-2s-223px.gif"; import loadingGiff from "../../../assets/img/Rolling-2s-223px.gif";
import { BsCheck2All } from "react-icons/bs";
let seCounter = 0;
const AddQuestionsFromBank = ({ const AddQuestionsFromBank = ({
grades, grades,
addExamState, addExamState,
@ -32,7 +34,13 @@ const AddQuestionsFromBank = ({
removeQuestionFromBank, removeQuestionFromBank,
removeExamQuestions, removeExamQuestions,
getQuestionBackToBank, getQuestionBackToBank,
submitHandler, addCategory,
categoryAddList,
addSubexam,
examId,
subExamList,
subExamLoading,
emptySubexamList,
}) => { }) => {
const [name, setName] = useState(null); const [name, setName] = useState(null);
const [type, setType] = useState(null); const [type, setType] = useState(null);
@ -52,7 +60,8 @@ const AddQuestionsFromBank = ({
title: "", title: "",
selectedQuestions: [], selectedQuestions: [],
}); });
const [subexamAddPermission, setSubexamAddPermission] = useState(0);
const [subexamAddPart, setSubexamAddPart] = useState(false);
// console.log(choosedQuestionaries) // console.log(choosedQuestionaries)
// console.log(newQuestionaire) // console.log(newQuestionaire)
// console.log(addExamState.questionnaires) // console.log(addExamState.questionnaires)
@ -63,6 +72,10 @@ const AddQuestionsFromBank = ({
console.log(choosedQuestion); console.log(choosedQuestion);
console.log(selectedCourse.selectedQuestions); console.log(selectedCourse.selectedQuestions);
// useEffect(()=>{
// emptySubexamList();
// },[])
const [fakeState, setFakeState] = useState(2); const [fakeState, setFakeState] = useState(2);
const payload = { name: name, description: description, type: type }; const payload = { name: name, description: description, type: type };
@ -173,10 +186,46 @@ const AddQuestionsFromBank = ({
addLesson({ name }); addLesson({ name });
}; };
const nextStephandler=()=>{ const submitLessons = () => {
submitHandler(); console.log("aaaaaaaaaaaaaaaa");
stepClick(); console.log(addExamState?.courses);
for (let i = 0; i < addExamState?.courses?.length; i++) {
addCategory({
title: addExamState?.courses[i].name,
gradeId: addExamState?.grade,
lessonId: addExamState?.courses[i].id,
});
}
setSubexamAddPermission(1);
setQuestionairePopUp(false);
setSubexamAddPart(true);
};
// subexamAdd----------------------------------
const subexamAddHandler = (index) => {
let inputs = document.querySelectorAll(`.subexamAddPart-input-${index}`);
console.log(inputs[2].checked);
seCounter = index;
addSubexam({
pid: examId,
name: addExamState?.courses[index].name,
description: " ",
categoryId: categoryAddList[index],
questionType: Number(inputs[1].value),
questionCount: Number(inputs[3].value),
coefficient: Number(inputs[0].value),
negativePoint: inputs[2].checked,
ord: Number(inputs[4].value),
});
};
const subexamPartFinalSubmit=()=>{
setSubexamAddPart(false);
} }
const nextStephandler = () => {
// submitHandler();
stepClick();
};
return ( return (
<div className="flex flex-col h-screen relative"> <div className="flex flex-col h-screen relative">
{questionarePopUp && ( {questionarePopUp && (
@ -249,7 +298,7 @@ const AddQuestionsFromBank = ({
</button> </button>
<button <button
className="p-2 px-4 bg-red52 text-white rounded-md shadow-md mr-2" className="p-2 px-4 bg-red52 text-white rounded-md shadow-md mr-2"
onClick={() => setQuestionairePopUp(false)} onClick={submitLessons}
> >
ثبت دروس ثبت دروس
</button> </button>
@ -287,6 +336,101 @@ const AddQuestionsFromBank = ({
)} )}
</div> </div>
)} )}
{subexamAddPart && (
<div className="w-full z-10 fixed h-screen backdrop-blur flex items-center top-0 justify-center ">
<AiOutlineCloseCircle
className="text-4xl text-red-600 cursor-pointer absolute top-6 left-20 z-20"
onClick={() => setAddLessonPart(false)}
/>
<div className="w-4/5 h-4/5 max-h-4/5 overflow-y-auto p-6 rounded-lg bg-[#fff] ">
<div className="w-full rtl flex items-center mb-6">
<div className="w-2 h-7 bg-blue-500 ml-2"></div>
<div className="text-xl tet-right">
تکمیل جزئیات دروس اضافه شده
</div>
</div>
{addExamState?.courses.map((item, index) => (
<div className="w-full pb-4 border-b border-gray-200 mb-3">
<div className="w-full text-right text-lg">{item.name}</div>
<div className="w-full flex items-center justify-between mt-4">
<div className="flex items-center">
<div>ضریب</div>
<input
type="text"
className={`subexamAddPart-input-${index} w-16 h-10 rounded border text-center mr-2`}
/>
</div>
<div className="flex items-center">
<div>تعداد گزینه</div>
<input
type="text"
className={`subexamAddPart-input-${index} w-16 h-10 rounded border text-center mr-2`}
/>
</div>
<div className="flex items-center">
<div>نمره منفی</div>
<input
type="checkbox"
className={`subexamAddPart-input-${index} w-10 h-10 rounded border text-center accent-red52 mr-2`}
/>
</div>
<div className="flex items-center">
<div>تعداد سوالات</div>
<input
type="text"
className={`subexamAddPart-input-${index} w-16 h-10 rounded border text-center mr-2`}
/>
</div>
<div className="flex items-center">
<div>ترتیب</div>
<input
type="text"
className={`subexamAddPart-input-${index} w-16 h-10 rounded border text-center mr-2`}
defaultValue={index + 1}
/>
</div>
{!subExamLoading && (
<div
className="w-24 h-10 flex items-center justify-center rounded bg-red52 text-white text-sm cursor-pointer"
onClick={() => subexamAddHandler(index)}
style={
subExamList[index]
? {
backgroundColor: "#84CC16",
pointerEvents: "none",
}
: null
}
>
{subExamList[index] ? (
<BsCheck2All className="text-xl text-white" />
) : (
"ثبت اطلاعات"
)}
</div>
)}
{subExamLoading && seCounter === index && (
<div className="w-24 h-10 flex items-center justify-center rounded bg-red52 text-white text-sm">
<img
src={loadingGiff}
alt="loadingGiff"
className="h-8"
/>
</div>
)}
</div>
</div>
))}
<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}
>
ثبت نهایی
</div>
</div>
</div>
)}
{/* ====================================================================================== */} {/* ====================================================================================== */}
<div className="flex py-3 items-center px-10 border-b border-gray-200"> <div className="flex py-3 items-center px-10 border-b border-gray-200">
<div className="flex flex-col w-1/6"> <div className="flex flex-col w-1/6">
@ -452,7 +596,7 @@ const AddQuestionsFromBank = ({
{selectedCourse.id !== null && ( {selectedCourse.id !== null && (
<> <>
{/* Picked Questions Top Bar */} {/* Picked Questions Top Bar */}
<div className="w-full flex h-16 px-8 mb-3 justify-start pt-4 items-center"> {/* <div className="w-full flex h-16 px-8 mb-3 justify-start pt-4 items-center bg-black">
<h1 className="text-blue3A font-bold text-lg text-right pl-4"> <h1 className="text-blue3A font-bold text-lg text-right pl-4">
سوالات {selectedCourse.title} سوالات {selectedCourse.title}
</h1> </h1>
@ -494,7 +638,7 @@ const AddQuestionsFromBank = ({
/> />
<p>نمره منفی</p> <p>نمره منفی</p>
</div> </div>
</div> </div> */}
<div <div
className="flex flex-col items-center overflow-x-hidden overflow-scroll" className="flex flex-col items-center overflow-x-hidden overflow-scroll"
@ -799,6 +943,10 @@ const mapStateToProps = (state) => ({
addExamState: state.addExamReduser, addExamState: state.addExamReduser,
addLessonLoading: state.lesson.loading, addLessonLoading: state.lesson.loading,
questionList: state.question.list, questionList: state.question.list,
categoryAddList: state.category.addList,
examId: state.exam2.lastExamAdd,
subExamList: state.exam2.subExamList,
subExamLoading: state.exam2.loading,
// lessonList: state.lesson.list // lessonList: state.lesson.list
}); });
@ -812,6 +960,9 @@ const mapDispatchToProps = {
removeExamQuestions: exam.removeExamQuestions, removeExamQuestions: exam.removeExamQuestions,
getQuestionBackToBank: exam.getQuestionBackToBank, getQuestionBackToBank: exam.getQuestionBackToBank,
changeQuestionOrder: exam.changeQuestionOrder, changeQuestionOrder: exam.changeQuestionOrder,
addCategory: category.add,
addSubexam: exam.subexamAdd,
emptySubexamList : exam.emptySubexamList
}; };
export default connect( export default connect(

@ -425,3 +425,5 @@ const mapStateToProps = (state) => ({
}); });
export default connect(mapStateToProps)(AddQuestionnaireExam); export default connect(mapStateToProps)(AddQuestionnaireExam);

@ -26,44 +26,7 @@ const AddQuestions = ({
getLesson(); getLesson();
}, [lastAdd]); }, [lastAdd]);
const submitHandler = () => {
let questionCount = 0;
for (let i = 0; i < addExamState.courses.length; i++) {
questionCount += addExamState.courses[i].selectedQuestions.length;
}
parentAdd({
name: addExamState.name,
description: addExamState.description,
// startDate: moment(
// `${addExamState.startDate?.year}/${addExamState.startDate?.month}/${addExamState.startDate?.day} ${addExamState.startDate?.hour}:${addExamState.startDate?.minute}`
// )
// .locale("en")
// .format("YYYY-MM-DD HH:mm"),
startDate: moment
.from(
`${addExamState.startDate?.year}/${addExamState.startDate?.month}/${addExamState.startDate?.day} ${addExamState.startDate?.hour}:${addExamState.startDate?.minute}`,
"fa",
"YYYY/MM/DD HH:mm"
)
.format("YYYY-MM-DD HH:mm"),
endDate: moment
.from(
`${addExamState.endDate?.year}/${addExamState.endDate?.month}/${addExamState.endDate?.day} ${addExamState.endDate?.hour}:${addExamState.endDate?.minute}`,
"fa",
"YYYY/MM/DD HH:mm"
)
.format("YYYY-MM-DD HH:mm"),
duration: addExamState?.duration || 60,
// duration:30,
type: addExamState.type,
//questionCount: addExamState.questions.length,
questionCount :questionCount,
examGroupId: addExamState.groupId,
levelCriterion: null,
budgetFileId: addExamState.budgetFileId,
});
// stepClick();
};
return addExamState.type == 2 ? ( return addExamState.type == 2 ? (
<AddQuestionnaireExam stepClick={stepClick} backStep={backStep} /> <AddQuestionnaireExam stepClick={stepClick} backStep={backStep} />
@ -73,7 +36,6 @@ const AddQuestions = ({
backStep={backStep} backStep={backStep}
lessonList={lessonList} lessonList={lessonList}
addLesson={addLesson} addLesson={addLesson}
submitHandler={submitHandler}
/> />
); );
}; };

Loading…
Cancel
Save