From b0bde770823ff691684f876a9de2763e5f64dad3 Mon Sep 17 00:00:00 2001 From: karimalden Date: Thu, 27 Jun 2024 12:47:33 +0300 Subject: [PATCH] QUESTION --- src/Components/ValidationField/View/File.tsx | 3 ++ src/Hooks/useSaveOnDisconnect.tsx | 33 +++++++++++++++++++ src/Layout/Dashboard/FormikFormModel.tsx | 1 + src/Pages/question/AddPage.tsx | 32 ++++++++++++++++-- src/Pages/question/EditPage.tsx | 29 +++++++++------- src/Pages/question/Model/AcceptModal.tsx | 5 +++ src/Pages/question/Model/Add.tsx | 7 ++-- src/Pages/question/Model/Edit.tsx | 2 +- .../question/Model/Field/ChoiceFields.tsx | 19 +++++++++-- src/Pages/question/Model/Field/File.tsx | 3 +- src/Pages/question/Model/Malty/Add.tsx | 10 ++++-- .../Model/Malty/ChoiceField/ChoiceFields.tsx | 26 +++++++++++++-- src/Pages/question/Model/Malty/Edit.tsx | 7 ++-- .../Malty/QuestionFIeld/QuestionFIeld.tsx | 28 ++++++++++++++-- src/Pages/question/useTableColumns.tsx | 8 ++++- src/Styles/Pages/exercise.scss | 7 ++++ src/api/config.ts | 4 +-- src/config/AppKey.ts | 1 + src/translate/ar.json | 6 ++-- src/types/Item.ts | 1 + src/utils/cleanObject.ts | 21 ++++++++++++ src/utils/hasItems.ts | 4 +++ src/zustand/ObjectToEditState.ts | 9 +++++ 23 files changed, 232 insertions(+), 34 deletions(-) create mode 100644 src/Hooks/useSaveOnDisconnect.tsx create mode 100644 src/utils/cleanObject.ts create mode 100644 src/utils/hasItems.ts diff --git a/src/Components/ValidationField/View/File.tsx b/src/Components/ValidationField/View/File.tsx index d0bbd2b..9e9758c 100644 --- a/src/Components/ValidationField/View/File.tsx +++ b/src/Components/ValidationField/View/File.tsx @@ -14,6 +14,9 @@ const File = ({ }: any) => { const { formik, t, isError,errorMsg } = useFormField(name, props); let imageUrl = formik?.values?.[name] ?? null; + console.log(imageUrl); + console.log(typeof imageUrl === 'string'); + const fileList: UploadFile[] = useMemo(() => { if (!imageUrl) return []; diff --git a/src/Hooks/useSaveOnDisconnect.tsx b/src/Hooks/useSaveOnDisconnect.tsx new file mode 100644 index 0000000..da2ae6c --- /dev/null +++ b/src/Hooks/useSaveOnDisconnect.tsx @@ -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; diff --git a/src/Layout/Dashboard/FormikFormModel.tsx b/src/Layout/Dashboard/FormikFormModel.tsx index 091a230..abe35f0 100644 --- a/src/Layout/Dashboard/FormikFormModel.tsx +++ b/src/Layout/Dashboard/FormikFormModel.tsx @@ -42,6 +42,7 @@ const FormikFormModel: React.FC = ({ formik.resetForm(); } }, [isOpen]); + return
{children}
; }} diff --git a/src/Pages/question/AddPage.tsx b/src/Pages/question/AddPage.tsx index a8e4be4..819c8f5 100644 --- a/src/Pages/question/AddPage.tsx +++ b/src/Pages/question/AddPage.tsx @@ -17,12 +17,17 @@ import { toast } from "react-toastify"; import AcceptModal from "./Model/AcceptModal"; import { useModalState } from "../../zustand/Modal"; 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 { 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() const {isBseQuestion,set_isBseQuestion} = useObjectToEdit() @@ -43,6 +48,8 @@ const AddPage: React.FC = () => { "isBase": 1, }; + + mutateAsync(newBseQuestion).then((data) => { const newBseQuestionId = (data as any)?.data?.id; const Questions = DataToSend?.Questions; @@ -72,17 +79,36 @@ const AddPage: React.FC = () => { if(isSuccess){ toast.success(t("validation.the_possess_done_successful")) set_object_to_edit(null) - set_Success(true) + set_Success(true) + localStorage.removeItem(QUESTION_OBJECT_KEY) } }, [isSuccess]) + let cleanedQuestionOptions = cleanObject(SavedQuestionData); + let noChange =hasItems(cleanedQuestionOptions) + + useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData); + + + const SavedData = {} as any + console.log(SavedData); const handleCancel = () => { - setIsOpen(ModalEnum?.QUESTION_ACCEPT); + if(!noChange){ + navigate(-1) + localStorage.removeItem(QUESTION_OBJECT_KEY) + + }else{ + + setIsOpen(ModalEnum?.QUESTION_ACCEPT); + } }; const [t] = useTranslation(); + + + if(isBseQuestion){ return (
diff --git a/src/Pages/question/EditPage.tsx b/src/Pages/question/EditPage.tsx index 321e05f..c9d5b90 100644 --- a/src/Pages/question/EditPage.tsx +++ b/src/Pages/question/EditPage.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from "react"; import { Modal, Spin } from "antd"; import FormikForm from "../../Layout/Dashboard/FormikFormModel"; 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 { useTranslation } from "react-i18next"; import { useNavigate, useParams } from "react-router-dom"; @@ -19,17 +19,17 @@ import { toast } from "react-toastify"; const EditPage: React.FC = () => { const {question_id,subject_id} = useParams() - const {isBseQuestion,set_isBseQuestion,set_Tags_search} = useObjectToEdit() + const {isBseQuestion,set_isBseQuestion,set_Tags_search,DeletedQuestions} = useObjectToEdit() const { mutate, isSuccess, isLoading } = useUpdateQuestion(); - const { mutate:AddQuestion} = useAddQuestion(); + const { mutate:DeleteQuestion} = useDeleteQuestion(); const {data,isLoading:dataLoading}= useGetAllQuestion({show:question_id}) const {data:Questions,isLoading:QuestionsDataLoading}= useGetAllQuestion({questionParentId:question_id}) const object_to_edit = {...data?.data,Questions:Questions?.data } ; - + useEffect(() => { if(object_to_edit?.isBase === 1 && isBseQuestion !== true){ @@ -45,7 +45,6 @@ const EditPage: React.FC = () => { console.log(DataToSend); if(isBseQuestion){ - console.log(1); const UpdateBseQuestion = { "id":DataToSend?.id, @@ -55,11 +54,18 @@ const EditPage: React.FC = () => { if( typeof UpdateBseQuestion?.image === "string"){ delete UpdateBseQuestion["image"] } - console.log(UpdateBseQuestion); - - mutate(UpdateBseQuestion) + console.log(DeletedQuestions,"DeletedQuestions"); + + mutate(UpdateBseQuestion) - const Questions = DataToSend?.Questions; + + DeletedQuestions?.map((item:any)=>{ + DeleteQuestion({id:item?.id}) + + }) + + + const Questions = DataToSend?.Questions; console.log(Questions,"Questions"); Questions?.map((item:Question)=>{ @@ -84,8 +90,9 @@ const EditPage: React.FC = () => { const QuestionOptions = { old: oldQuestionOptions, new: newQuestionOptions - }; - + } ; + console.log(QuestionOptions); + mutate({ ...updatedObject, QuestionOptions, diff --git a/src/Pages/question/Model/AcceptModal.tsx b/src/Pages/question/Model/AcceptModal.tsx index 37a7828..0e2b8b3 100644 --- a/src/Pages/question/Model/AcceptModal.tsx +++ b/src/Pages/question/Model/AcceptModal.tsx @@ -5,6 +5,7 @@ import { ModalEnum } from "../../../enums/Model"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; +import { QUESTION_OBJECT_KEY } from "../../../config/AppKey"; const AcceptModal: React.FC = () => { const { isOpen, setIsOpen } = useModalState((state) => state); @@ -12,8 +13,12 @@ const AcceptModal: React.FC = () => { const handleSubmit = () => { + localStorage.removeItem(QUESTION_OBJECT_KEY) console.log("Handle submit clicked"); + setIsOpen(""); + navigate(-1) + }; const handleCancel = () => { diff --git a/src/Pages/question/Model/Add.tsx b/src/Pages/question/Model/Add.tsx index a977876..676516e 100644 --- a/src/Pages/question/Model/Add.tsx +++ b/src/Pages/question/Model/Add.tsx @@ -15,7 +15,7 @@ import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; const Form = () => { const formik = useFormikContext(); - const{set_Success,Success} = useObjectToEdit() + const{set_Success,Success,set_SavedQuestionData} = useObjectToEdit() useEffect(() => { if (Success) { @@ -25,6 +25,9 @@ const Form = () => { } }, [Success]); +useEffect(() => { + set_SavedQuestionData(formik.values) +}, [formik?.values]) @@ -79,7 +82,7 @@ const Form = () => { } ) } - {formik?.values?.QuestionOptions?.length < 4 && ( + {formik?.values?.QuestionOptions?.length < 5 && (

{t("header.add_new_choice")}

diff --git a/src/Pages/question/Model/Edit.tsx b/src/Pages/question/Model/Edit.tsx index 565a5dc..3d93407 100644 --- a/src/Pages/question/Model/Edit.tsx +++ b/src/Pages/question/Model/Edit.tsx @@ -65,7 +65,7 @@ const Form = () => { } ) } - {formik?.values?.QuestionOptions?.length < 4 && ( + {formik?.values?.QuestionOptions?.length < 5 && (

{t("header.add_new_choice")}

diff --git a/src/Pages/question/Model/Field/ChoiceFields.tsx b/src/Pages/question/Model/Field/ChoiceFields.tsx index 864c0e3..84da61a 100644 --- a/src/Pages/question/Model/Field/ChoiceFields.tsx +++ b/src/Pages/question/Model/Field/ChoiceFields.tsx @@ -7,11 +7,24 @@ import { getCharFromNumber } from '../../../../utils/getCharFromNumber'; import CheckboxField from './CheckboxField'; import TextField from './TextField'; 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 formik = useFormikContext(); + const formik = useFormikContext(); 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 (
@@ -20,7 +33,9 @@ const ChoiceFields = ({index,data}:{index:number , data :Choice }) => { - +

+ +

) } diff --git a/src/Pages/question/Model/Field/File.tsx b/src/Pages/question/Model/Field/File.tsx index e02140f..e9e0dc6 100644 --- a/src/Pages/question/Model/Field/File.tsx +++ b/src/Pages/question/Model/Field/File.tsx @@ -18,7 +18,8 @@ const File = ({ const { formik, t, isError,errorMsg } = useFormField(newName, props); let imageUrl = formik?.values?.QuestionOptions[name]?.answer_image ?? null; // console.log(imageUrl); - + console.log(imageUrl); + const fileList: UploadFile[] = useMemo(() => { if (!imageUrl) return []; diff --git a/src/Pages/question/Model/Malty/Add.tsx b/src/Pages/question/Model/Malty/Add.tsx index dd1ab95..0079d89 100644 --- a/src/Pages/question/Model/Malty/Add.tsx +++ b/src/Pages/question/Model/Malty/Add.tsx @@ -107,9 +107,15 @@ const Form = () => { } ) } -

+ + {formik?.values?.Questions?.[parent_index]?.QuestionOptions?.length < 5 && ( +

handleAddChoice(parent_index)} size={23} /> {t("header.add_new_choice")} -

+

+ + )} + +
diff --git a/src/Pages/question/Model/Malty/ChoiceField/ChoiceFields.tsx b/src/Pages/question/Model/Malty/ChoiceField/ChoiceFields.tsx index 426850e..3c5a9f6 100644 --- a/src/Pages/question/Model/Malty/ChoiceField/ChoiceFields.tsx +++ b/src/Pages/question/Model/Malty/ChoiceField/ChoiceFields.tsx @@ -7,11 +7,31 @@ import { getCharFromNumber } from '../../../../../utils/getCharFromNumber'; import CheckboxField from './CheckboxField'; import TextField from './TextField'; 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 formik = useFormikContext(); + const formik = useFormikContext(); 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 (
@@ -20,7 +40,9 @@ const ChoiceFields = ({index,parent_index,data}:{index:number ,parent_index:numb - +

+ +

) } diff --git a/src/Pages/question/Model/Malty/Edit.tsx b/src/Pages/question/Model/Malty/Edit.tsx index dd26b22..12b27d7 100644 --- a/src/Pages/question/Model/Malty/Edit.tsx +++ b/src/Pages/question/Model/Malty/Edit.tsx @@ -101,9 +101,12 @@ const Form = () => { } ) } -

+ {formik?.values?.Questions?.[parent_index]?.QuestionOptions?.length < 5 && ( +

handleAddChoice(parent_index)} size={23} /> {t("header.add_new_choice")} -

+

+ + )} diff --git a/src/Pages/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx b/src/Pages/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx index 47ec2f1..5298496 100644 --- a/src/Pages/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx +++ b/src/Pages/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import { Choice } from '../../../../../types/Item' import ValidationField from '../../../../../Components/ValidationField/ValidationField' import { useFormikContext } from 'formik'; @@ -6,18 +6,40 @@ import { useTranslation } from 'react-i18next'; import { getCharFromNumber } from '../../../../../utils/getCharFromNumber'; import TextField from './TextField'; 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 formik = useFormikContext(); + const formik = useFormikContext(); console.log(index); + const {set_DeletedQuestions,DeletedQuestions} = useObjectToEdit() 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 (
- +

+ +

) } diff --git a/src/Pages/question/useTableColumns.tsx b/src/Pages/question/useTableColumns.tsx index 08ad6f4..1fc6158 100644 --- a/src/Pages/question/useTableColumns.tsx +++ b/src/Pages/question/useTableColumns.tsx @@ -79,7 +79,13 @@ export const useColumns = () => { align: "center", 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 ? (