add filter
This commit is contained in:
parent
c1e2718e14
commit
c08de08790
|
|
@ -2,6 +2,8 @@ import React, { useState, useEffect, useRef } from "react";
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { IoSearch } from "react-icons/io5";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { useFilterStateState } from "../../zustand/Filter";
|
||||
import { useDebounce } from "../../utils/useDebounce";
|
||||
|
||||
interface Props {
|
||||
placeholder: string;
|
||||
|
|
@ -11,36 +13,25 @@ interface Props {
|
|||
const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const DEBOUNCE_DELAY = 500; // Adjust the debounce delay as needed
|
||||
|
||||
useEffect(() => {
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
setSearchQuery(searchParams.get(searchBy) || "");
|
||||
}, [location.search, searchBy]);
|
||||
|
||||
const {setFilter} = useFilterStateState()
|
||||
|
||||
const handleInputChange = (value: string) => {
|
||||
setSearchQuery(value);
|
||||
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
if (value.trim() !== "") {
|
||||
navigate(`${location.pathname}?${searchBy}=${value.trim()}`);
|
||||
} else {
|
||||
const params = new URLSearchParams(location.search);
|
||||
params.delete(searchBy);
|
||||
navigate(`${location.pathname}`);
|
||||
}
|
||||
}, DEBOUNCE_DELAY);
|
||||
};
|
||||
|
||||
const handleInputChangeWithDebounce = useDebounce(
|
||||
(value: string) => {
|
||||
setFilter({
|
||||
name:value
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
const handleToggleDropdown = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
|
@ -69,7 +60,7 @@ const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => {
|
|||
className="search__input"
|
||||
placeholder={t(placeholder)}
|
||||
value={searchQuery}
|
||||
onChange={(e) => handleInputChange(e.target.value)}
|
||||
onChange={(e) => {handleInputChange(e.target.value) ; handleInputChangeWithDebounce(e.target.value)}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,54 +1,36 @@
|
|||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Divider, Select } from "antd";
|
||||
import SearchFieldWithSelect from "../../Components/DataTable/SearchFieldWithSelect";
|
||||
import { translateOptions } from "../../utils/translatedOptions";
|
||||
import { search_array } from "../../Routes";
|
||||
import { useFilterStateState } from "../../zustand/Filter";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { TbReorder } from "react-icons/tb";
|
||||
import { useFilterStateState } from "../../zustand/Filter";
|
||||
|
||||
const OrderBySelect = () => {
|
||||
const { t } = useTranslation();
|
||||
const { Filter, setFilter } = useFilterStateState();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const type_param = searchParams.get("type");
|
||||
const [type, setType] = useState(type_param);
|
||||
const translateArray = translateOptions(search_array, t);
|
||||
const {setFilter} = useFilterStateState()
|
||||
const handleChange = (value: string) => {
|
||||
const newArray = Filter?.filter((item: any) => item.select !== true);
|
||||
setFilter([
|
||||
...newArray,
|
||||
{ name: value, index: Filter.length, select: true },
|
||||
]);
|
||||
if (type_param) {
|
||||
searchParams.delete("type");
|
||||
setSearchParams(searchParams);
|
||||
}
|
||||
setType(value);
|
||||
setFilter({
|
||||
sort_by:value
|
||||
})
|
||||
};
|
||||
|
||||
// send this with api request
|
||||
// type: type,
|
||||
// page: currentPage,
|
||||
return (
|
||||
<div className="order_by_filter">
|
||||
<Select
|
||||
className="order_by_select"
|
||||
style={{ width: 200 }}
|
||||
size="large"
|
||||
allowClear
|
||||
placeholder={
|
||||
<div>
|
||||
<TbReorder className="addition_select_icon" /> {t("ترتيب حسب")}{" "}
|
||||
<TbReorder className="addition_select_icon" /> {t("header.sort_by")}{" "}
|
||||
</div>
|
||||
}
|
||||
onChange={handleChange}
|
||||
options={[
|
||||
{ value: "تصاعديا", label: t("تصاعديا") },
|
||||
{ value: "تنازليا", label: t("تنازليا") },
|
||||
{ value: "شوهدت مؤخرا", label: t("شوهدت مؤخرا") },
|
||||
{ value: "وصلت مؤخرا", label: t("وصلت مؤخرا") },
|
||||
{ value: "ascending", label: t("select.array.order.ascending") },
|
||||
{ value: "descending", label: t("select.array.order.descending") },
|
||||
{ value: "recently_viewed", label: t("select.array.order.recently_viewed") },
|
||||
{ value: "recently_arrived", label: t("select.array.order.recently_arrived") },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,36 +1,19 @@
|
|||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Divider, Select } from "antd";
|
||||
import SearchFieldWithSelect from "../../Components/DataTable/SearchFieldWithSelect";
|
||||
import { translateOptions } from "../../utils/translatedOptions";
|
||||
import { search_array } from "../../Routes";
|
||||
import { useFilterStateState } from "../../zustand/Filter";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import usePagination from "../../Layout/Dashboard/usePagination";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
|
||||
const PaginationColumn = () => {
|
||||
const { t } = useTranslation();
|
||||
const { Filter, setFilter } = useFilterStateState();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const type_param = searchParams.get("type");
|
||||
const [type, setType] = useState(type_param);
|
||||
const translateArray = translateOptions(search_array, t);
|
||||
const handleChange = (value: string) => {
|
||||
const newArray = Filter?.filter((item: any) => item.select !== true);
|
||||
setFilter([
|
||||
...newArray,
|
||||
{ name: value, index: Filter.length, select: true },
|
||||
]);
|
||||
if (type_param) {
|
||||
searchParams.delete("type");
|
||||
setSearchParams(searchParams);
|
||||
}
|
||||
setType(value);
|
||||
navigate(`?per_page=${value}`);
|
||||
};
|
||||
|
||||
// send this with api request
|
||||
// type: type,
|
||||
// page: currentPage,
|
||||
|
||||
return (
|
||||
<div className="pagination_column">
|
||||
<Select
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { ReactNode, useState } from "react";
|
||||
import React, { ReactNode, useEffect, useState } from "react";
|
||||
import { FaFilter } from "react-icons/fa";
|
||||
import { Form, Formik, FormikConfig, FormikHelpers } from "formik";
|
||||
import { Button, ButtonProps, Divider, Modal } from "antd";
|
||||
|
|
@ -10,6 +10,9 @@ import { QueryStatusEnum } from "../../../enums/QueryStatus";
|
|||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||
import FormikForm from "../../../Layout/Dashboard/FormikForm";
|
||||
import SpinContainer from "../../Layout/SpinContainer";
|
||||
import { TbFlagCancel } from "react-icons/tb";
|
||||
import { XFilled } from "@ant-design/icons";
|
||||
import { FaXmark } from "react-icons/fa6";
|
||||
|
||||
type OmitFormikProps = "children" | "initialValues" | "onSubmit";
|
||||
|
||||
|
|
@ -36,7 +39,6 @@ const useFilter = () => {
|
|||
const { filterState, setFilterState, clearFilterState } = useFilterState();
|
||||
const [t] = useTranslation();
|
||||
const [formValues, setFormValues] = useState({});
|
||||
const { setObjectToEdit } = useObjectToEdit();
|
||||
|
||||
// Define the type for the callback
|
||||
type SubmitCallback = () => void;
|
||||
|
|
@ -59,6 +61,10 @@ const useFilter = () => {
|
|||
</span>
|
||||
);
|
||||
};
|
||||
useEffect(() => {
|
||||
setFormValues({})
|
||||
setFilterState({})
|
||||
}, [])
|
||||
|
||||
const FilterBody = ({
|
||||
onSubmit,
|
||||
|
|
@ -67,7 +73,7 @@ const useFilter = () => {
|
|||
getValidationSchema,
|
||||
status,
|
||||
ModelClassName,
|
||||
width = "28vw",
|
||||
width = "500px",
|
||||
isLoading = false,
|
||||
setIsOpen,
|
||||
isOpen,
|
||||
|
|
@ -82,10 +88,17 @@ const useFilter = () => {
|
|||
Submit();
|
||||
setIsOpen("");
|
||||
};
|
||||
const handleCancel = () => {
|
||||
const handleCancel = (isCancel = false) => {
|
||||
|
||||
if(isCancel){
|
||||
setIsOpen("");
|
||||
return ;
|
||||
}
|
||||
|
||||
setIsOpen("");
|
||||
clearFilterState();
|
||||
setFormValues({});
|
||||
|
||||
};
|
||||
const handleOpen = () => {
|
||||
setIsOpen(true);
|
||||
|
|
@ -102,7 +115,7 @@ const useFilter = () => {
|
|||
footer={null}
|
||||
open={isOpen}
|
||||
onOk={handleOpen}
|
||||
onCancel={handleCancel}
|
||||
onCancel={()=>{}}
|
||||
mask={false}
|
||||
style={{ position: "absolute", top: "31.4%", left: "16.7%" }}
|
||||
>
|
||||
|
|
@ -115,7 +128,7 @@ const useFilter = () => {
|
|||
>
|
||||
<Form>
|
||||
<div>
|
||||
<header>{t("models.filter")}</header>
|
||||
<header> {t("models.filter")} <FaXmark onClick={()=>handleCancel(true)} /> </header>
|
||||
<Divider />
|
||||
<main className="main_modal">
|
||||
{isLoading ? <SpinContainer /> : children}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next";
|
|||
import { GoArrowSwitch } from "react-icons/go";
|
||||
import { useObjectToEdit } from "../../zustand/ObjectToEditState";
|
||||
import { QUESTION_OBJECT_KEY } from "../../config/AppKey";
|
||||
import { Popover } from "antd";
|
||||
import { CombinationKeyEnum } from "../../enums/CombinationKeyEnum";
|
||||
|
||||
const Header = () => {
|
||||
const [t] = useTranslation();
|
||||
|
|
@ -24,10 +26,23 @@ const Header = () => {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
const content = (
|
||||
<div>
|
||||
<p> (CTRL + SHIFT + {CombinationKeyEnum.CHOICE}) {t("header.add_choice")} </p>
|
||||
<p> (CTRL + SHIFT + {CombinationKeyEnum.QUESTION}) {t("header.add_question")} </p>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<header className="exercise_add_header mb-4">
|
||||
<article>
|
||||
|
||||
|
||||
<Popover content={content} title={t("practical.Abbreviations")}>
|
||||
<img src="/Icon/QuestionIcon.svg" alt="" />
|
||||
</Popover>
|
||||
|
||||
<div>
|
||||
{t("practical.add")} {t("models.exercise")}{" "}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ import BaseForm from "./Model/Malty/Form";
|
|||
import ModelForm from "./Model/ModelForm";
|
||||
const AcceptModal = lazy(() => import("./Model/AcceptModal"));
|
||||
|
||||
import { useModalState } from "../../../zustand/Modal";
|
||||
const AddPage: React.FC = () => {
|
||||
const { isSuccess: isSuccessAsync, mutateAsync } = useAddQuestionAsync();
|
||||
const { mutate, isSuccess, isLoading } = useAddQuestion();
|
||||
|
||||
const { mutateAsync } = useAddQuestionAsync();
|
||||
const { mutate, isLoading } = useAddQuestion();
|
||||
const {
|
||||
isBseQuestion,
|
||||
setTagsSearch,
|
||||
|
|
@ -107,41 +107,10 @@ const AddPage: React.FC = () => {
|
|||
};
|
||||
|
||||
const navigate = useNavigate();
|
||||
// console.log(SavedQuestionData);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (
|
||||
// isSuccessAsync &&
|
||||
// (SavedQuestionData?.Questions?.length > 0 ? isSuccess : true)
|
||||
// ) {
|
||||
// setObjectToEdit(null);
|
||||
// setSuccess(true);
|
||||
// localStorage.removeItem(QUESTION_OBJECT_KEY);
|
||||
// }
|
||||
// if (isSuccess && !SavedQuestionData?.Questions?.length) {
|
||||
// toast.success(t("validation.the_possess_done_successful"));
|
||||
// setObjectToEdit(null);
|
||||
// setSuccess(true);
|
||||
// localStorage.removeItem(QUESTION_OBJECT_KEY);
|
||||
// }
|
||||
// }, [isSuccess, isSuccessAsync]);
|
||||
|
||||
// let cleanedAnswers = cleanObject(SavedQuestionData);
|
||||
// let noChange = hasItems(cleanedAnswers);
|
||||
// console.log(SavedQuestionData);
|
||||
|
||||
// useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||
|
||||
// const SavedData = getLocalStorageQuestions(QUESTION_OBJECT_KEY);
|
||||
// console.log(SavedData);
|
||||
|
||||
const handleCancel = () => {
|
||||
navigate(-1);
|
||||
// if (!noChange) {
|
||||
// localStorage.removeItem(QUESTION_OBJECT_KEY);
|
||||
// } else {
|
||||
// setIsOpen(ModalEnum?.QUESTION_ACCEPT);
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,138 +0,0 @@
|
|||
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";
|
||||
|
||||
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">
|
||||
<div className="exercise_form">
|
||||
<ValidationField
|
||||
className="textarea_exercise"
|
||||
name="content"
|
||||
label="main_question"
|
||||
type="TextArea"
|
||||
/>
|
||||
<ValidationField
|
||||
className="file_exercise"
|
||||
name="image"
|
||||
label="attachment"
|
||||
type="File"
|
||||
/>
|
||||
|
||||
{/* <div className="">
|
||||
<ValidationField name="max_mark" label="max_mark" type="Number" className="inputSmall" disabled />
|
||||
<ValidationField name="min_mark_to_pass" label="min_mark_to_pass" className="inputSmall" type="Number" />
|
||||
|
||||
</div> */}
|
||||
<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>
|
||||
)}
|
||||
|
||||
<DynamicTags parent_index={parent_index} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
)}
|
||||
|
||||
<p className="add_new_button">
|
||||
<FaCirclePlus onClick={handleAddQuestion} size={23} />{" "}
|
||||
{t("header.add_new_question")}
|
||||
</p>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
export default Form;
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
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 PdfUploader from "../../../../../Components/CustomFields/PdfUploader";
|
||||
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 { useGetAllQuestion } from "../../../../../api/Question";
|
||||
import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
|
||||
|
||||
const Form = () => {
|
||||
const formik = useFormikContext<any>();
|
||||
const { isOpen } = useModalState((state) => state);
|
||||
// const {data} = useGetAllQuestion();
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen === "") {
|
||||
formik.setErrors({});
|
||||
formik.resetForm();
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
// console.log(formik?.errors);
|
||||
const [t] = useTranslation();
|
||||
|
||||
const handleAddChoice = (parent_index: number) => {
|
||||
console.log(parent_index);
|
||||
console.log(formik?.values?.Questions);
|
||||
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);
|
||||
};
|
||||
console.log(formik?.values);
|
||||
|
||||
return (
|
||||
<Row className="w-100">
|
||||
<div className="exercise_form">
|
||||
<ValidationField
|
||||
className="textarea_exercise"
|
||||
name="content"
|
||||
label="main_question"
|
||||
type="TextArea"
|
||||
/>
|
||||
<ValidationField
|
||||
className="file_exercise"
|
||||
name="image"
|
||||
label="attachment"
|
||||
type="File"
|
||||
/>
|
||||
|
||||
{/* <div className="">
|
||||
<ValidationField name="max_mark" label="max_mark" type="Number" className="inputSmall" disabled />
|
||||
<ValidationField name="min_mark_to_pass" label="min_mark_to_pass" className="inputSmall" type="Number" />
|
||||
|
||||
</div> */}
|
||||
<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>
|
||||
|
||||
{(
|
||||
(formik?.values as any)?.Questions?.[parent_index]?.answers ||
|
||||
[]
|
||||
).map((item: Choice, index: number) => {
|
||||
return (
|
||||
<ChoiceFields
|
||||
key={index}
|
||||
parent_index={parent_index}
|
||||
index={index}
|
||||
data={item}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{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>
|
||||
)}
|
||||
|
||||
<DynamicTags parent_index={parent_index} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
)}
|
||||
|
||||
<p className="add_new_button">
|
||||
<FaCirclePlus onClick={handleAddQuestion} size={23} />{" "}
|
||||
{t("header.add_new_question")}
|
||||
</p>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
export default Form;
|
||||
|
|
@ -2,12 +2,9 @@ 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";
|
||||
|
|
@ -15,6 +12,7 @@ import ImageBoxField from "../../../../../Components/CustomFields/ImageBoxField/
|
|||
import MaltySelectTag from "./Tags/MaltySelectTag";
|
||||
import useKeyCombination from "../../../../../Hooks/useKeyCombination";
|
||||
import { CombinationKeyEnum } from "../../../../../enums/CombinationKeyEnum";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
const Form = () => {
|
||||
const formik = useFormikContext<any>();
|
||||
|
|
@ -34,7 +32,7 @@ const Form = () => {
|
|||
|
||||
// console.log(formik?.errors);
|
||||
|
||||
const handleAddChoice = (parent_index: number) => {
|
||||
const handleAddChoice = (parent_index: number,fromKeyCombination:boolean = false) => {
|
||||
console.log(parent_index);
|
||||
|
||||
formik.setFieldValue(`Questions.[${parent_index}].answers`, [
|
||||
|
|
@ -46,9 +44,13 @@ const Form = () => {
|
|||
isCorrect: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
if(fromKeyCombination){
|
||||
toast.success(t("header.new_choice_have_been_added"))
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddQuestion = () => {
|
||||
const handleAddQuestion = (fromKeyCombination:boolean = false) => {
|
||||
formik.setFieldValue("Questions", [
|
||||
...((formik?.values as any)?.Questions as Choice[]),
|
||||
|
||||
|
|
@ -67,18 +69,21 @@ const Form = () => {
|
|||
const max_mark = formik?.values?.max_mark + 1;
|
||||
|
||||
formik.setFieldValue("max_mark", max_mark);
|
||||
if(fromKeyCombination){
|
||||
toast.success(t("header.new_question_have_been_added"))
|
||||
}
|
||||
};
|
||||
const [t] = useTranslation();
|
||||
|
||||
|
||||
const lastQuestions = formik?.values?.Questions?.length -1 ;
|
||||
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE }, () => {
|
||||
handleAddChoice(lastQuestions)
|
||||
handleAddChoice(lastQuestions,true)
|
||||
});
|
||||
|
||||
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.QUESTION }, () => {
|
||||
|
||||
handleAddQuestion()
|
||||
handleAddQuestion(true)
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -141,7 +146,7 @@ const Form = () => {
|
|||
)}
|
||||
|
||||
<p className="add_new_button">
|
||||
<FaCirclePlus onClick={handleAddQuestion} size={23} />{" "}
|
||||
<FaCirclePlus onClick={()=>handleAddQuestion()} size={23} />{" "}
|
||||
{t("header.add_new_question")}
|
||||
</p>
|
||||
</Row>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import ImageBoxField from "../../../../Components/CustomFields/ImageBoxField/Ima
|
|||
import SelectTag from "../../../../Components/CustomFields/SelectTag";
|
||||
import useKeyCombination from "../../../../Hooks/useKeyCombination";
|
||||
import { CombinationKeyEnum } from "../../../../enums/CombinationKeyEnum";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
const Form = () => {
|
||||
const [t] = useTranslation();
|
||||
|
|
@ -31,7 +32,8 @@ const Form = () => {
|
|||
setSavedQuestionData(formik.values);
|
||||
}, [formik?.values]);
|
||||
|
||||
const handleAddChoice = () => {
|
||||
const handleAddChoice = (fromKeyCombination:boolean = false ) => {
|
||||
|
||||
formik.setFieldValue("answers", [
|
||||
...((formik?.values as any)?.answers as Choice[]),
|
||||
{
|
||||
|
|
@ -40,12 +42,17 @@ const Form = () => {
|
|||
isCorrect: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
if(fromKeyCombination){
|
||||
toast.success(t("header.new_choice_have_been_added"))
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE }, () => {
|
||||
|
||||
handleAddChoice()
|
||||
handleAddChoice(true)
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -65,7 +72,7 @@ const Form = () => {
|
|||
<Choices />
|
||||
{formik?.values?.answers?.length < 5 && (
|
||||
<p className="add_new_button">
|
||||
<FaCirclePlus onClick={handleAddChoice} size={23} />{" "}
|
||||
<FaCirclePlus onClick={()=>handleAddChoice()} size={23} />{" "}
|
||||
{t("header.add_new_choice")}
|
||||
</p>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,10 @@
|
|||
border-radius: 10px 10px 0 0;
|
||||
margin: 0 !important;
|
||||
box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.1);
|
||||
|
||||
img{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.inputSmall {
|
||||
width: 100px;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { useLocation } from "react-router-dom";
|
|||
import { PaginationParams } from "../utils/PaginationParams";
|
||||
import { filterParams } from "../utils/filterParams";
|
||||
import useAuthState from "../../zustand/AuthState";
|
||||
import { useFilterStateState } from "../../zustand/Filter";
|
||||
|
||||
function useGetQuery(
|
||||
KEY: string | string[],
|
||||
|
|
@ -12,7 +13,9 @@ function useGetQuery(
|
|||
options: any = {},
|
||||
) {
|
||||
const axios = useAxios();
|
||||
|
||||
const {Filter} = useFilterStateState()
|
||||
const sort_by = Filter?.sort_by ?? null;
|
||||
const name = Filter?.name ?? null;
|
||||
const { show, pagination, ...remainingParams } = params;
|
||||
|
||||
const location = useLocation();
|
||||
|
|
@ -20,8 +23,8 @@ function useGetQuery(
|
|||
const { page, per_page } = PaginationParams(location);
|
||||
|
||||
const paramToSend = pagination
|
||||
? { page: page, per_page: per_page, ...remainingParams }
|
||||
: { ...remainingParams };
|
||||
? { page: page, per_page: per_page, ...remainingParams , sort_by,name }
|
||||
: { ...remainingParams ,sort_by,name};
|
||||
|
||||
const filteredParams = filterParams(paramToSend);
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,12 @@
|
|||
"add": "إضافة",
|
||||
"notification": "الاشعارات",
|
||||
"change_language": "تغيير اللغة",
|
||||
"delete_question": "حذف السؤال"
|
||||
"delete_question": "حذف السؤال",
|
||||
"add_choice": "اضافة خيار",
|
||||
"add_question": "اضافة سؤال",
|
||||
"new_choice_have_been_added": "تم إضافة خيار جديد",
|
||||
"new_question_have_been_added": "تم إضافة سؤال جديد",
|
||||
"sort_by":"ترتيب حسب"
|
||||
},
|
||||
"columns": {
|
||||
"id": "الرقم التعريفي",
|
||||
|
|
@ -210,7 +215,8 @@
|
|||
"delete_this_item": "احذف العنصر",
|
||||
"reset": "اعادة تعيين",
|
||||
"next": "التالي",
|
||||
"prev": "السابق"
|
||||
"prev": "السابق",
|
||||
"Abbreviations": "الاختصارات"
|
||||
},
|
||||
"Table": {
|
||||
"header": "",
|
||||
|
|
@ -642,7 +648,6 @@
|
|||
"enums": {
|
||||
"first_term": "الفصل الأول",
|
||||
"second_term": "الفصل الثاني"
|
||||
}
|
||||
},
|
||||
"array": {
|
||||
"Period": {
|
||||
|
|
@ -672,8 +677,16 @@
|
|||
"warning": "تحذير",
|
||||
"appreciation": "تقدير",
|
||||
"alert": "تنبيه"
|
||||
},
|
||||
"order": {
|
||||
"ascending": "تصاعديا",
|
||||
"descending": "تنازليا",
|
||||
"recently_viewed": "شوهدت مؤخرا",
|
||||
"recently_arrived": "وصلت مؤخرا"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"sidebar": {
|
||||
"dashboard": "لوحة القيادة",
|
||||
"course": "الصفوف",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user