QUESTION
This commit is contained in:
parent
6ec573a61d
commit
b0bde77082
|
|
@ -14,6 +14,9 @@ const File = ({
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { formik, t, isError,errorMsg } = useFormField(name, props);
|
const { formik, t, isError,errorMsg } = useFormField(name, props);
|
||||||
let imageUrl = formik?.values?.[name] ?? null;
|
let imageUrl = formik?.values?.[name] ?? null;
|
||||||
|
console.log(imageUrl);
|
||||||
|
console.log(typeof imageUrl === 'string');
|
||||||
|
|
||||||
const fileList: UploadFile[] = useMemo(() => {
|
const fileList: UploadFile[] = useMemo(() => {
|
||||||
if (!imageUrl) return [];
|
if (!imageUrl) return [];
|
||||||
|
|
||||||
|
|
|
||||||
33
src/Hooks/useSaveOnDisconnect.tsx
Normal file
33
src/Hooks/useSaveOnDisconnect.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
const useSaveOnDisconnect = (noChange: boolean, QUESTION_OBJECT_KEY: string, SavedQuestionData: any) => {
|
||||||
|
useEffect(() => {
|
||||||
|
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
||||||
|
console.log("disconnect");
|
||||||
|
if (noChange) {
|
||||||
|
const jsonData = JSON.stringify(SavedQuestionData);
|
||||||
|
localStorage.setItem(QUESTION_OBJECT_KEY, jsonData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOffline = () => {
|
||||||
|
console.log("disconnect");
|
||||||
|
if (noChange) {
|
||||||
|
const jsonData = JSON.stringify(SavedQuestionData);
|
||||||
|
localStorage.setItem(QUESTION_OBJECT_KEY, jsonData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add event listeners
|
||||||
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
window.addEventListener('offline', handleOffline);
|
||||||
|
|
||||||
|
// Cleanup function
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
window.removeEventListener('offline', handleOffline);
|
||||||
|
};
|
||||||
|
}, [noChange, QUESTION_OBJECT_KEY, SavedQuestionData]); // Add dependencies to the hook
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useSaveOnDisconnect;
|
||||||
|
|
@ -43,6 +43,7 @@ const FormikFormModel: React.FC<FormikFormProps> = ({
|
||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
|
|
||||||
return <Form className="w-100">{children}</Form>;
|
return <Form className="w-100">{children}</Form>;
|
||||||
}}
|
}}
|
||||||
</Formik>
|
</Formik>
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,17 @@ import { toast } from "react-toastify";
|
||||||
import AcceptModal from "./Model/AcceptModal";
|
import AcceptModal from "./Model/AcceptModal";
|
||||||
import { useModalState } from "../../zustand/Modal";
|
import { useModalState } from "../../zustand/Modal";
|
||||||
import { ModalEnum } from "../../enums/Model";
|
import { ModalEnum } from "../../enums/Model";
|
||||||
|
import { cleanObject } from "../../utils/cleanObject";
|
||||||
|
import { hasItems } from "../../utils/hasItems";
|
||||||
|
import { QUESTION_OBJECT_KEY } from "../../config/AppKey";
|
||||||
|
import useSaveOnDisconnect from "../../Hooks/useSaveOnDisconnect";
|
||||||
|
import { getLocalStorage } from "../../utils/LocalStorage";
|
||||||
|
|
||||||
const AddPage: React.FC = () => {
|
const AddPage: React.FC = () => {
|
||||||
|
|
||||||
|
|
||||||
const { mutate, isSuccess, isLoading ,mutateAsync} = useAddQuestion();
|
const { mutate, isSuccess, isLoading ,mutateAsync} = useAddQuestion();
|
||||||
const {object_to_edit,set_Tags_search,set_object_to_edit,set_Success} = useObjectToEdit()
|
const {object_to_edit,set_Tags_search,set_object_to_edit,set_Success,SavedQuestionData} = useObjectToEdit()
|
||||||
|
|
||||||
const {subject_id} = useParams<ParamsEnum>()
|
const {subject_id} = useParams<ParamsEnum>()
|
||||||
const {isBseQuestion,set_isBseQuestion} = useObjectToEdit()
|
const {isBseQuestion,set_isBseQuestion} = useObjectToEdit()
|
||||||
|
|
@ -43,6 +48,8 @@ const AddPage: React.FC = () => {
|
||||||
"isBase": 1,
|
"isBase": 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mutateAsync(newBseQuestion).then((data) => {
|
mutateAsync(newBseQuestion).then((data) => {
|
||||||
const newBseQuestionId = (data as any)?.data?.id;
|
const newBseQuestionId = (data as any)?.data?.id;
|
||||||
const Questions = DataToSend?.Questions;
|
const Questions = DataToSend?.Questions;
|
||||||
|
|
@ -73,16 +80,35 @@ const AddPage: React.FC = () => {
|
||||||
toast.success(t("validation.the_possess_done_successful"))
|
toast.success(t("validation.the_possess_done_successful"))
|
||||||
set_object_to_edit(null)
|
set_object_to_edit(null)
|
||||||
set_Success(true)
|
set_Success(true)
|
||||||
|
localStorage.removeItem(QUESTION_OBJECT_KEY)
|
||||||
|
|
||||||
}
|
}
|
||||||
}, [isSuccess])
|
}, [isSuccess])
|
||||||
|
|
||||||
|
let cleanedQuestionOptions = cleanObject(SavedQuestionData);
|
||||||
|
let noChange =hasItems(cleanedQuestionOptions)
|
||||||
|
|
||||||
|
useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
|
||||||
|
|
||||||
|
const SavedData = {} as any
|
||||||
|
console.log(SavedData);
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
if(!noChange){
|
||||||
|
navigate(-1)
|
||||||
|
localStorage.removeItem(QUESTION_OBJECT_KEY)
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
setIsOpen(ModalEnum?.QUESTION_ACCEPT);
|
setIsOpen(ModalEnum?.QUESTION_ACCEPT);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(isBseQuestion){
|
if(isBseQuestion){
|
||||||
return (
|
return (
|
||||||
<div className="exercise_add">
|
<div className="exercise_add">
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { useEffect } from "react";
|
||||||
import { Modal, Spin } from "antd";
|
import { Modal, Spin } from "antd";
|
||||||
import FormikForm from "../../Layout/Dashboard/FormikFormModel";
|
import FormikForm from "../../Layout/Dashboard/FormikFormModel";
|
||||||
import { getInitialValues, getValidationSchema ,getInitialValuesBase, getValidationSchemaBase, processTags} from "./Model/formUtil";
|
import { getInitialValues, getValidationSchema ,getInitialValuesBase, getValidationSchemaBase, processTags} from "./Model/formUtil";
|
||||||
import { useAddQuestion, useGetAllQuestion, useUpdateQuestion } from "../../api/Question";
|
import { useAddQuestion, useDeleteQuestion, useGetAllQuestion, useUpdateQuestion } from "../../api/Question";
|
||||||
import { useQueryClient } from "react-query";
|
import { useQueryClient } from "react-query";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
|
@ -19,10 +19,10 @@ import { toast } from "react-toastify";
|
||||||
const EditPage: React.FC = () => {
|
const EditPage: React.FC = () => {
|
||||||
|
|
||||||
const {question_id,subject_id} = useParams<ParamsEnum>()
|
const {question_id,subject_id} = useParams<ParamsEnum>()
|
||||||
const {isBseQuestion,set_isBseQuestion,set_Tags_search} = useObjectToEdit()
|
const {isBseQuestion,set_isBseQuestion,set_Tags_search,DeletedQuestions} = useObjectToEdit()
|
||||||
|
|
||||||
const { mutate, isSuccess, isLoading } = useUpdateQuestion();
|
const { mutate, isSuccess, isLoading } = useUpdateQuestion();
|
||||||
const { mutate:AddQuestion} = useAddQuestion();
|
const { mutate:DeleteQuestion} = useDeleteQuestion();
|
||||||
|
|
||||||
const {data,isLoading:dataLoading}= useGetAllQuestion({show:question_id})
|
const {data,isLoading:dataLoading}= useGetAllQuestion({show:question_id})
|
||||||
|
|
||||||
|
|
@ -45,7 +45,6 @@ const EditPage: React.FC = () => {
|
||||||
console.log(DataToSend);
|
console.log(DataToSend);
|
||||||
|
|
||||||
if(isBseQuestion){
|
if(isBseQuestion){
|
||||||
console.log(1);
|
|
||||||
|
|
||||||
const UpdateBseQuestion = {
|
const UpdateBseQuestion = {
|
||||||
"id":DataToSend?.id,
|
"id":DataToSend?.id,
|
||||||
|
|
@ -55,10 +54,17 @@ const EditPage: React.FC = () => {
|
||||||
if( typeof UpdateBseQuestion?.image === "string"){
|
if( typeof UpdateBseQuestion?.image === "string"){
|
||||||
delete UpdateBseQuestion["image"]
|
delete UpdateBseQuestion["image"]
|
||||||
}
|
}
|
||||||
console.log(UpdateBseQuestion);
|
console.log(DeletedQuestions,"DeletedQuestions");
|
||||||
|
|
||||||
mutate(UpdateBseQuestion)
|
mutate(UpdateBseQuestion)
|
||||||
|
|
||||||
|
|
||||||
|
DeletedQuestions?.map((item:any)=>{
|
||||||
|
DeleteQuestion({id:item?.id})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const Questions = DataToSend?.Questions;
|
const Questions = DataToSend?.Questions;
|
||||||
console.log(Questions,"Questions");
|
console.log(Questions,"Questions");
|
||||||
|
|
||||||
|
|
@ -84,7 +90,8 @@ const EditPage: React.FC = () => {
|
||||||
const QuestionOptions = {
|
const QuestionOptions = {
|
||||||
old: oldQuestionOptions,
|
old: oldQuestionOptions,
|
||||||
new: newQuestionOptions
|
new: newQuestionOptions
|
||||||
};
|
} ;
|
||||||
|
console.log(QuestionOptions);
|
||||||
|
|
||||||
mutate({
|
mutate({
|
||||||
...updatedObject,
|
...updatedObject,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { ModalEnum } from "../../../enums/Model";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
|
import { QUESTION_OBJECT_KEY } from "../../../config/AppKey";
|
||||||
|
|
||||||
const AcceptModal: React.FC = () => {
|
const AcceptModal: React.FC = () => {
|
||||||
const { isOpen, setIsOpen } = useModalState((state) => state);
|
const { isOpen, setIsOpen } = useModalState((state) => state);
|
||||||
|
|
@ -12,8 +13,12 @@ const AcceptModal: React.FC = () => {
|
||||||
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
|
localStorage.removeItem(QUESTION_OBJECT_KEY)
|
||||||
console.log("Handle submit clicked");
|
console.log("Handle submit clicked");
|
||||||
|
setIsOpen("");
|
||||||
|
|
||||||
navigate(-1)
|
navigate(-1)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const{set_Success,Success} = useObjectToEdit()
|
const{set_Success,Success,set_SavedQuestionData} = useObjectToEdit()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Success) {
|
if (Success) {
|
||||||
|
|
@ -25,6 +25,9 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
}, [Success]);
|
}, [Success]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
set_SavedQuestionData(formik.values)
|
||||||
|
}, [formik?.values])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -79,7 +82,7 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{formik?.values?.QuestionOptions?.length < 4 && (
|
{formik?.values?.QuestionOptions?.length < 5 && (
|
||||||
<p className="add_new_button" >
|
<p className="add_new_button" >
|
||||||
<FaCirclePlus onClick={handleAddChoice} size={23} /> {t("header.add_new_choice")}
|
<FaCirclePlus onClick={handleAddChoice} size={23} /> {t("header.add_new_choice")}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{formik?.values?.QuestionOptions?.length < 4 && (
|
{formik?.values?.QuestionOptions?.length < 5 && (
|
||||||
<p className="add_new_button" >
|
<p className="add_new_button" >
|
||||||
<FaCirclePlus onClick={handleAddChoice} size={23} /> {t("header.add_new_choice")}
|
<FaCirclePlus onClick={handleAddChoice} size={23} /> {t("header.add_new_choice")}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,24 @@ import { getCharFromNumber } from '../../../../utils/getCharFromNumber';
|
||||||
import CheckboxField from './CheckboxField';
|
import CheckboxField from './CheckboxField';
|
||||||
import TextField from './TextField';
|
import TextField from './TextField';
|
||||||
import File from './File';
|
import File from './File';
|
||||||
|
import { FaCirclePlus, FaDeleteLeft } from 'react-icons/fa6';
|
||||||
|
import { FaTrash } from 'react-icons/fa';
|
||||||
|
|
||||||
const ChoiceFields = ({index,data}:{index:number , data :Choice }) => {
|
const ChoiceFields = ({index,data}:{index:number , data :Choice }) => {
|
||||||
const formik = useFormikContext();
|
const formik = useFormikContext<any>();
|
||||||
|
|
||||||
const [t] = useTranslation()
|
const [t] = useTranslation()
|
||||||
|
|
||||||
|
const handleDeleteChoice = () => {
|
||||||
|
console.log(index);
|
||||||
|
console.log(formik.values.QuestionOptions[index]);
|
||||||
|
|
||||||
|
const updatedQuestionOptions = formik.values.QuestionOptions.filter((_:any, i:any) => i !== index);
|
||||||
|
|
||||||
|
formik.setFieldValue('QuestionOptions', updatedQuestionOptions);
|
||||||
|
};
|
||||||
|
console.log(formik.values);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='ChoiceFields'>
|
<div className='ChoiceFields'>
|
||||||
|
|
||||||
|
|
@ -20,7 +33,9 @@ const ChoiceFields = ({index,data}:{index:number , data :Choice }) => {
|
||||||
<File className="file_exercise" label={"attachment"} name={index} type="File" />
|
<File className="file_exercise" label={"attachment"} name={index} type="File" />
|
||||||
|
|
||||||
<CheckboxField className="" label="The_correct_answer" name={index} type="Checkbox" />
|
<CheckboxField className="" label="The_correct_answer" name={index} type="Checkbox" />
|
||||||
|
<p className="delete_question_options" >
|
||||||
|
<FaTrash onClick={handleDeleteChoice} size={17} />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ const File = ({
|
||||||
const { formik, t, isError,errorMsg } = useFormField(newName, props);
|
const { formik, t, isError,errorMsg } = useFormField(newName, props);
|
||||||
let imageUrl = formik?.values?.QuestionOptions[name]?.answer_image ?? null;
|
let imageUrl = formik?.values?.QuestionOptions[name]?.answer_image ?? null;
|
||||||
// console.log(imageUrl);
|
// console.log(imageUrl);
|
||||||
|
console.log(imageUrl);
|
||||||
|
|
||||||
const fileList: UploadFile[] = useMemo(() => {
|
const fileList: UploadFile[] = useMemo(() => {
|
||||||
if (!imageUrl) return [];
|
if (!imageUrl) return [];
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,16 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{formik?.values?.Questions?.[parent_index]?.QuestionOptions?.length < 5 && (
|
||||||
<p className="add_new_button" >
|
<p className="add_new_button" >
|
||||||
<FaCirclePlus onClick={()=> handleAddChoice(parent_index)} size={23} /> {t("header.add_new_choice")}
|
<FaCirclePlus onClick={()=> handleAddChoice(parent_index)} size={23} /> {t("header.add_new_choice")}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<DynamicTags parent_index={parent_index} />
|
<DynamicTags parent_index={parent_index} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,31 @@ import { getCharFromNumber } from '../../../../../utils/getCharFromNumber';
|
||||||
import CheckboxField from './CheckboxField';
|
import CheckboxField from './CheckboxField';
|
||||||
import TextField from './TextField';
|
import TextField from './TextField';
|
||||||
import File from './File';
|
import File from './File';
|
||||||
|
import { FaTrash } from 'react-icons/fa';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
const ChoiceFields = ({index,parent_index,data}:{index:number ,parent_index:number, data :Choice }) => {
|
const ChoiceFields = ({index,parent_index,data}:{index:number ,parent_index:number, data :Choice }) => {
|
||||||
const formik = useFormikContext();
|
const formik = useFormikContext<any>();
|
||||||
|
|
||||||
const [t] = useTranslation()
|
const [t] = useTranslation()
|
||||||
|
|
||||||
|
const handleDeleteChoice = () => {
|
||||||
|
const arrayLength = formik.values.Questions?.[parent_index].QuestionOptions?.length
|
||||||
|
|
||||||
|
console.log(arrayLength);
|
||||||
|
|
||||||
|
if(arrayLength === 1)
|
||||||
|
{
|
||||||
|
toast.error(t("validation.Sorry, the question must have at least one option"))
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const updatedQuestionOptions = formik.values.Questions?.[parent_index].QuestionOptions.filter((_:any, i:any) => i !== index);
|
||||||
|
formik.setFieldValue(`Questions[${parent_index}].QuestionOptions`, updatedQuestionOptions);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='ChoiceFields'>
|
<div className='ChoiceFields'>
|
||||||
|
|
||||||
|
|
@ -20,7 +40,9 @@ const ChoiceFields = ({index,parent_index,data}:{index:number ,parent_index:numb
|
||||||
<File className="file_exercise" label={"attachment"} name={index} type="File" parent_index={parent_index} />
|
<File className="file_exercise" label={"attachment"} name={index} type="File" parent_index={parent_index} />
|
||||||
|
|
||||||
<CheckboxField className="" label="The_correct_answer" name={index} type="Checkbox" parent_index={parent_index} />
|
<CheckboxField className="" label="The_correct_answer" name={index} type="Checkbox" parent_index={parent_index} />
|
||||||
|
<p className="delete_question_options" >
|
||||||
|
<FaTrash onClick={handleDeleteChoice} size={17} />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,10 +101,13 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{formik?.values?.Questions?.[parent_index]?.QuestionOptions?.length < 5 && (
|
||||||
<p className="add_new_button" >
|
<p className="add_new_button" >
|
||||||
<FaCirclePlus onClick={()=> handleAddChoice(parent_index)} size={23} /> {t("header.add_new_choice")}
|
<FaCirclePlus onClick={()=> handleAddChoice(parent_index)} size={23} /> {t("header.add_new_choice")}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
)}
|
||||||
|
|
||||||
<DynamicTags parent_index={parent_index} />
|
<DynamicTags parent_index={parent_index} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { Choice } from '../../../../../types/Item'
|
import { Choice } from '../../../../../types/Item'
|
||||||
import ValidationField from '../../../../../Components/ValidationField/ValidationField'
|
import ValidationField from '../../../../../Components/ValidationField/ValidationField'
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
|
|
@ -6,18 +6,40 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { getCharFromNumber } from '../../../../../utils/getCharFromNumber';
|
import { getCharFromNumber } from '../../../../../utils/getCharFromNumber';
|
||||||
import TextField from './TextField';
|
import TextField from './TextField';
|
||||||
import File from './File';
|
import File from './File';
|
||||||
|
import { FaTrash } from 'react-icons/fa';
|
||||||
|
import { useObjectToEdit } from '../../../../../zustand/ObjectToEditState';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
const QuestionFIeld = ({index,data}:{index:number , data :Choice }) => {
|
const QuestionFIeld = ({index,data}:{index:number , data :Choice }) => {
|
||||||
const formik = useFormikContext();
|
const formik = useFormikContext<any>();
|
||||||
console.log(index);
|
console.log(index);
|
||||||
|
const {set_DeletedQuestions,DeletedQuestions} = useObjectToEdit()
|
||||||
|
|
||||||
const [t] = useTranslation()
|
const [t] = useTranslation()
|
||||||
|
useEffect(() => {
|
||||||
|
set_DeletedQuestions([])
|
||||||
|
}, [window?.location.pathname])
|
||||||
|
|
||||||
|
const handleDeleteQuestion = () => {
|
||||||
|
|
||||||
|
const DeleteQuestionId = formik.values.Questions?.[index];
|
||||||
|
if(DeleteQuestionId?.id){
|
||||||
|
set_DeletedQuestions([...DeletedQuestions,DeleteQuestionId])
|
||||||
|
|
||||||
|
}
|
||||||
|
const updatedQuestionOptions = formik.values.Questions.filter((_:any, i:any) => i !== index);
|
||||||
|
formik.setFieldValue(`Questions`, updatedQuestionOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='ChoiceFields'>
|
<div className='ChoiceFields'>
|
||||||
|
|
||||||
<TextField className="textarea_exercise" placeholder={"choice"} label2={t(`input.question`)+ ` ` +`${index + 1}`} name={index} type="TextArea" />
|
<TextField className="textarea_exercise" placeholder={"choice"} label2={t(`input.question`)+ ` ` +`${index + 1}`} name={index} type="TextArea" />
|
||||||
<File className="file_exercise" label={"attachment"} name={index} type="File" />
|
<File className="file_exercise" label={"attachment"} name={index} type="File" />
|
||||||
|
<p className="delete_question_options" >
|
||||||
|
<FaTrash onClick={handleDeleteQuestion} size={17} />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,13 @@ export const useColumns = () => {
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) => record?.isBase === 1 ? t("practical.yes") : t ("practical.no"),
|
render: (text, record) => record?.isBase === 1 ? t("practical.yes") : t ("practical.no"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: `${t("columns.question_options_count")}`,
|
||||||
|
dataIndex: "name",
|
||||||
|
key: "name",
|
||||||
|
align: "center",
|
||||||
|
render: (text, record) => record?.question_options_count,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: can_add_Question ? (
|
title: can_add_Question ? (
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -119,3 +119,10 @@
|
||||||
.inputSmall{
|
.inputSmall{
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.delete_question_options{
|
||||||
|
margin-top: 25px;
|
||||||
|
color: var(--primary);
|
||||||
|
position: absolute;
|
||||||
|
left: 100px;
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
export const BaseURL = "http://192.168.1.108:8000/api/";
|
// export const BaseURL = "http://192.168.1.108:8000/api/";
|
||||||
// export const BaseURL = "http://127.0.0.1:8000/api/";
|
// export const BaseURL = "http://127.0.0.1:8000/api/";
|
||||||
|
|
||||||
// export const BaseURL = "https://school-back-dev.point-dev.net/api/";
|
export const BaseURL = "https://exercise-automation.point-dev.net/api/";
|
||||||
|
|
||||||
export const ImageBaseURL = "http://192.168.1.9:8000/";
|
export const ImageBaseURL = "http://192.168.1.9:8000/";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ export const Currency = "ل.س";
|
||||||
export const TOKEN_KEY = PROJECT_NAME + "_TOKEN";
|
export const TOKEN_KEY = PROJECT_NAME + "_TOKEN";
|
||||||
export const USER_KEY = PROJECT_NAME + "_USER";
|
export const USER_KEY = PROJECT_NAME + "_USER";
|
||||||
export const ABILITIES_KEY = PROJECT_NAME + "_ABILITIES";
|
export const ABILITIES_KEY = PROJECT_NAME + "_ABILITIES";
|
||||||
|
export const QUESTION_OBJECT_KEY = PROJECT_NAME + "_QUESTION";
|
||||||
|
|
||||||
export const TERM_OBJECT_KEY = PROJECT_NAME + "_OBJECT_TERM";
|
export const TERM_OBJECT_KEY = PROJECT_NAME + "_OBJECT_TERM";
|
||||||
export const BRANCH_OBJECT_KEY = PROJECT_NAME + "_OBJECT_BRANCH";
|
export const BRANCH_OBJECT_KEY = PROJECT_NAME + "_OBJECT_BRANCH";
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@
|
||||||
"some_thing_went_wrong": "حدث خطأ ما",
|
"some_thing_went_wrong": "حدث خطأ ما",
|
||||||
"Due_date_must_be_before_assigning_date": "يجب أن يكون تاريخ الاستحقاق بعد تاريخ التعيين",
|
"Due_date_must_be_before_assigning_date": "يجب أن يكون تاريخ الاستحقاق بعد تاريخ التعيين",
|
||||||
"grade_to_pass_must_be_less_than_max_grade": "يجب أن تكون درجة النجاح أقل من الحد الأقصى للدرجة",
|
"grade_to_pass_must_be_less_than_max_grade": "يجب أن تكون درجة النجاح أقل من الحد الأقصى للدرجة",
|
||||||
"max_mark_must_be_greater_than_min_mark_to_pass":"يجب ان تكون اكبر من علامة النجاح"
|
"max_mark_must_be_greater_than_min_mark_to_pass":"يجب ان تكون اكبر من علامة النجاح",
|
||||||
|
"Sorry, the question must have at least one option":"عذرًا، يجب أن يحتوي السؤال على خيار واحد على الأقل"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"register_students": "تسجيل الطلاب",
|
"register_students": "تسجيل الطلاب",
|
||||||
|
|
@ -151,7 +152,8 @@
|
||||||
"lesson_count":"عدد الدروس",
|
"lesson_count":"عدد الدروس",
|
||||||
"max_mark":"العلامة الكاملة",
|
"max_mark":"العلامة الكاملة",
|
||||||
"min_mark_to_pass" : "علامة النجاح",
|
"min_mark_to_pass" : "علامة النجاح",
|
||||||
"isBase":"سؤال رئيسي"
|
"isBase":"سؤال رئيسي",
|
||||||
|
"question_options_count":"عدد الخيارات"
|
||||||
},
|
},
|
||||||
"practical": {
|
"practical": {
|
||||||
"to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال",
|
"to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال",
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,7 @@ export interface Question {
|
||||||
min_mark_to_pass: number;
|
min_mark_to_pass: number;
|
||||||
image: string | null;
|
image: string | null;
|
||||||
Questions?:any[]
|
Questions?:any[]
|
||||||
|
question_options_count?:any
|
||||||
QuestionOptions: QuestionOption[];
|
QuestionOptions: QuestionOption[];
|
||||||
tags: tags[]; // Assuming tags are strings, adjust as per actual data type
|
tags: tags[]; // Assuming tags are strings, adjust as per actual data type
|
||||||
}
|
}
|
||||||
21
src/utils/cleanObject.ts
Normal file
21
src/utils/cleanObject.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
export function cleanObject(obj:any) {
|
||||||
|
// Create a new object to store the cleaned data
|
||||||
|
let cleanedObj = {} as any;
|
||||||
|
|
||||||
|
// Iterate over each property in the input object
|
||||||
|
for (let key in obj) {
|
||||||
|
// Check if the property value is not null, an empty string, or an empty array
|
||||||
|
if (
|
||||||
|
obj[key] !== null &&
|
||||||
|
obj[key] !== undefined &&
|
||||||
|
obj[key] !== "" &&
|
||||||
|
!(Array.isArray(obj[key]) && obj[key].length === 0)
|
||||||
|
) {
|
||||||
|
// Add the property to the cleaned object
|
||||||
|
cleanedObj[key] = obj[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the cleaned object
|
||||||
|
return cleanedObj;
|
||||||
|
}
|
||||||
4
src/utils/hasItems.ts
Normal file
4
src/utils/hasItems.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
export function hasItems(obj:any) {
|
||||||
|
// Check if the object has any properties
|
||||||
|
return Object.keys(obj).length > 0;
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,11 @@ interface ModelState {
|
||||||
set_isBseQuestion: (data: any) => void;
|
set_isBseQuestion: (data: any) => void;
|
||||||
Success: boolean;
|
Success: boolean;
|
||||||
set_Success: (data: any) => void;
|
set_Success: (data: any) => void;
|
||||||
|
DeletedQuestions: any;
|
||||||
|
set_DeletedQuestions: (data: any) => void;
|
||||||
|
|
||||||
|
SavedQuestionData: any;
|
||||||
|
set_SavedQuestionData: (data: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useObjectToEdit = create<ModelState>((set) => ({
|
export const useObjectToEdit = create<ModelState>((set) => ({
|
||||||
|
|
@ -44,4 +49,8 @@ export const useObjectToEdit = create<ModelState>((set) => ({
|
||||||
set_isBseQuestion: (data) => set(() => ({ isBseQuestion: data })),
|
set_isBseQuestion: (data) => set(() => ({ isBseQuestion: data })),
|
||||||
Success: false,
|
Success: false,
|
||||||
set_Success: (data) => set(() => ({ Success: data })),
|
set_Success: (data) => set(() => ({ Success: data })),
|
||||||
|
DeletedQuestions: [],
|
||||||
|
set_DeletedQuestions: (data) => set(() => ({ DeletedQuestions: data })),
|
||||||
|
SavedQuestionData: [],
|
||||||
|
set_SavedQuestionData: (data) => set(() => ({ SavedQuestionData: data })),
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user