add filter

This commit is contained in:
karimaldeen 2024-09-12 10:08:59 +03:00
parent c1e2718e14
commit c08de08790
14 changed files with 169 additions and 464 deletions

View File

@ -2,6 +2,8 @@ import React, { useState, useEffect, useRef } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { IoSearch } from "react-icons/io5"; import { IoSearch } from "react-icons/io5";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { useFilterStateState } from "../../zustand/Filter";
import { useDebounce } from "../../utils/useDebounce";
interface Props { interface Props {
placeholder: string; placeholder: string;
@ -11,36 +13,25 @@ interface Props {
const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => { const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState<string>(""); const [searchQuery, setSearchQuery] = useState<string>("");
const location = useLocation();
const navigate = useNavigate();
const inputRef = useRef<HTMLInputElement>(null); 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); const {setFilter} = useFilterStateState()
setSearchQuery(searchParams.get(searchBy) || "");
}, [location.search, searchBy]);
const handleInputChange = (value: string) => { const handleInputChange = (value: string) => {
setSearchQuery(value); 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 = () => { const handleToggleDropdown = () => {
setIsOpen(!isOpen); setIsOpen(!isOpen);
}; };
@ -69,7 +60,7 @@ const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => {
className="search__input" className="search__input"
placeholder={t(placeholder)} placeholder={t(placeholder)}
value={searchQuery} value={searchQuery}
onChange={(e) => handleInputChange(e.target.value)} onChange={(e) => {handleInputChange(e.target.value) ; handleInputChangeWithDebounce(e.target.value)}}
/> />
</div> </div>
</div> </div>

View File

@ -1,54 +1,36 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Divider, Select } from "antd"; 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 { TbReorder } from "react-icons/tb";
import { useFilterStateState } from "../../zustand/Filter";
const OrderBySelect = () => { const OrderBySelect = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { Filter, setFilter } = useFilterStateState(); const {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 handleChange = (value: string) => { const handleChange = (value: string) => {
const newArray = Filter?.filter((item: any) => item.select !== true); setFilter({
setFilter([ sort_by:value
...newArray, })
{ name: value, index: Filter.length, select: true },
]);
if (type_param) {
searchParams.delete("type");
setSearchParams(searchParams);
}
setType(value);
}; };
// send this with api request
// type: type,
// page: currentPage,
return ( return (
<div className="order_by_filter"> <div className="order_by_filter">
<Select <Select
className="order_by_select" className="order_by_select"
style={{ width: 200 }} style={{ width: 200 }}
size="large" size="large"
allowClear
placeholder={ placeholder={
<div> <div>
<TbReorder className="addition_select_icon" /> {t("ترتيب حسب")}{" "} <TbReorder className="addition_select_icon" /> {t("header.sort_by")}{" "}
</div> </div>
} }
onChange={handleChange} onChange={handleChange}
options={[ options={[
{ value: "تصاعديا", label: t("تصاعديا") }, { value: "ascending", label: t("select.array.order.ascending") },
{ value: "تنازليا", label: t("تنازليا") }, { value: "descending", label: t("select.array.order.descending") },
{ value: "شوهدت مؤخرا", label: t("شوهدت مؤخرا") }, { value: "recently_viewed", label: t("select.array.order.recently_viewed") },
{ value: "وصلت مؤخرا", label: t("وصلت مؤخرا") }, { value: "recently_arrived", label: t("select.array.order.recently_arrived") },
]} ]}
/> />
</div> </div>

View File

@ -1,36 +1,19 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Divider, Select } from "antd"; import { Divider, Select } from "antd";
import SearchFieldWithSelect from "../../Components/DataTable/SearchFieldWithSelect"; import usePagination from "../../Layout/Dashboard/usePagination";
import { translateOptions } from "../../utils/translatedOptions"; import { useNavigate } from "react-router-dom";
import { search_array } from "../../Routes";
import { useFilterStateState } from "../../zustand/Filter";
import { useSearchParams } from "react-router-dom";
const PaginationColumn = () => { const PaginationColumn = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { Filter, setFilter } = useFilterStateState(); const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();
const type_param = searchParams.get("type");
const [type, setType] = useState(type_param);
const translateArray = translateOptions(search_array, t);
const handleChange = (value: string) => { const handleChange = (value: string) => {
const newArray = Filter?.filter((item: any) => item.select !== true); navigate(`?per_page=${value}`);
setFilter([
...newArray,
{ name: value, index: Filter.length, select: true },
]);
if (type_param) {
searchParams.delete("type");
setSearchParams(searchParams);
}
setType(value);
}; };
// send this with api request
// type: type,
// page: currentPage,
return ( return (
<div className="pagination_column"> <div className="pagination_column">
<Select <Select

View File

@ -1,4 +1,4 @@
import React, { ReactNode, useState } from "react"; import React, { ReactNode, useEffect, useState } from "react";
import { FaFilter } from "react-icons/fa"; import { FaFilter } from "react-icons/fa";
import { Form, Formik, FormikConfig, FormikHelpers } from "formik"; import { Form, Formik, FormikConfig, FormikHelpers } from "formik";
import { Button, ButtonProps, Divider, Modal } from "antd"; import { Button, ButtonProps, Divider, Modal } from "antd";
@ -10,6 +10,9 @@ import { QueryStatusEnum } from "../../../enums/QueryStatus";
import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
import FormikForm from "../../../Layout/Dashboard/FormikForm"; import FormikForm from "../../../Layout/Dashboard/FormikForm";
import SpinContainer from "../../Layout/SpinContainer"; 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"; type OmitFormikProps = "children" | "initialValues" | "onSubmit";
@ -36,7 +39,6 @@ const useFilter = () => {
const { filterState, setFilterState, clearFilterState } = useFilterState(); const { filterState, setFilterState, clearFilterState } = useFilterState();
const [t] = useTranslation(); const [t] = useTranslation();
const [formValues, setFormValues] = useState({}); const [formValues, setFormValues] = useState({});
const { setObjectToEdit } = useObjectToEdit();
// Define the type for the callback // Define the type for the callback
type SubmitCallback = () => void; type SubmitCallback = () => void;
@ -59,6 +61,10 @@ const useFilter = () => {
</span> </span>
); );
}; };
useEffect(() => {
setFormValues({})
setFilterState({})
}, [])
const FilterBody = ({ const FilterBody = ({
onSubmit, onSubmit,
@ -67,7 +73,7 @@ const useFilter = () => {
getValidationSchema, getValidationSchema,
status, status,
ModelClassName, ModelClassName,
width = "28vw", width = "500px",
isLoading = false, isLoading = false,
setIsOpen, setIsOpen,
isOpen, isOpen,
@ -82,10 +88,17 @@ const useFilter = () => {
Submit(); Submit();
setIsOpen(""); setIsOpen("");
}; };
const handleCancel = () => { const handleCancel = (isCancel = false) => {
if(isCancel){
setIsOpen("");
return ;
}
setIsOpen(""); setIsOpen("");
clearFilterState(); clearFilterState();
setFormValues({}); setFormValues({});
}; };
const handleOpen = () => { const handleOpen = () => {
setIsOpen(true); setIsOpen(true);
@ -102,7 +115,7 @@ const useFilter = () => {
footer={null} footer={null}
open={isOpen} open={isOpen}
onOk={handleOpen} onOk={handleOpen}
onCancel={handleCancel} onCancel={()=>{}}
mask={false} mask={false}
style={{ position: "absolute", top: "31.4%", left: "16.7%" }} style={{ position: "absolute", top: "31.4%", left: "16.7%" }}
> >
@ -115,7 +128,7 @@ const useFilter = () => {
> >
<Form> <Form>
<div> <div>
<header>{t("models.filter")}</header> <header> {t("models.filter")} <FaXmark onClick={()=>handleCancel(true)} /> </header>
<Divider /> <Divider />
<main className="main_modal"> <main className="main_modal">
{isLoading ? <SpinContainer /> : children} {isLoading ? <SpinContainer /> : children}

View File

@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next";
import { GoArrowSwitch } from "react-icons/go"; import { GoArrowSwitch } from "react-icons/go";
import { useObjectToEdit } from "../../zustand/ObjectToEditState"; import { useObjectToEdit } from "../../zustand/ObjectToEditState";
import { QUESTION_OBJECT_KEY } from "../../config/AppKey"; import { QUESTION_OBJECT_KEY } from "../../config/AppKey";
import { Popover } from "antd";
import { CombinationKeyEnum } from "../../enums/CombinationKeyEnum";
const Header = () => { const Header = () => {
const [t] = useTranslation(); 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 ( return (
<header className="exercise_add_header mb-4"> <header className="exercise_add_header mb-4">
<article> <article>
<Popover content={content} title={t("practical.Abbreviations")}>
<img src="/Icon/QuestionIcon.svg" alt="" /> <img src="/Icon/QuestionIcon.svg" alt="" />
</Popover>
<div> <div>
{t("practical.add")} {t("models.exercise")}{" "} {t("practical.add")} {t("models.exercise")}{" "}
</div> </div>

View File

@ -20,10 +20,10 @@ 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"));
import { useModalState } from "../../../zustand/Modal";
const AddPage: React.FC = () => { const AddPage: React.FC = () => {
const { isSuccess: isSuccessAsync, mutateAsync } = useAddQuestionAsync();
const { mutate, isSuccess, isLoading } = useAddQuestion(); const { mutateAsync } = useAddQuestionAsync();
const { mutate, isLoading } = useAddQuestion();
const { const {
isBseQuestion, isBseQuestion,
setTagsSearch, setTagsSearch,
@ -107,41 +107,10 @@ const AddPage: React.FC = () => {
}; };
const navigate = useNavigate(); 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 = () => { const handleCancel = () => {
navigate(-1); navigate(-1);
// if (!noChange) {
// localStorage.removeItem(QUESTION_OBJECT_KEY);
// } else {
// setIsOpen(ModalEnum?.QUESTION_ACCEPT);
// }
}; };

View File

@ -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;

View File

@ -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;

View File

@ -2,12 +2,9 @@ import { Col, Row } from "reactstrap";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import ValidationField from "../../../../../Components/ValidationField/ValidationField"; import ValidationField from "../../../../../Components/ValidationField/ValidationField";
import { useFormikContext } from "formik"; import { useFormikContext } from "formik";
import { useModalState } from "../../../../../zustand/Modal";
import ChoiceFields from "./ChoiceField/ChoiceFields";
import { FaCirclePlus } from "react-icons/fa6"; import { FaCirclePlus } from "react-icons/fa6";
import { Choice } from "../../../../../types/Item"; import { Choice } from "../../../../../types/Item";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import DynamicTags from "./Tags/DynamicTags";
import QuestionFIeld from "./QuestionFIeld/QuestionFIeld"; import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState"; import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState";
import Choices from "./ChoiceField/Choices"; import Choices from "./ChoiceField/Choices";
@ -15,6 +12,7 @@ import ImageBoxField from "../../../../../Components/CustomFields/ImageBoxField/
import MaltySelectTag from "./Tags/MaltySelectTag"; import MaltySelectTag from "./Tags/MaltySelectTag";
import useKeyCombination from "../../../../../Hooks/useKeyCombination"; import useKeyCombination from "../../../../../Hooks/useKeyCombination";
import { CombinationKeyEnum } from "../../../../../enums/CombinationKeyEnum"; import { CombinationKeyEnum } from "../../../../../enums/CombinationKeyEnum";
import { toast } from "react-toastify";
const Form = () => { const Form = () => {
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
@ -34,7 +32,7 @@ const Form = () => {
// console.log(formik?.errors); // console.log(formik?.errors);
const handleAddChoice = (parent_index: number) => { const handleAddChoice = (parent_index: number,fromKeyCombination:boolean = false) => {
console.log(parent_index); console.log(parent_index);
formik.setFieldValue(`Questions.[${parent_index}].answers`, [ formik.setFieldValue(`Questions.[${parent_index}].answers`, [
@ -46,9 +44,13 @@ const Form = () => {
isCorrect: 0, isCorrect: 0,
}, },
]); ]);
if(fromKeyCombination){
toast.success(t("header.new_choice_have_been_added"))
}
}; };
const handleAddQuestion = () => { const handleAddQuestion = (fromKeyCombination:boolean = false) => {
formik.setFieldValue("Questions", [ formik.setFieldValue("Questions", [
...((formik?.values as any)?.Questions as Choice[]), ...((formik?.values as any)?.Questions as Choice[]),
@ -67,18 +69,21 @@ const Form = () => {
const max_mark = formik?.values?.max_mark + 1; const max_mark = formik?.values?.max_mark + 1;
formik.setFieldValue("max_mark", max_mark); formik.setFieldValue("max_mark", max_mark);
if(fromKeyCombination){
toast.success(t("header.new_question_have_been_added"))
}
}; };
const [t] = useTranslation(); const [t] = useTranslation();
const lastQuestions = formik?.values?.Questions?.length -1 ; const lastQuestions = formik?.values?.Questions?.length -1 ;
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE }, () => { useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE }, () => {
handleAddChoice(lastQuestions) handleAddChoice(lastQuestions,true)
}); });
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.QUESTION }, () => { useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.QUESTION }, () => {
handleAddQuestion() handleAddQuestion(true)
}); });
@ -141,7 +146,7 @@ const Form = () => {
)} )}
<p className="add_new_button"> <p className="add_new_button">
<FaCirclePlus onClick={handleAddQuestion} size={23} />{" "} <FaCirclePlus onClick={()=>handleAddQuestion()} size={23} />{" "}
{t("header.add_new_question")} {t("header.add_new_question")}
</p> </p>
</Row> </Row>

View File

@ -11,6 +11,7 @@ import ImageBoxField from "../../../../Components/CustomFields/ImageBoxField/Ima
import SelectTag from "../../../../Components/CustomFields/SelectTag"; import SelectTag from "../../../../Components/CustomFields/SelectTag";
import useKeyCombination from "../../../../Hooks/useKeyCombination"; import useKeyCombination from "../../../../Hooks/useKeyCombination";
import { CombinationKeyEnum } from "../../../../enums/CombinationKeyEnum"; import { CombinationKeyEnum } from "../../../../enums/CombinationKeyEnum";
import { toast } from "react-toastify";
const Form = () => { const Form = () => {
const [t] = useTranslation(); const [t] = useTranslation();
@ -31,7 +32,8 @@ const Form = () => {
setSavedQuestionData(formik.values); setSavedQuestionData(formik.values);
}, [formik?.values]); }, [formik?.values]);
const handleAddChoice = () => { const handleAddChoice = (fromKeyCombination:boolean = false ) => {
formik.setFieldValue("answers", [ formik.setFieldValue("answers", [
...((formik?.values as any)?.answers as Choice[]), ...((formik?.values as any)?.answers as Choice[]),
{ {
@ -40,12 +42,17 @@ const Form = () => {
isCorrect: 0, isCorrect: 0,
}, },
]); ]);
if(fromKeyCombination){
toast.success(t("header.new_choice_have_been_added"))
}
}; };
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE }, () => { useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE }, () => {
handleAddChoice() handleAddChoice(true)
}); });
@ -65,7 +72,7 @@ const Form = () => {
<Choices /> <Choices />
{formik?.values?.answers?.length < 5 && ( {formik?.values?.answers?.length < 5 && (
<p className="add_new_button"> <p className="add_new_button">
<FaCirclePlus onClick={handleAddChoice} size={23} />{" "} <FaCirclePlus onClick={()=>handleAddChoice()} size={23} />{" "}
{t("header.add_new_choice")} {t("header.add_new_choice")}
</p> </p>
)} )}

View File

@ -132,6 +132,10 @@
border-radius: 10px 10px 0 0; border-radius: 10px 10px 0 0;
margin: 0 !important; margin: 0 !important;
box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.1); box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.1);
img{
cursor: pointer;
}
} }
.inputSmall { .inputSmall {
width: 100px; width: 100px;

View File

@ -4,6 +4,7 @@ import { useLocation } from "react-router-dom";
import { PaginationParams } from "../utils/PaginationParams"; import { PaginationParams } from "../utils/PaginationParams";
import { filterParams } from "../utils/filterParams"; import { filterParams } from "../utils/filterParams";
import useAuthState from "../../zustand/AuthState"; import useAuthState from "../../zustand/AuthState";
import { useFilterStateState } from "../../zustand/Filter";
function useGetQuery( function useGetQuery(
KEY: string | string[], KEY: string | string[],
@ -12,7 +13,9 @@ function useGetQuery(
options: any = {}, options: any = {},
) { ) {
const axios = useAxios(); const axios = useAxios();
const {Filter} = useFilterStateState()
const sort_by = Filter?.sort_by ?? null;
const name = Filter?.name ?? null;
const { show, pagination, ...remainingParams } = params; const { show, pagination, ...remainingParams } = params;
const location = useLocation(); const location = useLocation();
@ -20,8 +23,8 @@ function useGetQuery(
const { page, per_page } = PaginationParams(location); const { page, per_page } = PaginationParams(location);
const paramToSend = pagination const paramToSend = pagination
? { page: page, per_page: per_page, ...remainingParams } ? { page: page, per_page: per_page, ...remainingParams , sort_by,name }
: { ...remainingParams }; : { ...remainingParams ,sort_by,name};
const filteredParams = filterParams(paramToSend); const filteredParams = filterParams(paramToSend);

View File

@ -110,7 +110,12 @@
"add": "إضافة", "add": "إضافة",
"notification": "الاشعارات", "notification": "الاشعارات",
"change_language": "تغيير اللغة", "change_language": "تغيير اللغة",
"delete_question": "حذف السؤال" "delete_question": "حذف السؤال",
"add_choice": "اضافة خيار",
"add_question": "اضافة سؤال",
"new_choice_have_been_added": "تم إضافة خيار جديد",
"new_question_have_been_added": "تم إضافة سؤال جديد",
"sort_by":"ترتيب حسب"
}, },
"columns": { "columns": {
"id": "الرقم التعريفي", "id": "الرقم التعريفي",
@ -210,7 +215,8 @@
"delete_this_item": "احذف العنصر", "delete_this_item": "احذف العنصر",
"reset": "اعادة تعيين", "reset": "اعادة تعيين",
"next": "التالي", "next": "التالي",
"prev": "السابق" "prev": "السابق",
"Abbreviations": "الاختصارات"
}, },
"Table": { "Table": {
"header": "", "header": "",
@ -642,7 +648,6 @@
"enums": { "enums": {
"first_term": "الفصل الأول", "first_term": "الفصل الأول",
"second_term": "الفصل الثاني" "second_term": "الفصل الثاني"
}
}, },
"array": { "array": {
"Period": { "Period": {
@ -672,8 +677,16 @@
"warning": "تحذير", "warning": "تحذير",
"appreciation": "تقدير", "appreciation": "تقدير",
"alert": "تنبيه" "alert": "تنبيه"
},
"order": {
"ascending": "تصاعديا",
"descending": "تنازليا",
"recently_viewed": "شوهدت مؤخرا",
"recently_arrived": "وصلت مؤخرا"
}
} }
}, },
"sidebar": { "sidebar": {
"dashboard": "لوحة القيادة", "dashboard": "لوحة القيادة",
"course": "الصفوف", "course": "الصفوف",