Quiz_dashboard/src/Pages/Admin/question/EditPage.tsx

419 lines
12 KiB
TypeScript

import React, { useEffect } from "react";
import { Checkbox, Modal, Popover, Spin } from "antd";
import {
getInitialValues,
getValidationSchema,
getInitialValuesBase,
getValidationSchemaBase,
processTags,
} from "./formUtil";
import {
useAddQuestion,
useDeleteQuestion,
useGetAllQuestion,
useUpdateQuestion,
} from "../../../api/Question";
import { useTranslation } from "react-i18next";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import { ParamsEnum } from "../../../enums/params";
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
import { removeStringKeys } from "../../../utils/removeStringKeys";
import SpinContainer from "../../../Components/Layout/SpinContainer";
import ModelForm from "./Model/ModelForm";
import BaseForm from "./Model/Malty/Form";
import { Question } from "../../../types/Item";
import { toast } from "react-toastify";
import { deletePathSegments } from "../../../utils/deletePathSegments";
import { Form, Formik } from "formik";
import { MdOutlineArrowForwardIos } from "react-icons/md";
import { SettingFilled } from "@ant-design/icons";
import { CheckboxProps } from "antd/lib";
const EditPage: React.FC = () => {
const { subject_id, lesson_id, question_id } = useParams<ParamsEnum>();
const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions , ShowHint,setShowHint } =
useObjectToEdit();
const { mutate, isSuccess, isLoading } = useUpdateQuestion();
const { mutate: DeleteQuestion } = useDeleteQuestion();
const { mutate: mutateAdd , isLoading:LoadingAsync } = useAddQuestion();
const { data, isLoading: dataLoading } = useGetAllQuestion({
show: question_id,
});
const { data: Questions, isLoading: QuestionsDataLoading } =
useGetAllQuestion({
parent_id: question_id,
});
const objectToEdit = { ...data?.data, Questions: Questions?.data };
useEffect(() => {
if (objectToEdit?.isBase && isBseQuestion !== true) {
setIsBseQuestion(true);
}
}, [objectToEdit?.isBase]);
const [t] = useTranslation();
const handleSubmit = (values: any) => {
const DataToSend = structuredClone(values);
setTagsSearch(null);
if (isBseQuestion) {
const UpdateBseQuestion = {
id: DataToSend?.id,
content: DataToSend?.content,
content_image: DataToSend?.content_image ?? "",
};
if (
typeof UpdateBseQuestion?.content_image === "string" &&
UpdateBseQuestion?.content_image !== ""
) {
delete UpdateBseQuestion["content_image"];
}
console.log(DeletedQuestions, "DeletedQuestions");
console.log(UpdateBseQuestion);
// mutate(UpdateBseQuestion);
DeletedQuestions?.map((item: any) => {
DeleteQuestion({ id: item?.id });
});
const Questions = DataToSend?.Questions;
console.log(Questions, "Questions");
Questions?.map((item: Question) => {
console.log(item);
if (item?.id) {
const itemToSend = structuredClone(item);
const keysToRemove = ["content_image"];
console.log(itemToSend,"itemToSend");
const updatedObject = removeStringKeys(itemToSend, keysToRemove);
console.log(updatedObject, "updatedObject");
const tags = processTags(updatedObject);
const oldAnswers = [] as any;
const newAnswers = [] as any;
if(updatedObject?.content_image === null){
updatedObject["content_image"] = ""
}
updatedObject?.answers?.forEach((item: any) => {
if (item?.id) {
if(item?.content_image === null){
item["content_image"] = ""
}
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
} else {
newAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
}
});
const answers = {
old: oldAnswers,
new: newAnswers,
};
const emptyTag = tags?.new?.length === 0 && tags?.old?.length === 0
const tagToSend = emptyTag ? "" : tags
mutate({
...updatedObject,
answers,
tags:tagToSend,
});
} else {
console.log(values?.id);
const tags = processTags(item);
console.log(item,"DataToSend");
console.log(tags,"tags");
mutateAdd({
...item,
subject_id: subject_id,
tags,
lessons_ids: [lesson_id],
parent_id: values?.id,
});
}
});
} else {
const keysToRemove = ["content_image"];
console.log(DataToSend);
const updatedObject = removeStringKeys(DataToSend, keysToRemove);
delete updatedObject["parent_id"];
const tags = processTags(updatedObject);
if (!values?.content_image) {
updatedObject["content_image"] = "";
}
const oldAnswers = [] as any;
const newAnswers = [] as any;
updatedObject?.answers?.forEach((item: any) => {
if (item?.id) {
console.log(item,"item");
const deletedImage = item?.content_image === null
if(deletedImage){
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0, content_image:"" });
}else{
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
}
} else {
newAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
}
});
const answers = {
old: oldAnswers,
new: newAnswers,
};
console.log(tags, "tags");
if (tags?.new?.length < 1 && tags?.old?.length < 1) {
mutate({ ...updatedObject, answers, tags: "" });
} else {
mutate({ ...updatedObject, answers, tags });
}
}
};
const location = useLocation();
const navigate = useNavigate();
const handleCancel = () => {
navigate(-1);
};
const handleValidateSingleQuestion = (values:any)=>{
const haveMoreThanOneAnswer = values?.answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
const content = values.content ;
const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ;
console.log(haveImageOrContent,"haveImageOrContent");
if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
if(!haveMoreThanOneAnswer){
toast.error(t("validation.it_should_have_more_than_one_answers")) ;
return false ;
}
if(!haveOneAnswerRight){
toast.error(t("validation.it_should_have_more_than_one_correct_answers")) ;
return false ;
}
if(haveImageOrContent){
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
return false
}
}
const handleValidateBaseQuestion = (values: any) => {
const haveAnswers = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
const content = Question.content ;
const content_image = Question.content_image ;
const haveContentOrContentImage = !!content || !!content_image ;
if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
//// answers
const answers = Question?.answers;
const haveAnswers = answers?.length > 0;
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
const haveOneAnswerRight =
haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
if (!haveAnswers) {
toast.error(t("validation.it_should_have_more_than_one_answers"));
return false;
}
if (!haveMoreThanOneAnswer) {
toast.error(t("validation.it_should_have_more_than_one_answers"));
return false;
}
if (!haveOneAnswerRight) {
toast.error(t("validation.it_should_have_more_than_one_correct_answers"));
return false;
}
if(haveImageOrContent){
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
return false
}
return true;
});
console.log(haveAnswers, "haveAnswers");
};
const handleNavigateToPage = () => {
const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, "");
navigate(cleanedUrl);
};
useEffect(() => {
if (isSuccess) {
toast.success(t("validation.the_possess_done_successful"));
navigate(deletePathSegments(location.pathname, 2));
}
}, [isSuccess]);
const onChange: CheckboxProps['onChange'] = (e) => {
setShowHint(e.target.checked);
};
const contentSetting = (
<div>
<Checkbox checked={ShowHint} onChange={onChange}>
{ t("header.show_hint")}
</Checkbox>
</div>
);
const Loading = LoadingAsync || isLoading
if (dataLoading || QuestionsDataLoading) {
return <SpinContainer />;
}
if (objectToEdit?.isBase) {
return (
<div className="QuestionPractical">
<header>
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.edit_question")}
</header>
<div className="exercise_add">
<Formik
onSubmit={handleSubmit}
initialValues={getInitialValuesBase(objectToEdit)}
validationSchema={getValidationSchemaBase}
enableReinitialize
>
{({ values,handleSubmit }) => (
<Form className="w-100">
<main className="w-100 exercise_add_main">
{/* <Header/> */}
<header className="exercise_add_header mb-4">
<div>
{t("practical.edit")} {t("models.exercise")}{" "}
</div>
<div className="SettingEdit">
<Popover trigger="click" content={contentSetting}>
<SettingFilled/>
</Popover>
<div>{t("header.exercise")}</div>
</div>
</header>
<BaseForm />
<div className="exercise_add_buttons">
<div onClick={handleCancel}>{t("practical.back")}</div>
<button disabled={Loading} className="relative" type="submit"
onClick={()=>{handleValidateBaseQuestion(values) ;handleSubmit(values)}}
onSubmit={()=>{handleValidateBaseQuestion(values) ;handleSubmit(values) }}
> {t("practical.edit")}
{Loading && (
<span className="Spinier_Div">
<Spin />
</span>
)}
</button>
</div>
</main>
</Form>
)}
</Formik>
</div>
</div>
);
}
return (
<div className="QuestionPractical">
<header>
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.edit_question")}
</header>
<div className="exercise_add">
<Formik
enableReinitialize={true}
initialValues={getInitialValues(objectToEdit)}
validationSchema={getValidationSchema}
onSubmit={(values) => {
handleSubmit(values);
}}
>
{({ values,handleSubmit , dirty }) => (
<Form className="w-100">
<main className="w-100 exercise_add_main">
{/* <Header/> */}
<header className="exercise_add_header mb-4">
<div>
{t("practical.edit")} {t("models.exercise")}{" "}
</div>
<div>{t("header.exercise")}</div>
</header>
<ModelForm />
<div className="exercise_add_buttons">
<div onClick={handleCancel}>{t("practical.back")}</div>
<button
disabled={Loading || !dirty}
className="relative"
onClick={()=>{handleValidateSingleQuestion(values) ;handleSubmit(values)}}
onSubmit={()=>{handleValidateSingleQuestion(values) ;handleSubmit(values) }}
type="submit"
> {t("practical.edit")}
{Loading && (
<span className="Spinier_Div">
<Spin />
</span>
)}
</button>
</div>
</main>
</Form>
)}
</Formik>
</div>
</div>
);
};
export default EditPage;