fix multy question
This commit is contained in:
parent
6e1e79465f
commit
4f944eab55
|
|
@ -3,14 +3,17 @@ import { Select, Spin } from 'antd';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useDebounce } from '../../utils/useDebounce';
|
import { useDebounce } from '../../utils/useDebounce';
|
||||||
import { useGetAllTag } from '../../api/tags';
|
import { useGetAllTag } from '../../api/tags';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
const SelectTag: React.FC = () => {
|
const SelectTag: React.FC = () => {
|
||||||
const [searchValue, setSearchValue] = useState<string>('');
|
const [searchValue, setSearchValue] = useState<string>('');
|
||||||
const [fieldValue, setFieldValue] = useState<string>('');
|
const [fieldValue, setFieldValue] = useState<string>('');
|
||||||
|
const formik = useFormikContext<any>()
|
||||||
const handleChange = (value: string[]) => {
|
const handleChange = (value: string[]) => {
|
||||||
|
formik.setFieldValue("tags",value)
|
||||||
setSearchValue('');
|
setSearchValue('');
|
||||||
setFieldValue('');
|
setFieldValue('');
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearch = useDebounce((value: string) => {
|
const handleSearch = useDebounce((value: string) => {
|
||||||
|
|
@ -35,9 +38,7 @@ const SelectTag: React.FC = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const options = data?.data ?? []
|
const options = data?.data ?? []
|
||||||
console.log(options,"options");
|
|
||||||
const additionalData = options?.length < 1 && searchValue.length > 1 && !isLoading ? [{id:`new_${searchValue}`,name:searchValue}] :[];
|
const additionalData = options?.length < 1 && searchValue.length > 1 && !isLoading ? [{id:`new_${searchValue}`,name:searchValue}] :[];
|
||||||
console.log(additionalData);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='SelectTag'>
|
<div className='SelectTag'>
|
||||||
|
|
@ -66,6 +67,7 @@ const SelectTag: React.FC = () => {
|
||||||
handleBlur();
|
handleBlur();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
value={formik?.values?.tags ?? []}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
import Header from "../../../Components/exercise/Header";
|
import Header from "../../../Components/exercise/Header";
|
||||||
import { Question } from "../../../types/Item";
|
import { Question } from "../../../types/Item";
|
||||||
import BaseForm from "./Model/Malty/Add";
|
import BaseForm from "./Model/Malty/Form";
|
||||||
import ModelForm from "./Model/ModelForm";
|
import ModelForm from "./Model/ModelForm";
|
||||||
const AcceptModal = lazy(() => import("./Model/AcceptModal"));
|
const AcceptModal = lazy(() => import("./Model/AcceptModal"));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { removeStringKeys } from "../../../utils/removeStringKeys";
|
import { removeStringKeys } from "../../../utils/removeStringKeys";
|
||||||
import SpinContainer from "../../../Components/Layout/SpinContainer";
|
import SpinContainer from "../../../Components/Layout/SpinContainer";
|
||||||
import ModelForm from "./Model/ModelForm";
|
import ModelForm from "./Model/ModelForm";
|
||||||
import BaseForm from "./Model/Malty/Edit";
|
import BaseForm from "./Model/Malty/Form";
|
||||||
import { Question } from "../../../types/Item";
|
import { Question } from "../../../types/Item";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import useSetPageTitle from "../../../Hooks/useSetPageTitle";
|
import useSetPageTitle from "../../../Hooks/useSetPageTitle";
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ import File from "./File";
|
||||||
import { FaTrash } from "react-icons/fa";
|
import { FaTrash } from "react-icons/fa";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import HintField from "./HintField";
|
import HintField from "./HintField";
|
||||||
|
import ImageBoxField from "../../../../../../Components/CustomFields/ImageBoxField/ImageBoxField";
|
||||||
|
import { GoTrash } from "react-icons/go";
|
||||||
|
|
||||||
const ChoiceFields = ({
|
const ChoiceFields = ({
|
||||||
index,
|
index,
|
||||||
|
|
@ -51,18 +53,15 @@ const ChoiceFields = ({
|
||||||
<TextField
|
<TextField
|
||||||
className="textarea_exercise"
|
className="textarea_exercise"
|
||||||
placeholder={"choice"}
|
placeholder={"choice"}
|
||||||
label2={t(`input.choice`) + ` ` + `(${getCharFromNumber(index)})`}
|
label2={t(`input.choice`) + ` ` + `( ${t(`alphabet.${getCharFromNumber(index)}`)} )`}
|
||||||
name={index}
|
name={index}
|
||||||
parent_index={parent_index}
|
parent_index={parent_index}
|
||||||
type="TextArea"
|
type="TextArea"
|
||||||
/>
|
/>
|
||||||
<File
|
|
||||||
className="file_exercise"
|
<ImageBoxField name={`Questions.${parent_index}.answers.${index}.answer_image`} />
|
||||||
label={"attachment"}
|
|
||||||
name={index}
|
<div className="answer_status">
|
||||||
type="File"
|
|
||||||
parent_index={parent_index}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<CheckboxField
|
<CheckboxField
|
||||||
className=""
|
className=""
|
||||||
|
|
@ -72,18 +71,23 @@ const ChoiceFields = ({
|
||||||
parent_index={parent_index}
|
parent_index={parent_index}
|
||||||
/>
|
/>
|
||||||
<p className="delete_question_options">
|
<p className="delete_question_options">
|
||||||
<FaTrash onClick={handleDeleteChoice} size={17} />
|
{t("header.delete_choice")}
|
||||||
|
<GoTrash className="trash_icon" onClick={handleDeleteChoice} size={17} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</div>
|
||||||
<HintField
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div className="exercise_form_width">
|
||||||
|
<ValidationField
|
||||||
className=" "
|
className=" "
|
||||||
|
placeholder="_"
|
||||||
|
name={`Questions.${parent_index}.answers.${index}.hint`}
|
||||||
label="hint"
|
label="hint"
|
||||||
placeholder="hint"
|
type="text"
|
||||||
name={index}
|
style={{ width: "100%" }}
|
||||||
|
|
||||||
parent_index={parent_index}
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
134
src/Pages/Admin/question/Model/Malty/Form.tsx
Normal file
134
src/Pages/Admin/question/Model/Malty/Form.tsx
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
import { Col, Row } from "reactstrap";
|
||||||
|
import React, { useEffect } from "react";
|
||||||
|
import ValidationField from "../../../../../Components/ValidationField/ValidationField";
|
||||||
|
import { useFormikContext } from "formik";
|
||||||
|
import { useModalState } from "../../../../../zustand/Modal";
|
||||||
|
import ChoiceFields from "./ChoiceField/ChoiceFields";
|
||||||
|
import { FaCirclePlus } from "react-icons/fa6";
|
||||||
|
import { Choice } from "../../../../../types/Item";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import DynamicTags from "./Tags/DynamicTags";
|
||||||
|
import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
|
||||||
|
import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState";
|
||||||
|
import Choices from "./ChoiceField/Choices";
|
||||||
|
import ImageBoxField from "../../../../../Components/CustomFields/ImageBoxField/ImageBoxField";
|
||||||
|
import MaltySelectTag from "./Tags/MaltySelectTag";
|
||||||
|
|
||||||
|
const Form = () => {
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
|
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (Success) {
|
||||||
|
formik.setErrors({});
|
||||||
|
formik.resetForm({ values: {} });
|
||||||
|
setSuccess(false);
|
||||||
|
}
|
||||||
|
}, [Success]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSavedQuestionData(formik.values);
|
||||||
|
}, [formik?.values]);
|
||||||
|
|
||||||
|
// console.log(formik?.errors);
|
||||||
|
|
||||||
|
const handleAddChoice = (parent_index: number) => {
|
||||||
|
console.log(parent_index);
|
||||||
|
|
||||||
|
formik.setFieldValue(`Questions.[${parent_index}].answers`, [
|
||||||
|
...((formik?.values as any)?.Questions?.[parent_index]
|
||||||
|
.answers as Choice[]),
|
||||||
|
|
||||||
|
{
|
||||||
|
answer: null,
|
||||||
|
answer_image: null,
|
||||||
|
isCorrect: 0,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddQuestion = () => {
|
||||||
|
formik.setFieldValue("Questions", [
|
||||||
|
...((formik?.values as any)?.Questions as Choice[]),
|
||||||
|
|
||||||
|
{
|
||||||
|
content: "",
|
||||||
|
image: "",
|
||||||
|
parent: "",
|
||||||
|
isBase: 0,
|
||||||
|
// max_mark: 1,
|
||||||
|
// min_mark_to_pass: 1,
|
||||||
|
answers: [{ answer: null, answer_image: null, isCorrect: 0 }],
|
||||||
|
tags: [],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const max_mark = formik?.values?.max_mark + 1;
|
||||||
|
|
||||||
|
formik.setFieldValue("max_mark", max_mark);
|
||||||
|
};
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row className="w-100 exercise_form_container">
|
||||||
|
<div className="exercise_form">
|
||||||
|
|
||||||
|
<ValidationField className="textarea_exercise" name="content" label="main_question" type="TextArea" />
|
||||||
|
<ImageBoxField name="image" />
|
||||||
|
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<div className=" flex "></div>
|
||||||
|
|
||||||
|
{((formik?.values as any)?.Questions || [])?.map(
|
||||||
|
(item: Choice, parent_index: number) => {
|
||||||
|
return (
|
||||||
|
<div key={parent_index}>
|
||||||
|
<div className="exercise_form">
|
||||||
|
<QuestionFIeld
|
||||||
|
key={parent_index}
|
||||||
|
index={parent_index}
|
||||||
|
data={item}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Choices parent_index={parent_index} />
|
||||||
|
|
||||||
|
{formik?.values?.Questions?.[parent_index]?.answers
|
||||||
|
?.length < 5 && (
|
||||||
|
<p className="add_new_button">
|
||||||
|
<FaCirclePlus
|
||||||
|
onClick={() => handleAddChoice(parent_index)}
|
||||||
|
size={23}
|
||||||
|
/>{" "}
|
||||||
|
{t("header.add_new_choice")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
<div className="exercise_form_width">
|
||||||
|
|
||||||
|
<ValidationField
|
||||||
|
className=" "
|
||||||
|
placeholder="_"
|
||||||
|
name={`answers.${parent_index}.hint`}
|
||||||
|
label="hint_question"
|
||||||
|
type="text"
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
|
<MaltySelectTag parent_index={parent_index} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
|
||||||
|
<p className="add_new_button">
|
||||||
|
<FaCirclePlus onClick={handleAddQuestion} size={23} />{" "}
|
||||||
|
{t("header.add_new_question")}
|
||||||
|
</p>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Form;
|
||||||
|
|
@ -11,6 +11,8 @@ import { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import CheckboxField from "./CheckboxField";
|
import CheckboxField from "./CheckboxField";
|
||||||
import HintField from "./HintField";
|
import HintField from "./HintField";
|
||||||
|
import ImageBoxField from "../../../../../../Components/CustomFields/ImageBoxField/ImageBoxField";
|
||||||
|
import { GoTrash } from "react-icons/go";
|
||||||
|
|
||||||
const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
|
|
@ -33,39 +35,36 @@ const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="d-c">
|
<>
|
||||||
|
|
||||||
|
<div className="exercise_forms">
|
||||||
<div className="ChoiceFields">
|
<div className="ChoiceFields">
|
||||||
<TextField
|
<TextField
|
||||||
className="textarea_exercise"
|
className="textarea_exercise"
|
||||||
placeholder={"choice"}
|
placeholder={"question"}
|
||||||
label2={t(`input.question`) + ` ` + `${index + 1}`}
|
label2={t(`input.question`) + ` ` + `( ${t(`alphabet.${getCharFromNumber(index)}`)} )`}
|
||||||
name={index}
|
name={index}
|
||||||
|
id={`question_${index + 1}`}
|
||||||
type="TextArea"
|
type="TextArea"
|
||||||
/>
|
/>
|
||||||
<File
|
|
||||||
className="file_exercise"
|
|
||||||
label={"attachment"}
|
|
||||||
name={index}
|
|
||||||
type="File"
|
|
||||||
/>
|
|
||||||
<CheckboxField
|
|
||||||
className="canAnswersBeShuffled"
|
|
||||||
label={"canAnswersBeShuffled"}
|
|
||||||
name={index}
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
<ImageBoxField name={`Questions.${index}.image`} />
|
||||||
|
|
||||||
|
<div className="answer_status">
|
||||||
|
|
||||||
<p className="delete_question_options">
|
<p className="delete_question_options">
|
||||||
<FaTrash onClick={handleDeleteQuestion} size={17} />
|
{t("header.delete_question")}
|
||||||
|
<GoTrash className="trash_icon" onClick={handleDeleteQuestion} size={17} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<HintField placeholder={"hint"} name={index} label="hint" id={`hint`} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
77
src/Pages/Admin/question/Model/Malty/Tags/MaltySelectTag.tsx
Normal file
77
src/Pages/Admin/question/Model/Malty/Tags/MaltySelectTag.tsx
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
import React, { useState, useMemo } from 'react';
|
||||||
|
import { Select, Spin } from 'antd';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { useDebounce } from '../../../../../../utils/useDebounce';
|
||||||
|
import { useGetAllTag } from '../../../../../../api/tags';
|
||||||
|
|
||||||
|
const MaltySelectTag = ({parent_index}:{parent_index:number}) => {
|
||||||
|
const [searchValue, setSearchValue] = useState<string>('');
|
||||||
|
const [fieldValue, setFieldValue] = useState<string>('');
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
|
const values = formik?.values?.Questions?.[parent_index]?.tags;
|
||||||
|
const handleChange = (value: string[]) => {
|
||||||
|
formik.setFieldValue(`Questions.[${parent_index}].tags`,value)
|
||||||
|
setSearchValue('');
|
||||||
|
setFieldValue('');
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = useDebounce((value: string) => {
|
||||||
|
setSearchValue(value);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleFieldChange = (value: string) => {
|
||||||
|
setFieldValue(value);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBlur = () => {
|
||||||
|
setSearchValue('');
|
||||||
|
setFieldValue('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data, isLoading } = useGetAllTag({
|
||||||
|
name: searchValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const options = data?.data ?? []
|
||||||
|
const additionalData = options?.length < 1 && searchValue.length > 1 && !isLoading ? [{id:`new_${searchValue}`,name:searchValue}] :[];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='SelectTag'>
|
||||||
|
|
||||||
|
<label htmlFor="">
|
||||||
|
{t("models.tag")}
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
mode="multiple"
|
||||||
|
allowClear
|
||||||
|
style={{ width: '100%' ,height:"40px"}}
|
||||||
|
placeholder=""
|
||||||
|
fieldNames={{ label: 'name', value: 'id' }}
|
||||||
|
onChange={handleChange}
|
||||||
|
options={[...options,...additionalData]}
|
||||||
|
filterOption={false}
|
||||||
|
loading={isLoading}
|
||||||
|
notFoundContent={isLoading ? <Spin /> : t("practical.not_found")}
|
||||||
|
onSearch={(value) => {
|
||||||
|
handleSearch(value);
|
||||||
|
handleFieldChange(value);
|
||||||
|
}}
|
||||||
|
searchValue={fieldValue}
|
||||||
|
onDropdownVisibleChange={(open) => {
|
||||||
|
if (!open) {
|
||||||
|
handleBlur();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={values ?? []}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MaltySelectTag;
|
||||||
|
|
@ -193,3 +193,7 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.exercise_forms{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
@ -109,7 +109,8 @@
|
||||||
"delete_choice": "حذف الخيار",
|
"delete_choice": "حذف الخيار",
|
||||||
"add": "إضافة",
|
"add": "إضافة",
|
||||||
"notification": "الاشعارات",
|
"notification": "الاشعارات",
|
||||||
"change_language": "تغيير اللغة"
|
"change_language": "تغيير اللغة",
|
||||||
|
"delete_question":"حذف السؤال"
|
||||||
},
|
},
|
||||||
"columns": {
|
"columns": {
|
||||||
"id": "الرقم التعريفي",
|
"id": "الرقم التعريفي",
|
||||||
|
|
@ -374,8 +375,8 @@
|
||||||
"id": "الرقم التعريفي",
|
"id": "الرقم التعريفي",
|
||||||
"icon": "الايقونة",
|
"icon": "الايقونة",
|
||||||
"answer_content":"نص السؤال",
|
"answer_content":"نص السؤال",
|
||||||
"hint":"شرح السؤال",
|
"hint":"شرح الاختيار",
|
||||||
"hint_question":"شرح الاختيار",
|
"hint_question":"شرح السؤال",
|
||||||
"_":""
|
"_":""
|
||||||
},
|
},
|
||||||
"select": {
|
"select": {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user