From 0586a88cabeb6a1194f5e95bb54ec3a7e3021f0e Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 11:55:13 +0300 Subject: [PATCH 01/12] add validation --- src/Hooks/useFormField.tsx | 1 + src/Layout/Dashboard/FormikFormModel.tsx | 1 + src/Pages/Admin/question/AddPage.tsx | 147 ++++++++++++------ src/Pages/Admin/question/EditPage.tsx | 107 +++++++++++-- .../question/Model/Field/ChoiceFields.tsx | 1 + src/Pages/Admin/question/Model/Malty/Form.tsx | 4 +- .../Model/Malty/Tags/MaltySelectTag.tsx | 4 - src/Pages/Admin/question/Model/ModelForm.tsx | 9 +- src/Pages/Admin/question/Model/formUtil.ts | 34 +++- src/Pages/Auth/FormField.tsx | 22 +-- src/Pages/Auth/LoginForm.tsx | 4 +- src/Pages/Auth/formutils.ts | 4 +- src/translate/ar.json | 4 +- 13 files changed, 242 insertions(+), 100 deletions(-) diff --git a/src/Hooks/useFormField.tsx b/src/Hooks/useFormField.tsx index 81a7f03..c136873 100644 --- a/src/Hooks/useFormField.tsx +++ b/src/Hooks/useFormField.tsx @@ -7,6 +7,7 @@ import { useEffect } from "react"; const useFormField = (name: string, props?: any) => { const [field, meta] = useField({ name, ...props }); + const { t } = useTranslation(); const formik = useFormikContext(); diff --git a/src/Layout/Dashboard/FormikFormModel.tsx b/src/Layout/Dashboard/FormikFormModel.tsx index 6019065..c12a9cc 100644 --- a/src/Layout/Dashboard/FormikFormModel.tsx +++ b/src/Layout/Dashboard/FormikFormModel.tsx @@ -29,6 +29,7 @@ const FormikFormModel: React.FC = ({ initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit} + > {(formik) => { useEffect(() => { diff --git a/src/Pages/Admin/question/AddPage.tsx b/src/Pages/Admin/question/AddPage.tsx index c632a2e..7f96a8d 100644 --- a/src/Pages/Admin/question/AddPage.tsx +++ b/src/Pages/Admin/question/AddPage.tsx @@ -19,6 +19,7 @@ import { Question } from "../../../types/Item"; import BaseForm from "./Model/Malty/Form"; import ModelForm from "./Model/ModelForm"; import { toast } from "react-toastify"; +import { Form, Formik } from "formik"; const AcceptModal = lazy(() => import("./Model/AcceptModal")); const AddPage: React.FC = () => { @@ -30,12 +31,7 @@ const AddPage: React.FC = () => { const [t] = useTranslation(); const { subject_id, lesson_id } = useParams(); - console.log(objectToEdit, "objectToEdit"); - - const handleSubmit = ( - values: any, - { resetForm }: { resetForm: () => void }, - ) => { + const handleSubmit = ( values: any) => { const DataToSend = structuredClone(values); setTagsSearch(null); console.log(1); @@ -95,17 +91,6 @@ const AddPage: React.FC = () => { }; }); - if (answers?.length > 0) { - const isValidAnswers = answers?.some( - (answer: any) => answer?.isCorrect === 1, - ); - console.log(!isValidAnswers); - - if (!isValidAnswers) { - toast.error(t("validation.at_least_one_answer_should_be_correct")); - return; - } - } const NewQuestion = { ...values, @@ -122,6 +107,54 @@ const AddPage: React.FC = () => { } }; + + const handleValidateSingleQuestion = (values:any)=>{ + const haveAnswers = values?.answers?.length > 0 ; + const haveMoreThanOneAnswer = haveAnswers && values?.answers?.length > 1; + const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true ) + if(!haveAnswers){ + 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 ; + } + + } + + const handleValidateBaseQuestion = (values: any) => { + const haveAnswers = values?.Questions?.every((Question: any, QuestionsIndex: number) => { + 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); + + 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; + } + + return true; + }); + + console.log(haveAnswers, "haveAnswers"); + }; + const navigate = useNavigate(); const handleCancel = () => { @@ -129,7 +162,6 @@ const AddPage: React.FC = () => { }; const Loading = LoadingAsync || isLoading useEffect(() => { - console.log("all api success"); if (isSuccess) { setSuccess(true); } @@ -137,19 +169,28 @@ const AddPage: React.FC = () => { if (isBseQuestion) { return ( + +
- + {({ values,handleSubmit }) => ( + +
{t("practical.back")}
-
- +
+ )} + }> @@ -169,29 +212,43 @@ const AddPage: React.FC = () => { } return (
- -
-
- + { + handleSubmit(values); + }} +> + {({ values,handleSubmit }) => ( +
+
+
+ -
-
{t("practical.back")}
- -
-
- + {Loading && ( + + + + )} + +
+ + + )} + + }> diff --git a/src/Pages/Admin/question/EditPage.tsx b/src/Pages/Admin/question/EditPage.tsx index 8535c6c..b68ccb7 100644 --- a/src/Pages/Admin/question/EditPage.tsx +++ b/src/Pages/Admin/question/EditPage.tsx @@ -25,6 +25,7 @@ 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"; const EditPage: React.FC = () => { const { subject_id, lesson_id, question_id } = useParams(); @@ -187,6 +188,54 @@ const EditPage: React.FC = () => { }; + const handleValidateSingleQuestion = (values:any)=>{ + const haveAnswers = values?.answers?.length > 0 ; + const haveMoreThanOneAnswer = haveAnswers && values?.answers?.length > 1; + const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true ) + if(!haveAnswers){ + 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 ; + } + +} + +const handleValidateBaseQuestion = (values: any) => { + const haveAnswers = values?.Questions?.every((Question: any, QuestionsIndex: number) => { + 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); + + 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; + } + + return true; + }); + + console.log(haveAnswers, "haveAnswers"); +}; + + useEffect(() => { if (isSuccess) { toast.success(t("validation.the_possess_done_successful")); @@ -202,12 +251,16 @@ const EditPage: React.FC = () => { if (objectToEdit?.isBase) { return (
- -
+ {({ values,handleSubmit }) => ( + +
+
{/*
*/}
@@ -218,8 +271,10 @@ const EditPage: React.FC = () => {
{t("practical.back")}
-
- +
+ )} + +
); } return (
- -
+ + { + handleSubmit(values); + }} +> + {({ values,handleSubmit }) => ( +
+
{/*
*/}
@@ -252,8 +316,13 @@ const EditPage: React.FC = () => {
{t("practical.back")}
-
- + +
+ )} +
+
); }; diff --git a/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx b/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx index 19c7003..7539165 100644 --- a/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx +++ b/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx @@ -39,6 +39,7 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => { name={index} id={`choice_${index + 1}`} type="TextArea" + /> diff --git a/src/Pages/Admin/question/Model/Malty/Form.tsx b/src/Pages/Admin/question/Model/Malty/Form.tsx index bad59e2..7bd2d90 100644 --- a/src/Pages/Admin/question/Model/Malty/Form.tsx +++ b/src/Pages/Admin/question/Model/Malty/Form.tsx @@ -86,6 +86,8 @@ const Form = () => { }, ); + + return (
@@ -99,7 +101,7 @@ const Form = () => {
-
+
{((formik?.values as any)?.Questions || [])?.map( (item: Choice, parent_index: number) => { diff --git a/src/Pages/Admin/question/Model/Malty/Tags/MaltySelectTag.tsx b/src/Pages/Admin/question/Model/Malty/Tags/MaltySelectTag.tsx index 18026d3..e140d88 100644 --- a/src/Pages/Admin/question/Model/Malty/Tags/MaltySelectTag.tsx +++ b/src/Pages/Admin/question/Model/Malty/Tags/MaltySelectTag.tsx @@ -41,14 +41,10 @@ const MaltySelectTag = ({ parent_index }: { parent_index: number }) => { ? [{ id: searchValue, name: searchValue }] : []; - console.log(options); const value = formik?.values?.Questions[parent_index]?.tags?.map( (item: any) => item?.id ?? item, ) ?? []; - console.log(formik?.values?.Questions[parent_index]); - - console.log(value); const AllOptions = [...options, ...additionalData]; diff --git a/src/Pages/Admin/question/Model/ModelForm.tsx b/src/Pages/Admin/question/Model/ModelForm.tsx index 483e1d8..2794d0d 100644 --- a/src/Pages/Admin/question/Model/ModelForm.tsx +++ b/src/Pages/Admin/question/Model/ModelForm.tsx @@ -20,7 +20,7 @@ const Form = () => { const handleAddChoice = (fromKeyCombination: boolean = false) => { formik.setFieldValue("answers", [ - ...((formik?.values as any)?.answers as Choice[]), + ...(formik?.values?.answers ?? []) , { content: null, content_image: null, @@ -42,13 +42,12 @@ const Form = () => { useEffect(() => { if (Success) { - formik?.setValues({}); - formik.setErrors({}); + formik.resetForm() setSuccess(false); - console.log(formik.errors); } }, [Success]); + return (
@@ -62,7 +61,7 @@ const Form = () => {
- {formik?.values?.answers?.length < 5 && ( + {(formik?.values?.answers === null || formik?.values?.answers === undefined || formik?.values?.answers?.length < 5) && (

handleAddChoice()} size={23} />{" "} {t("header.add_new_choice")} diff --git a/src/Pages/Admin/question/Model/formUtil.ts b/src/Pages/Admin/question/Model/formUtil.ts index 85d1cd9..0c4240a 100644 --- a/src/Pages/Admin/question/Model/formUtil.ts +++ b/src/Pages/Admin/question/Model/formUtil.ts @@ -6,7 +6,7 @@ export const getInitialValues = (objectToEdit: Question): any => { const tags = objectToEdit?.tags?.map((item: any, index: number) => { return { ...item }; }); - + return { id: objectToEdit?.id ?? null, content: objectToEdit?.content ?? "", @@ -16,7 +16,7 @@ export const getInitialValues = (objectToEdit: Question): any => { hint: objectToEdit?.hint ?? null, isBase: 0, parent_id: objectToEdit?.parent_id ?? "", - answers: objectToEdit?.answers ?? [], + answers: objectToEdit?.answers ?? null, tags: tags ?? [], }; }; @@ -32,6 +32,19 @@ export const getValidationSchema = () => { content_image: Yup.string().nullable(), isCorrect: Yup.boolean(), }), + ).min(2).nullable().test( + "at-least-one-correct", + "At least one answer must be correct", + (answers: any) => { + console.log(answers, "answers"); + if(answers === null){ + return true + } + return answers?.some( + (answer: any) => + answer?.isCorrect === true || answer?.isCorrect === 1, + ); + }, ), }); }; @@ -42,10 +55,18 @@ export const getInitialValuesBase = (objectToEdit: Question): any => { id: tag?.id, name: tag?.name, })); - console.log(item, "item"); + const newAnswers = item?.answers?.map((item:any)=>{ + return { + ...item, + content : item?.content ?? null + } + }) + console.log(newAnswers,"newAnswers"); + return { ...item, + answer:newAnswers, canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0, hint: objectToEdit?.hint ?? "", isBase: 0, @@ -53,7 +74,7 @@ export const getInitialValuesBase = (objectToEdit: Question): any => { }; }); - const questions = newQuestions ?? []; + const questions = newQuestions ?? [{answers:[]}]; return { id: objectToEdit?.id ?? null, @@ -84,12 +105,11 @@ export const getValidationSchemaBase = () => { answer_image: Yup.string().nullable(), isCorrect: Yup.boolean(), }), - ) + ).min(2) .test( "at-least-one-correct", "At least one answer must be correct", (answers: any) => { - console.log(answers, "answers"); return answers.some( (answer: any) => @@ -98,7 +118,7 @@ export const getValidationSchemaBase = () => { }, ), }), - ), + ).min(1), }); }; diff --git a/src/Pages/Auth/FormField.tsx b/src/Pages/Auth/FormField.tsx index 00181ca..28ec2d0 100644 --- a/src/Pages/Auth/FormField.tsx +++ b/src/Pages/Auth/FormField.tsx @@ -14,6 +14,7 @@ import { } from "../../config/AppKey"; import useFormatAuthDataToSelect from "../../utils/useFormatAuthDataToSelect"; import { useTranslation } from "react-i18next"; +import ValidationField from "../../Components/ValidationField/ValidationField"; type FormFieldType = { isLoading: boolean; @@ -25,22 +26,11 @@ const FormField = ({ isLoading }: FormFieldType) => {

{/* */}

{t("تسجيل الدخول إلى حسابك")}

-
- - -
-
+ + + + {/*
@@ -53,7 +43,7 @@ const FormField = ({ isLoading }: FormFieldType) => { className="passwordInput" size="large" /> -
+
*/}
diff --git a/src/Pages/Admin/question/Model/formUtil.ts b/src/Pages/Admin/question/Model/formUtil.ts index 0c4240a..5122ad5 100644 --- a/src/Pages/Admin/question/Model/formUtil.ts +++ b/src/Pages/Admin/question/Model/formUtil.ts @@ -32,7 +32,7 @@ export const getValidationSchema = () => { content_image: Yup.string().nullable(), isCorrect: Yup.boolean(), }), - ).min(2).nullable().test( + ).min(2).test( "at-least-one-correct", "At least one answer must be correct", (answers: any) => { @@ -111,6 +111,10 @@ export const getValidationSchemaBase = () => { "At least one answer must be correct", (answers: any) => { + if(answers === null){ + return true + } + return answers.some( (answer: any) => answer.isCorrect === true || answer.isCorrect === 1, diff --git a/src/Pages/Admin/question/Page.tsx b/src/Pages/Admin/question/Page.tsx index cc5d70f..244d272 100644 --- a/src/Pages/Admin/question/Page.tsx +++ b/src/Pages/Admin/question/Page.tsx @@ -11,7 +11,6 @@ import DeleteModels from "../../../Layout/Dashboard/DeleteModels"; import { ModalEnum } from "../../../enums/Model"; import { useGetAllSubject } from "../../../api/subject"; import { useGetAllGrade } from "../../../api/grade"; -import { useGetAllCurriculum } from "../../../api/curriculum"; import PageHeader from "../../../Layout/Dashboard/PageHeader"; import { ABILITIES_ENUM } from "../../../enums/abilities"; import { canAddQuestion } from "../../../utils/hasAbilityFn"; From cd89ad405b7d4db793f3329ca27c98b851859049 Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 14:52:14 +0300 Subject: [PATCH 04/12] add button for ux --- src/Components/exercise/Header.tsx | 25 +++++++++++++++++-- src/Pages/Admin/question/AddPage.tsx | 26 ++++++++++++++++--- src/Pages/Admin/question/EditPage.tsx | 22 ++++++++++++++++ src/Pages/Home/Dummy.tsx | 2 ++ src/Styles/Antd/Mix.scss | 7 +----- src/Styles/Pages/exercise.scss | 36 ++++++++++++++++++++++++++- src/translate/ar.json | 4 ++- 7 files changed, 109 insertions(+), 13 deletions(-) diff --git a/src/Components/exercise/Header.tsx b/src/Components/exercise/Header.tsx index 2914ff1..ffa1aec 100644 --- a/src/Components/exercise/Header.tsx +++ b/src/Components/exercise/Header.tsx @@ -4,14 +4,16 @@ 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 { Popconfirm, Popover } from "antd"; import { CombinationKeyEnum } from "../../enums/CombinationKeyEnum"; +import { PopconfirmProps } from "antd/lib"; const Header = () => { const [t] = useTranslation(); const { values, setFieldValue, setValues } = useFormikContext(); const { isBseQuestion, setIsBseQuestion } = useObjectToEdit(); const { setSavedQuestionData } = useObjectToEdit(); + const handleChange = () => { setSavedQuestionData(null); localStorage.removeItem(QUESTION_OBJECT_KEY); @@ -26,6 +28,14 @@ const Header = () => { } }; + const confirm: PopconfirmProps['onConfirm'] = (e) => { + console.log(e); + setTimeout(() => { + handleChange() + }, 500); + + }; + const content = (

@@ -52,7 +62,18 @@ const Header = () => {

- + {confirm()}} + defaultOpen={false} + + > + + + + {isBseQuestion || values?.isBase === 1 ? t("header.malty_exercise") : t("header.exercise")} diff --git a/src/Pages/Admin/question/AddPage.tsx b/src/Pages/Admin/question/AddPage.tsx index 5093148..8e22305 100644 --- a/src/Pages/Admin/question/AddPage.tsx +++ b/src/Pages/Admin/question/AddPage.tsx @@ -10,7 +10,7 @@ import { } from "./Model/formUtil"; import { useAddQuestion, useAddQuestionAsync } from "../../../api/Question"; import { useTranslation } from "react-i18next"; -import { useNavigate, useParams } from "react-router-dom"; +import { useLocation, useNavigate, useParams } from "react-router-dom"; import { ParamsEnum } from "../../../enums/params"; import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; @@ -20,9 +20,12 @@ import BaseForm from "./Model/Malty/Form"; import ModelForm from "./Model/ModelForm"; import { toast } from "react-toastify"; import { Form, Formik } from "formik"; +import { MdOutlineArrowForwardIos } from "react-icons/md"; const AcceptModal = lazy(() => import("./Model/AcceptModal")); const AddPage: React.FC = () => { + const location = useLocation(); + const { mutateAsync,isLoading:LoadingAsync } = useAddQuestionAsync(); const { mutate, isLoading, isSuccess } = useAddQuestion(); const { isBseQuestion, setTagsSearch, objectToEdit, setSuccess } = @@ -157,6 +160,10 @@ const AddPage: React.FC = () => { const navigate = useNavigate(); + const handleNavigateToPage = () => { + const cleanedUrl = location.pathname?.replace("/Question/add", ""); + navigate(cleanedUrl); + }; const handleCancel = () => { navigate(-1); }; @@ -169,8 +176,12 @@ const AddPage: React.FC = () => { if (isBseQuestion) { return ( - +
+
+ {t("header.add_new_question")} +
+
{
+
+ ); } + return ( -
+ +
+
+ {t("header.add_new_question")} +
+
{
+
); }; diff --git a/src/Pages/Admin/question/EditPage.tsx b/src/Pages/Admin/question/EditPage.tsx index b68ccb7..1de5f7b 100644 --- a/src/Pages/Admin/question/EditPage.tsx +++ b/src/Pages/Admin/question/EditPage.tsx @@ -26,6 +26,7 @@ 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"; const EditPage: React.FC = () => { const { subject_id, lesson_id, question_id } = useParams(); @@ -236,6 +237,11 @@ const handleValidateBaseQuestion = (values: any) => { }; +const handleNavigateToPage = () => { + const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, ""); + navigate(cleanedUrl); +}; + useEffect(() => { if (isSuccess) { toast.success(t("validation.the_possess_done_successful")); @@ -250,6 +256,13 @@ const handleValidateBaseQuestion = (values: any) => { } if (objectToEdit?.isBase) { return ( + + +
+
+ {t("header.edit_question")} +
+
{
+
); } + return ( + +
+
+ {t("header.edit_question")} +
{
+
+ ); }; diff --git a/src/Pages/Home/Dummy.tsx b/src/Pages/Home/Dummy.tsx index 85181c8..cbf55f7 100644 --- a/src/Pages/Home/Dummy.tsx +++ b/src/Pages/Home/Dummy.tsx @@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next"; import { ABILITIES_ENUM } from "../../enums/abilities"; import useSetPageTitle from "../../Hooks/useSetPageTitle"; import useFilter from "../../Components/FilterField/components/useFilter"; +import { Button, Popconfirm } from "antd"; const Dummy = () => { const [t] = useTranslation(); @@ -12,6 +13,7 @@ const Dummy = () => {
{/* karim */} +
); }; diff --git a/src/Styles/Antd/Mix.scss b/src/Styles/Antd/Mix.scss index 1f327c6..eaf8c3e 100644 --- a/src/Styles/Antd/Mix.scss +++ b/src/Styles/Antd/Mix.scss @@ -10,12 +10,7 @@ } } } - -.Popover { - .ant-popover-inner { - padding: 0 !important; - } -} +x .Color_type_checkbox.false { .ant-checkbox-checked .ant-checkbox-inner { diff --git a/src/Styles/Pages/exercise.scss b/src/Styles/Pages/exercise.scss index f0d4925..5e0736f 100644 --- a/src/Styles/Pages/exercise.scss +++ b/src/Styles/Pages/exercise.scss @@ -41,7 +41,7 @@ // padding: 2vw; .exercise_add_main { background: var(--bg); - padding: 2vw; + padding: 10px 2vw; } .exercise_add_buttons { display: flex; @@ -212,3 +212,37 @@ transform: translateY(55px); z-index: -1; } + + + +.ant-popconfirm .ant-popconfirm-buttons{ + display: flex; + align-items: center; + justify-content: center; + >{ + flex: 1; + min-height: auto; + min-width: 30px; + + } + .ant-btn{ + min-height: 30px !important; + max-height: 30px !important; + min-width: 50px; + padding: 5px !important; + display: flex; + align-items: center; + justify-content: center ; + + + } +} + +.QuestionPractical{ + display: flex; + flex-direction: column; + background: var(--bg); + >header{ + padding: 30px 2vw 10px 2vw; + } +} \ No newline at end of file diff --git a/src/translate/ar.json b/src/translate/ar.json index 281453e..1dbd029 100644 --- a/src/translate/ar.json +++ b/src/translate/ar.json @@ -125,7 +125,9 @@ "personal_information": "المعلومات الشخصية", "address": "العنوان", "attachment": "المرفق", - "subject_of_class": "مواد الصف" + "subject_of_class": "مواد الصف", + "this_will_un_do_all_your_changes":"سوف يؤدي هذا إلى إلغاء جميع تغييراتك", + "edit_question":"تعديل سؤال" }, "columns": { "id": "الرقم التعريفي", From 5c41a13cb19a82aa5fa233f33afeca783f703b09 Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 15:08:53 +0300 Subject: [PATCH 05/12] remove question drag and drop --- .../Admin/question/Model/Field/Choices.tsx | 18 ++++++++++--- .../Model/Malty/ChoiceField/Choices.tsx | 25 +++++++++++++++++-- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/Pages/Admin/question/Model/Field/Choices.tsx b/src/Pages/Admin/question/Model/Field/Choices.tsx index 61f575c..dfe7d95 100644 --- a/src/Pages/Admin/question/Model/Field/Choices.tsx +++ b/src/Pages/Admin/question/Model/Field/Choices.tsx @@ -36,12 +36,21 @@ const Choices = () => { }; return ( - + <> + {formik?.values?.answers?.map((item: Choice, index: number) => { + return ( +
+ +
+ ); + })} + + {/* {(provided) => (
{formik?.values?.answers?.map((item: Choice, index: number) => { - // Use a unique identifier for draggableId const draggableId = item.name ? item.name.toString() : `item-${index}`; @@ -67,11 +76,12 @@ const Choices = () => { ); })} - {provided.placeholder} {/* Placeholder for spacing */} + {provided.placeholder}
)}
-
+
*/} + ); }; diff --git a/src/Pages/Admin/question/Model/Malty/ChoiceField/Choices.tsx b/src/Pages/Admin/question/Model/Malty/ChoiceField/Choices.tsx index d84cd7c..af7cbf9 100644 --- a/src/Pages/Admin/question/Model/Malty/ChoiceField/Choices.tsx +++ b/src/Pages/Admin/question/Model/Malty/ChoiceField/Choices.tsx @@ -44,7 +44,28 @@ const Choices = ({ parent_index }: { parent_index: number }) => { return ( <> - + +
+ {( + (formik?.values as any)?.Questions?.[parent_index]?.answers || + [] + ).map((item: Choice, index: number) => { + return ( +
+ +
+ ); + })} + +
+ {/* {(provided) => (
@@ -87,7 +108,7 @@ const Choices = ({ parent_index }: { parent_index: number }) => {
)}
-
+
*/} ); }; From b1c5405ff71c38c16b7f782dce0d71c2dceac10c Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 15:17:40 +0300 Subject: [PATCH 06/12] fix validation --- src/Layout/Dashboard/DeleteModels.tsx | 2 +- src/Pages/Admin/question/AddPage.tsx | 6 +----- src/Pages/Admin/question/EditPage.tsx | 7 ++----- src/Pages/Admin/question/Model/formUtil.ts | 7 ------- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/Layout/Dashboard/DeleteModels.tsx b/src/Layout/Dashboard/DeleteModels.tsx index dc88705..dd9fed4 100644 --- a/src/Layout/Dashboard/DeleteModels.tsx +++ b/src/Layout/Dashboard/DeleteModels.tsx @@ -73,7 +73,7 @@ const DeleteModels: React.FC = ({ { const handleValidateSingleQuestion = (values:any)=>{ - const haveAnswers = values?.answers?.length > 0 ; - const haveMoreThanOneAnswer = haveAnswers && values?.answers?.length > 1; + const haveMoreThanOneAnswer = values?.answers?.length > 1; const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true ) - if(!haveAnswers){ - return false ; - } if(!haveMoreThanOneAnswer){ toast.error(t("validation.it_should_have_more_than_one_answers")) ; return false ; diff --git a/src/Pages/Admin/question/EditPage.tsx b/src/Pages/Admin/question/EditPage.tsx index 1de5f7b..c82a6af 100644 --- a/src/Pages/Admin/question/EditPage.tsx +++ b/src/Pages/Admin/question/EditPage.tsx @@ -190,12 +190,9 @@ const EditPage: React.FC = () => { const handleValidateSingleQuestion = (values:any)=>{ - const haveAnswers = values?.answers?.length > 0 ; - const haveMoreThanOneAnswer = haveAnswers && values?.answers?.length > 1; + const haveMoreThanOneAnswer = values?.answers?.length > 1; const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true ) - if(!haveAnswers){ - return false ; - } + if(!haveMoreThanOneAnswer){ toast.error(t("validation.it_should_have_more_than_one_answers")) ; return false ; diff --git a/src/Pages/Admin/question/Model/formUtil.ts b/src/Pages/Admin/question/Model/formUtil.ts index 5122ad5..bb129dd 100644 --- a/src/Pages/Admin/question/Model/formUtil.ts +++ b/src/Pages/Admin/question/Model/formUtil.ts @@ -37,9 +37,6 @@ export const getValidationSchema = () => { "At least one answer must be correct", (answers: any) => { console.log(answers, "answers"); - if(answers === null){ - return true - } return answers?.some( (answer: any) => answer?.isCorrect === true || answer?.isCorrect === 1, @@ -110,10 +107,6 @@ export const getValidationSchemaBase = () => { "at-least-one-correct", "At least one answer must be correct", (answers: any) => { - - if(answers === null){ - return true - } return answers.some( (answer: any) => From e981ce748198aa2abf69d09aa1bbbc477c749487 Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 15:21:43 +0300 Subject: [PATCH 07/12] add icon sidebar --- src/Pages/Admin/question/Model/formUtil.ts | 1 - src/Routes.tsx | 20 +++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Pages/Admin/question/Model/formUtil.ts b/src/Pages/Admin/question/Model/formUtil.ts index bb129dd..dc19acd 100644 --- a/src/Pages/Admin/question/Model/formUtil.ts +++ b/src/Pages/Admin/question/Model/formUtil.ts @@ -36,7 +36,6 @@ export const getValidationSchema = () => { "at-least-one-correct", "At least one answer must be correct", (answers: any) => { - console.log(answers, "answers"); return answers?.some( (answer: any) => answer?.isCorrect === true || answer?.isCorrect === 1, diff --git a/src/Routes.tsx b/src/Routes.tsx index fcd53d0..409c91c 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -1,5 +1,5 @@ import { TCrudRoute, TMenuItem } from "./types/App"; -import { FaHome, FaMoneyBill, FaSellcast } from "react-icons/fa"; +import { FaCashRegister, FaHome, FaMoneyBill, FaPaperclip, FaSellcast, FaTag, FaUser } from "react-icons/fa"; import React from "react"; const Dummy = React.lazy(() => import("./Pages/Home/Dummy")); @@ -43,12 +43,14 @@ import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "./enums/abilities"; import { ParamsEnum } from "./enums/params"; import { TbCategory } from "react-icons/tb"; import { UserTypeEnum } from "./enums/UserType"; +import { FaTags } from "react-icons/fa6"; +import { MdGrade } from "react-icons/md"; export const menuItems: TMenuItem[] = [ { header: "page_header.dashboard", element: , - icon: , + icon: , text: "sidebar.dashboard", path: "/", abilities: ABILITIES_ENUM?.PASS, @@ -59,7 +61,7 @@ export const menuItems: TMenuItem[] = [ { header: "page_header.grade", element: , - icon: , + icon: , text: "sidebar.grade", path: `/${ABILITIES_ENUM?.GRADE}`, abilities: ABILITIES_ENUM?.GRADE, @@ -69,7 +71,7 @@ export const menuItems: TMenuItem[] = [ { header: "page_header.tags", element: , - icon: , + icon: , text: "sidebar.tags", path: `/${ABILITIES_ENUM?.TAG}`, abilities: ABILITIES_ENUM?.TAG, @@ -77,9 +79,9 @@ export const menuItems: TMenuItem[] = [ prevPath: 0, }, { - header: "page_header.tags", + header: "page_header.report", element: , - icon: , + icon: , text: "sidebar.report", path: `/${ABILITIES_ENUM?.Report}`, abilities: ABILITIES_ENUM?.Report, @@ -89,7 +91,7 @@ export const menuItems: TMenuItem[] = [ { header: "page_header.student", element: , - icon: , + icon: , text: "sidebar.student", path: `/${ABILITIES_ENUM?.STUDENT}`, abilities: ABILITIES_ENUM?.STUDENT, @@ -99,7 +101,7 @@ export const menuItems: TMenuItem[] = [ { header: "page_header.reSeller", element: , - icon: , + icon: , text: "sidebar.reseller", path: `/${ABILITIES_ENUM?.RE_SELLER}`, abilities: ABILITIES_ENUM?.RE_SELLER, @@ -109,7 +111,7 @@ export const menuItems: TMenuItem[] = [ { header: "page_header.user", element: , - icon: , + icon: , text: "sidebar.user", path: `/${ABILITIES_ENUM?.USER}`, abilities: ABILITIES_ENUM?.USER, From 693c1cdb069253e20edb91d5f71377cd69ad3c76 Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 16:00:20 +0300 Subject: [PATCH 08/12] remove un used code --- .../ImageBoxField/ImageBoxField.tsx | 2 +- src/Components/exercise/Header.tsx | 4 +- src/Pages/Admin/question/AddPage.tsx | 14 +-- src/Pages/Admin/question/EditPage.tsx | 3 +- .../Admin/question/Model/AcceptModal.tsx | 57 ---------- .../Model/Malty/ChoiceField/CheckboxField.tsx | 5 +- .../Model/Malty/ChoiceField/ChoiceFields.tsx | 3 - .../question/Model/Malty/ChoiceField/File.tsx | 88 -------------- .../Model/Malty/ChoiceField/HintField.tsx | 54 --------- src/Pages/Admin/question/Model/Malty/Form.tsx | 6 + .../Model/Malty/QuestionFIeld/File.tsx | 85 -------------- .../Model/Malty/QuestionFIeld/HintField.tsx | 52 --------- .../Malty/QuestionFIeld/QuestionFIeld.tsx | 6 - .../question/Model/Malty/Tags/DynamicTags.tsx | 107 ------------------ .../Admin/question/Model/Malty/Tags/Tag.tsx | 80 ------------- .../Admin/question/{Model => }/formUtil.ts | 2 +- 16 files changed, 17 insertions(+), 551 deletions(-) delete mode 100644 src/Pages/Admin/question/Model/AcceptModal.tsx delete mode 100644 src/Pages/Admin/question/Model/Malty/ChoiceField/File.tsx delete mode 100644 src/Pages/Admin/question/Model/Malty/ChoiceField/HintField.tsx delete mode 100644 src/Pages/Admin/question/Model/Malty/QuestionFIeld/File.tsx delete mode 100644 src/Pages/Admin/question/Model/Malty/QuestionFIeld/HintField.tsx delete mode 100644 src/Pages/Admin/question/Model/Malty/Tags/DynamicTags.tsx delete mode 100644 src/Pages/Admin/question/Model/Malty/Tags/Tag.tsx rename src/Pages/Admin/question/{Model => }/formUtil.ts (98%) diff --git a/src/Components/CustomFields/ImageBoxField/ImageBoxField.tsx b/src/Components/CustomFields/ImageBoxField/ImageBoxField.tsx index e19dd62..230058e 100644 --- a/src/Components/CustomFields/ImageBoxField/ImageBoxField.tsx +++ b/src/Components/CustomFields/ImageBoxField/ImageBoxField.tsx @@ -63,7 +63,7 @@ const ImageBoxField = ({ name }: any) => {
hidden
)}
-
+
{imagePreview ? ( Preview ) : ( diff --git a/src/Components/exercise/Header.tsx b/src/Components/exercise/Header.tsx index ffa1aec..a524b5f 100644 --- a/src/Components/exercise/Header.tsx +++ b/src/Components/exercise/Header.tsx @@ -72,11 +72,11 @@ const Header = () => { > - - {isBseQuestion || values?.isBase === 1 ? t("header.malty_exercise") : t("header.exercise")} + +
); diff --git a/src/Pages/Admin/question/AddPage.tsx b/src/Pages/Admin/question/AddPage.tsx index 5d35fe7..1f4b5dd 100644 --- a/src/Pages/Admin/question/AddPage.tsx +++ b/src/Pages/Admin/question/AddPage.tsx @@ -1,13 +1,12 @@ import React, { Suspense, lazy, useEffect } from "react"; import { Spin } from "antd"; -import FormikForm from "../../../Layout/Dashboard/FormikFormModel"; import { getInitialValues, getValidationSchema, getInitialValuesBase, getValidationSchemaBase, processTags, -} from "./Model/formUtil"; +} from "./formUtil"; import { useAddQuestion, useAddQuestionAsync } from "../../../api/Question"; import { useTranslation } from "react-i18next"; import { useLocation, useNavigate, useParams } from "react-router-dom"; @@ -21,7 +20,6 @@ import ModelForm from "./Model/ModelForm"; import { toast } from "react-toastify"; import { Form, Formik } from "formik"; import { MdOutlineArrowForwardIos } from "react-icons/md"; -const AcceptModal = lazy(() => import("./Model/AcceptModal")); const AddPage: React.FC = () => { const location = useLocation(); @@ -163,7 +161,8 @@ const AddPage: React.FC = () => { const handleCancel = () => { navigate(-1); }; - const Loading = LoadingAsync || isLoading + const Loading = LoadingAsync || isLoading; + useEffect(() => { if (isSuccess) { setSuccess(true); @@ -211,9 +210,7 @@ const AddPage: React.FC = () => { )} - }> - - +
@@ -264,9 +261,6 @@ const AddPage: React.FC = () => { )} - }> - - ); diff --git a/src/Pages/Admin/question/EditPage.tsx b/src/Pages/Admin/question/EditPage.tsx index c82a6af..7c6427c 100644 --- a/src/Pages/Admin/question/EditPage.tsx +++ b/src/Pages/Admin/question/EditPage.tsx @@ -1,13 +1,12 @@ 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"; +} from "./formUtil"; import { useAddQuestion, useDeleteQuestion, diff --git a/src/Pages/Admin/question/Model/AcceptModal.tsx b/src/Pages/Admin/question/Model/AcceptModal.tsx deleted file mode 100644 index 43531b9..0000000 --- a/src/Pages/Admin/question/Model/AcceptModal.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from "react"; -import { Modal } from "antd"; -import { useModalState } from "../../../../zustand/Modal"; -import { ModalEnum } from "../../../../enums/Model"; -import { useTranslation } from "react-i18next"; -import { useNavigate } from "react-router-dom"; -import { QUESTION_OBJECT_KEY } from "../../../../config/AppKey"; - -const AcceptModal: React.FC = () => { - const { isOpen, setIsOpen } = useModalState((state) => state); - const navigate = useNavigate(); - - const handleSubmit = () => { - localStorage.removeItem(QUESTION_OBJECT_KEY); - console.log("Handle submit clicked"); - setIsOpen(""); - - navigate(-1); - }; - - const handleCancel = () => { - setIsOpen(""); - }; - - const [t] = useTranslation(); - return ( - <> - -
{t("practical.accept_back")}
- -
-
- -
- -
-
{t("practical.cancel")}
-
{t("practical.accept")}
-
-
-
- - ); -}; - -export default AcceptModal; diff --git a/src/Pages/Admin/question/Model/Malty/ChoiceField/CheckboxField.tsx b/src/Pages/Admin/question/Model/Malty/ChoiceField/CheckboxField.tsx index 990bcdc..139fc2c 100644 --- a/src/Pages/Admin/question/Model/Malty/ChoiceField/CheckboxField.tsx +++ b/src/Pages/Admin/question/Model/Malty/ChoiceField/CheckboxField.tsx @@ -1,7 +1,6 @@ import React from "react"; -import useFormField from "../../../../../../Hooks/useFormField"; -import { Checkbox, Form } from "antd"; -import { useFormik, useFormikContext } from "formik"; +import { Checkbox } from "antd"; +import { useFormikContext } from "formik"; import { useTranslation } from "react-i18next"; const CheckboxField = ({ name, diff --git a/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx b/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx index 0640d42..4586fbb 100644 --- a/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx +++ b/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx @@ -6,10 +6,7 @@ import { useTranslation } from "react-i18next"; 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"; -import HintField from "./HintField"; import ImageBoxField from "../../../../../../Components/CustomFields/ImageBoxField/ImageBoxField"; import { GoTrash } from "react-icons/go"; diff --git a/src/Pages/Admin/question/Model/Malty/ChoiceField/File.tsx b/src/Pages/Admin/question/Model/Malty/ChoiceField/File.tsx deleted file mode 100644 index b3d2e37..0000000 --- a/src/Pages/Admin/question/Model/Malty/ChoiceField/File.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { Button, Upload, UploadFile } from "antd"; -import useFormField from "../../../../../../Hooks/useFormField"; -import { UploadOutlined } from "@ant-design/icons"; -import { useMemo } from "react"; - -const File = ({ - name, - label, - onChange, - isDisabled, - placholder, - className, - parent_index, - props, -}: any) => { - const newName = `Questions[${parent_index}].answers[${name}].answer_image`; - - const { formik, t, isError, errorMsg } = useFormField(newName, props); - let imageUrl = - formik?.values?.Questions?.[parent_index]?.answers[name]?.answer_image ?? - null; - // console.log(imageUrl); - - const fileList: UploadFile[] = useMemo(() => { - if (!imageUrl) return []; - - return [ - typeof imageUrl === "string" - ? { - uid: "-1", - name: "uploaded-image", - status: "done", - url: imageUrl, - thumbUrl: imageUrl, - } - : { - uid: imageUrl.uid || "-1", - name: imageUrl.name || "uploaded-image", - status: "done", - originFileObj: imageUrl, - }, - ]; - }, [imageUrl]); - // console.log(1); - - const FilehandleChange = (value: any) => { - // console.log(value,"filevalue"); - if (value.fileList.length === 0) { - formik.setFieldValue(newName, null); - } else { - formik.setFieldValue( - `Questions[${parent_index}].answers[${name}].answer_image`, - value?.file?.originFileObj, - ); - } - }; - const customRequest = async ({ onSuccess, no_label, label_icon }: any) => { - onSuccess(); - }; - return ( -
- - - - -
{isError ? "required" : ""}
- {errorMsg} -
-
- ); -}; - -export default File; diff --git a/src/Pages/Admin/question/Model/Malty/ChoiceField/HintField.tsx b/src/Pages/Admin/question/Model/Malty/ChoiceField/HintField.tsx deleted file mode 100644 index dcdf284..0000000 --- a/src/Pages/Admin/question/Model/Malty/ChoiceField/HintField.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { Form, Input } from "antd"; -import React from "react"; -import useFormField from "../../../../../../Hooks/useFormField"; -import { MdOutlineEdit } from "react-icons/md"; -import { Field } from "formik"; - -const HintField = ({ - name, - label, - label2, - placeholder, - isDisabled, - onChange, - props, - parent_index, - id, - className, -}: any) => { - const newName = `Questions[${parent_index}].answers[${name}].hint`; - - const { formik, isError, errorMsg, t } = useFormField(newName, props); - const TextFilehandleChange = ( - e: React.ChangeEvent, - ) => { - // console.log('Change:', e.target.value); - formik.setFieldValue(newName, e.target.value); - }; - - return ( -
- - - - -
- ); -}; - -export default React.memo(HintField); diff --git a/src/Pages/Admin/question/Model/Malty/Form.tsx b/src/Pages/Admin/question/Model/Malty/Form.tsx index 62a0839..fbb81f3 100644 --- a/src/Pages/Admin/question/Model/Malty/Form.tsx +++ b/src/Pages/Admin/question/Model/Malty/Form.tsx @@ -87,6 +87,12 @@ const Form = () => { ); + useEffect(() => { + if (Success) { + formik.resetForm() + setSuccess(false); + } + }, [Success]); return ( diff --git a/src/Pages/Admin/question/Model/Malty/QuestionFIeld/File.tsx b/src/Pages/Admin/question/Model/Malty/QuestionFIeld/File.tsx deleted file mode 100644 index fdc5bab..0000000 --- a/src/Pages/Admin/question/Model/Malty/QuestionFIeld/File.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { Button, Upload, UploadFile } from "antd"; -import useFormField from "../../../../../../Hooks/useFormField"; -import { UploadOutlined } from "@ant-design/icons"; -import { useMemo } from "react"; - -const File = ({ - name, - label, - onChange, - isDisabled, - placholder, - className, - props, -}: any) => { - const newName = `Questions[${name}].image`; - - const { formik, t, isError, errorMsg } = useFormField(newName, props); - let imageUrl = formik?.values?.Questions?.[name]?.image ?? null; - // console.log(imageUrl); - - const fileList: UploadFile[] = useMemo(() => { - if (!imageUrl) return []; - - return [ - typeof imageUrl === "string" - ? { - uid: "-1", - name: "uploaded-image", - status: "done", - url: imageUrl, - thumbUrl: imageUrl, - } - : { - uid: imageUrl.uid || "-1", - name: imageUrl.name || "uploaded-image", - status: "done", - originFileObj: imageUrl, - }, - ]; - }, [imageUrl]); - // console.log(1); - - const FilehandleChange = (value: any) => { - // console.log(value,"filevalue"); - if (value.fileList.length === 0) { - formik.setFieldValue(newName, null); - } else { - formik.setFieldValue( - `Questions[${name}].image`, - value?.file?.originFileObj, - ); - } - }; - const customRequest = async ({ onSuccess, no_label, label_icon }: any) => { - onSuccess(); - }; - return ( -
- - - - -
{isError ? "required" : ""}
- {errorMsg} -
-
- ); -}; - -export default File; diff --git a/src/Pages/Admin/question/Model/Malty/QuestionFIeld/HintField.tsx b/src/Pages/Admin/question/Model/Malty/QuestionFIeld/HintField.tsx deleted file mode 100644 index 753a8b3..0000000 --- a/src/Pages/Admin/question/Model/Malty/QuestionFIeld/HintField.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Form, Input } from "antd"; -import React from "react"; -import useFormField from "../../../../../../Hooks/useFormField"; -import { MdOutlineEdit } from "react-icons/md"; -import { Field } from "formik"; - -const HintField = ({ - name, - label, - label2, - placeholder, - isDisabled, - onChange, - props, - id, - className, -}: any) => { - const newName = `Questions[${name}].hint`; - const { formik, isError, errorMsg, t } = useFormField(newName, props); - const TextFilehandleChange = ( - e: React.ChangeEvent, - ) => { - // console.log('Change:', e.target.value); - formik.setFieldValue(newName, e.target.value); - }; - - return ( -
- - - - -
- ); -}; - -export default React.memo(HintField); diff --git a/src/Pages/Admin/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx b/src/Pages/Admin/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx index 5bb1b33..907b975 100644 --- a/src/Pages/Admin/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx +++ b/src/Pages/Admin/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx @@ -1,16 +1,10 @@ import React, { useEffect } from "react"; import { Choice } from "../../../../../../types/Item"; -import ValidationField from "../../../../../../Components/ValidationField/ValidationField"; import { useFormikContext } from "formik"; 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"; -import CheckboxField from "./CheckboxField"; -import HintField from "./HintField"; import ImageBoxField from "../../../../../../Components/CustomFields/ImageBoxField/ImageBoxField"; import { GoTrash } from "react-icons/go"; diff --git a/src/Pages/Admin/question/Model/Malty/Tags/DynamicTags.tsx b/src/Pages/Admin/question/Model/Malty/Tags/DynamicTags.tsx deleted file mode 100644 index 81b5fd8..0000000 --- a/src/Pages/Admin/question/Model/Malty/Tags/DynamicTags.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { useFormikContext } from "formik"; -import React from "react"; -import { useTranslation } from "react-i18next"; -import { FaCirclePlus } from "react-icons/fa6"; -import Tag from "./Tag"; -import { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState"; -import { useGetAllTag } from "../../../../../../api/tags"; - -const DynamicTags = ({ parent_index }: { parent_index: number }) => { - const formik = useFormikContext(); - const [t] = useTranslation(); - const { TagsSearch, setTagsSearch, currentTag, currentParentIndex } = - useObjectToEdit(); - const { data } = useGetAllTag({ - name: TagsSearch, - }); - const suggests = data?.data; - - const handleAddChoice = () => { - const length = formik?.values?.Questions?.[parent_index]?.tags.length; - const lastElement = - formik?.values?.Questions?.[parent_index]?.tags[length - 1]?.name; - setTagsSearch(null); - - if (lastElement !== "") { - formik.setFieldValue(`Questions.[${parent_index}].tags`, [ - ...((formik?.values as any)?.Questions?.[parent_index]?.tags as any[]), - - { - id: length + "_new", - name: "", - key: length, - }, - ]); - } else { - } - }; - // console.log(formik?.values); - // console.log(currentTag); - - const handleChoice = (item: any) => { - const length = formik?.values?.Questions?.[parent_index]?.tags?.length; - console.log(currentTag); - - formik.setFieldValue(`Questions.[${parent_index}].tags[${currentTag}]`, { - ...item, - key: length, - }); - setTagsSearch(null); - }; - - // console.log(formik?.values?.tags?.length); - - return ( -
- {formik?.values?.Questions?.[parent_index]?.tags?.length < 1 && ( -

- {" "} - {t("header.add_tag")} -

- )} - -
-
- {( - ((formik?.values as any)?.Questions?.[parent_index] - ?.tags as any[]) || [] - ).map((item: any, index: number) => { - return ( - - ); - })} -
- - {formik?.values?.Questions?.[parent_index]?.tags?.length > 0 && ( -

- -

- )} -
- {TagsSearch && currentParentIndex === parent_index && ( -
- {suggests?.map((item: any, index: number) => { - console.log(currentParentIndex === parent_index); - - return ( -
handleChoice(item)} - > - {item?.name} -
- ); - })} -
- )} -
- ); -}; - -export default DynamicTags; diff --git a/src/Pages/Admin/question/Model/Malty/Tags/Tag.tsx b/src/Pages/Admin/question/Model/Malty/Tags/Tag.tsx deleted file mode 100644 index fbbfcd0..0000000 --- a/src/Pages/Admin/question/Model/Malty/Tags/Tag.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { useFormikContext } from "formik"; -import React, { useRef, useEffect } from "react"; -import { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState"; -import { FaTrash } from "react-icons/fa"; - -const Tag = ({ - data, - index, - parent_index, -}: { - data: any; - index: number; - parent_index: number; -}) => { - const inputRef = useRef(null); - const timeoutRef = useRef(null); - const DEBOUNCE_DELAY = 500; - const formik = useFormikContext(); - const { setTagsSearch, setCurrentTag, setCurrentParentIndex } = - useObjectToEdit(); - console.log(formik?.values?.Questions); - - useEffect(() => { - if (inputRef.current) { - inputRef.current.style.width = `${(formik?.values?.Questions?.[parent_index]?.tags[index]?.name?.length + 1) * 8}px`; - } - }, [formik?.values?.Questions?.[parent_index]?.tags[index]?.name]); - - const handleEditInputChange = (e: React.ChangeEvent) => { - // console.log(e.target.value); - - formik.setFieldValue(`Questions.[${parent_index}].tags[${index}]`, { - key: parent_index, - name: e.target.value, - id: `${parent_index}_key`, - }); - setCurrentTag(index); - setCurrentParentIndex(parent_index); - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } - - timeoutRef.current = setTimeout(() => { - setTagsSearch(e.target.value); - }, DEBOUNCE_DELAY); - }; - - const handleDeleteChoice = () => { - console.log(data); - - // Create a copy of current tags array - const currentTags = [...formik.values.tags]; - - // Remove the item at the specified index from the array - currentTags.splice(index, 1); - - console.log(currentTags); // Log the updated tags array - - // Update formik field value with the updated tags array - formik.setFieldValue(`Questions.[${parent_index}].tags`, currentTags); - - // Reset search state if needed - setTagsSearch(null); - }; - - return ( -
- - -
- ); -}; - -export default Tag; diff --git a/src/Pages/Admin/question/Model/formUtil.ts b/src/Pages/Admin/question/formUtil.ts similarity index 98% rename from src/Pages/Admin/question/Model/formUtil.ts rename to src/Pages/Admin/question/formUtil.ts index dc19acd..1a4f553 100644 --- a/src/Pages/Admin/question/Model/formUtil.ts +++ b/src/Pages/Admin/question/formUtil.ts @@ -1,5 +1,5 @@ import * as Yup from "yup"; -import { Question } from "../../../../types/Item"; +import { Question } from "../../../types/Item"; import { toast } from "react-toastify"; export const getInitialValues = (objectToEdit: Question): any => { From 0b827ba990fafbf9613277564746c262832be5da Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 16:21:57 +0300 Subject: [PATCH 09/12] add new page "QuestionBank" --- .vscode/settings.json | 1 + .../ValidationField/View/TextField.tsx | 3 +- .../Admin/QuestionBank/Model/AddModel.tsx | 33 ++++++++ .../Admin/QuestionBank/Model/EditModel.tsx | 38 +++++++++ .../Admin/QuestionBank/Model/FilterForm.tsx | 20 +++++ .../Admin/QuestionBank/Model/ModelForm.tsx | 17 ++++ .../Admin/QuestionBank/Model/formUtil.ts | 19 +++++ src/Pages/Admin/QuestionBank/Page.tsx | 46 ++++++++++ src/Pages/Admin/QuestionBank/Table.tsx | 18 ++++ .../Admin/QuestionBank/useTableColumns.tsx | 83 +++++++++++++++++++ .../question/Model/Field/ChoiceFields.tsx | 1 + .../Model/Malty/ChoiceField/ChoiceFields.tsx | 1 + src/Pages/Admin/question/Model/Malty/Form.tsx | 1 + src/Pages/Admin/question/Model/ModelForm.tsx | 1 + src/Routes.tsx | 13 +++ src/enums/Model.ts | 7 ++ src/enums/abilities.ts | 1 + src/translate/ar.json | 12 ++- src/utils/hasAbilityFn.ts | 22 +++++ 19 files changed, 332 insertions(+), 5 deletions(-) create mode 100644 src/Pages/Admin/QuestionBank/Model/AddModel.tsx create mode 100644 src/Pages/Admin/QuestionBank/Model/EditModel.tsx create mode 100644 src/Pages/Admin/QuestionBank/Model/FilterForm.tsx create mode 100644 src/Pages/Admin/QuestionBank/Model/ModelForm.tsx create mode 100644 src/Pages/Admin/QuestionBank/Model/formUtil.ts create mode 100644 src/Pages/Admin/QuestionBank/Page.tsx create mode 100644 src/Pages/Admin/QuestionBank/Table.tsx create mode 100644 src/Pages/Admin/QuestionBank/useTableColumns.tsx diff --git a/.vscode/settings.json b/.vscode/settings.json index fae1ae1..54fb8c9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,6 +13,7 @@ "Popconfirm", "queryqlent", "registraion", + "Sellcast", "SENDNOTIFICATION", "setdateparams", "szhsin", diff --git a/src/Components/ValidationField/View/TextField.tsx b/src/Components/ValidationField/View/TextField.tsx index ae60405..35babba 100644 --- a/src/Components/ValidationField/View/TextField.tsx +++ b/src/Components/ValidationField/View/TextField.tsx @@ -25,6 +25,7 @@ const TextField = ({ ) => { formik.setFieldValue(name, e.target.value); }; + return (
diff --git a/src/Pages/Admin/QuestionBank/Model/AddModel.tsx b/src/Pages/Admin/QuestionBank/Model/AddModel.tsx new file mode 100644 index 0000000..348426b --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/AddModel.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import { getInitialValues, getValidationSchema } from "./formUtil"; +import { ModalEnum } from "../../../../enums/Model"; +import LayoutModel from "../../../../Layout/Dashboard/LayoutModel"; +import { QueryStatusEnum } from "../../../../enums/QueryStatus"; +import ModelForm from "./ModelForm"; +import { useAddGrade } from "../../../../api/grade"; + +const AddModel: React.FC = () => { + const { mutate, status } = useAddGrade(); + + const handleSubmit = (values: any) => { + mutate({ + ...values, + }); + }; + return ( + <> + + + + + ); +}; + +export default AddModel; diff --git a/src/Pages/Admin/QuestionBank/Model/EditModel.tsx b/src/Pages/Admin/QuestionBank/Model/EditModel.tsx new file mode 100644 index 0000000..a2e1fdb --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/EditModel.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { getInitialValues, getValidationSchema } from "./formUtil"; +import { ModalEnum } from "../../../../enums/Model"; +import LayoutModel from "../../../../Layout/Dashboard/LayoutModel"; +import ModelForm from "./ModelForm"; +import { QueryStatusEnum } from "../../../../enums/QueryStatus"; +import { useObjectToEdit } from "../../../../zustand/ObjectToEditState"; +import { useUpdateQuestion } from "../../../../api/Question"; +import { handelImageState } from "../../../../utils/DataToSendImageState"; + +const EditModel: React.FC = () => { + const { mutate, status } = useUpdateQuestion(); + const { objectToEdit } = useObjectToEdit((state) => state); + + const handleSubmit = (values: any) => { + const Data_to_send = { ...values }; + const handelImage = handelImageState(Data_to_send, "icon"); + mutate(handelImage); + }; + + return ( + <> + + + + + ); +}; + +export default EditModel; diff --git a/src/Pages/Admin/QuestionBank/Model/FilterForm.tsx b/src/Pages/Admin/QuestionBank/Model/FilterForm.tsx new file mode 100644 index 0000000..c870850 --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/FilterForm.tsx @@ -0,0 +1,20 @@ +import React from "react"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; +import { Col, Row } from "reactstrap"; +import { useFormikContext } from "formik"; + +const FilterForm = () => { + const formik = useFormikContext(); + + return ( +
+ + + + + +
+ ); +}; + +export default FilterForm; diff --git a/src/Pages/Admin/QuestionBank/Model/ModelForm.tsx b/src/Pages/Admin/QuestionBank/Model/ModelForm.tsx new file mode 100644 index 0000000..b18fe6f --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/ModelForm.tsx @@ -0,0 +1,17 @@ +import { Col, Row } from "reactstrap"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; + +const Form = () => { + return ( + + + + + + + + + ); +}; + +export default Form; diff --git a/src/Pages/Admin/QuestionBank/Model/formUtil.ts b/src/Pages/Admin/QuestionBank/Model/formUtil.ts new file mode 100644 index 0000000..77f69bf --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/formUtil.ts @@ -0,0 +1,19 @@ +import * as Yup from "yup"; +import { Grade, GradeInitialValues } from "../../../../types/Grade"; + +export const getInitialValues = ( + objectToEdit: Partial, +): GradeInitialValues => { + return { + id: objectToEdit?.id, + name: objectToEdit?.name ?? "", + icon: objectToEdit?.icon ?? "", + }; +}; + +export const getValidationSchema = () => { + // validate input + return Yup.object().shape({ + name: Yup.string().required("validation.required"), + }); +}; diff --git a/src/Pages/Admin/QuestionBank/Page.tsx b/src/Pages/Admin/QuestionBank/Page.tsx new file mode 100644 index 0000000..e905425 --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Page.tsx @@ -0,0 +1,46 @@ +import { useTranslation } from "react-i18next"; +import { lazy, Suspense } from "react"; +import { Spin } from "antd"; +import useSetPageTitle from "../../../Hooks/useSetPageTitle"; +import { ModalEnum } from "../../../enums/Model"; +import { useDeleteQuestion } from "../../../api/Question"; +import PageHeader from "../../../Layout/Dashboard/PageHeader"; +import FilterLayout from "../../../Layout/Dashboard/FilterLayout"; +import FilterForm from "./Model/FilterForm"; +import { canAddQuestionBank } from "../../../utils/hasAbilityFn"; + +const Table = lazy(() => import("./Table")); +const AddModalForm = lazy(() => import("./Model/AddModel")); +const EditModalForm = lazy(() => import("./Model/EditModel")); +const DeleteModalForm = lazy( + () => import("../../../Layout/Dashboard/DeleteModels"), +); + +const TableHeader = () => { + const [t] = useTranslation(); + const deleteMutation = useDeleteQuestion(); + + useSetPageTitle(t(`page_header.QuestionBank`)); + + return ( +
+ }> + + } filterTitle="table.QuestionBank" /> + + + + + + + ); +}; + +export default TableHeader; diff --git a/src/Pages/Admin/QuestionBank/Table.tsx b/src/Pages/Admin/QuestionBank/Table.tsx new file mode 100644 index 0000000..37f483c --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Table.tsx @@ -0,0 +1,18 @@ +import { useColumns } from "./useTableColumns"; +import React from "react"; +import DataTable from "../../../Layout/Dashboard/Table/DataTable"; +import { useGetAllQuestion } from "../../../api/Question"; +import { useFilterState } from "../../../Components/Utils/Filter/FilterState"; + +const App: React.FC = () => { + const { filterState } = useFilterState(); + + const response = useGetAllQuestion({ + pagination: true, + ...filterState, + }); + + return ; +}; + +export default App; diff --git a/src/Pages/Admin/QuestionBank/useTableColumns.tsx b/src/Pages/Admin/QuestionBank/useTableColumns.tsx new file mode 100644 index 0000000..da5680c --- /dev/null +++ b/src/Pages/Admin/QuestionBank/useTableColumns.tsx @@ -0,0 +1,83 @@ +import { TableColumnsType } from "antd"; +import { Question } from "../../../types/Item"; +import { FaPlus } from "react-icons/fa"; +import { ModalEnum } from "../../../enums/Model"; +import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; +import { useTranslation } from "react-i18next"; +import { ABILITIES_ENUM } from "../../../enums/abilities"; +import { useNavigate } from "react-router-dom"; +import { useModalState } from "../../../zustand/Modal"; +import { + canAddQuestion, + canDeleteQuestion, + canEditQuestion, +} from "../../../utils/hasAbilityFn"; +import ActionButtons from "../../../Components/Table/ActionButtons"; + +export const useColumns = () => { + const { setObjectToEdit } = useObjectToEdit((state) => state); + const navigate = useNavigate(); + const { setIsOpen } = useModalState((state) => state); + + const handelAdd = () => { + setObjectToEdit({}); + navigate(`${ABILITIES_ENUM?.QUESTION}/add`); + }; + + const handelDelete = (data: any) => { + setObjectToEdit(data); + setIsOpen(ModalEnum?.QUESTION_DELETE); + }; + + const handleEdit = (record: any) => { + setObjectToEdit(record); + navigate(`${ABILITIES_ENUM?.QUESTION}/${record?.id}`); + }; + const [t] = useTranslation(); + + const columns: TableColumnsType = [ + { + title: t("columns.id"), + dataIndex: "id", + key: "id", + align: "center", + render: (text, record) => record?.id, + }, + { + title: `${t("columns.content")}`, + dataIndex: "name", + key: "name", + align: "center", + render: (text, record) => record?.content, + ellipsis: true, + }, + { + title: t("columns.isBase"), + dataIndex: "isBase", + key: "isBase", + align: "center", + render: (text, record) => + record?.isBase ? t("practical.yes") : t("practical.no"), + }, + + { + title: "#", + key: "actions", + align: "center", + + render: (_text, record, index) => { + return ( + handelDelete(record)} + onEdit={() => handleEdit(record)} + /> + ); + }, + }, + ]; + + return columns; +}; diff --git a/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx b/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx index 37630b6..552e7eb 100644 --- a/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx +++ b/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx @@ -70,6 +70,7 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => { type="TextArea" style={{ width: "100%" , height: 60,resize:"none" }} showCount={false} + autoSize={{ minRows: 2, maxRows: 10 }} /> diff --git a/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx b/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx index 4586fbb..46dac53 100644 --- a/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx +++ b/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx @@ -89,6 +89,7 @@ const ChoiceFields = ({ type="TextArea" style={{ width: "100%" , height: 60,resize:"none" }} showCount={false} + autoSize={{ minRows: 2, maxRows: 10 }} /> diff --git a/src/Pages/Admin/question/Model/Malty/Form.tsx b/src/Pages/Admin/question/Model/Malty/Form.tsx index fbb81f3..8effc15 100644 --- a/src/Pages/Admin/question/Model/Malty/Form.tsx +++ b/src/Pages/Admin/question/Model/Malty/Form.tsx @@ -142,6 +142,7 @@ const Form = () => { label="hint_question" type="TextArea" style={{ width: "100%" , height: 60,resize:"none" }} + autoSize={{ minRows: 2, maxRows: 10 }} showCount={false} /> diff --git a/src/Pages/Admin/question/Model/ModelForm.tsx b/src/Pages/Admin/question/Model/ModelForm.tsx index b104882..6de101f 100644 --- a/src/Pages/Admin/question/Model/ModelForm.tsx +++ b/src/Pages/Admin/question/Model/ModelForm.tsx @@ -77,6 +77,7 @@ const Form = () => { type="TextArea" style={{ width: "100%" , height: 60,resize:"none" }} showCount={false} + autoSize={{ minRows: 2, maxRows: 10 }} /> diff --git a/src/Routes.tsx b/src/Routes.tsx index 409c91c..93a9a74 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -32,6 +32,7 @@ const EditReSeller = React.lazy( const User = React.lazy(() => import("./Pages/Admin/User/Page")); const Param = React.lazy(() => import("./Pages/Admin/Param/Page")); +const QuestionBank = React.lazy(() => import("./Pages/Admin/QuestionBank/Page")); /// RESELLER /// const Student_Package = React.lazy( @@ -129,6 +130,18 @@ export const menuItems: TMenuItem[] = [ prevPath: 0, }, + { + header: "page_header.questionBank", + element: , + icon: , + text: "sidebar.questionBank", + path: `/${ABILITIES_ENUM?.QUESTION}`, + abilities: ABILITIES_ENUM?.QUESTION, + abilities_value: ABILITIES_VALUES_ENUM.INDEX, + prevPath: 0, + }, + + /// RESELLER ///// { diff --git a/src/enums/Model.ts b/src/enums/Model.ts index 5a95bef..de37336 100644 --- a/src/enums/Model.ts +++ b/src/enums/Model.ts @@ -186,4 +186,11 @@ export enum ModalEnum { Student_Package_EDIT = "Student_Package.edit", Student_Package_ADD = "Student_Package.add", Student_Package_DELETE = "Student_Package.delete", + + + ///QuestionBank + + QUESTION_BANK_ADD = "QuestionBank.add", + QUESTION_BANK_EDIT = "QuestionBank.edit", + QUESTION_BANK_DELETE = "QuestionBank.delete", } diff --git a/src/enums/abilities.ts b/src/enums/abilities.ts index 427f62a..e84627a 100644 --- a/src/enums/abilities.ts +++ b/src/enums/abilities.ts @@ -47,6 +47,7 @@ export enum ABILITIES_ENUM { User = "user", RE_SELLER = "reseller", Student_Package = "student_package", + QUESTION_BANK = "QuestionBank" //// } diff --git a/src/translate/ar.json b/src/translate/ar.json index c2d428a..bd36428 100644 --- a/src/translate/ar.json +++ b/src/translate/ar.json @@ -753,7 +753,8 @@ "reseller": "البائعين", "param": "معامل", "student_package": "حزمة الطالب", - "quiz":"الاختبارات" + "quiz":"الاختبارات", + "QuestionBank":"بنك الأسئلة" }, "message": { "some_thing_went_wrong": "حدث خطأ ما", @@ -788,7 +789,8 @@ "grade": "الصفوف", "report": "تقرير", "tags": "كلمات مفتاحية", - "reseller":"البائعين" + "reseller":"البائعين", + "QuestionBank":"بنك الأسئلة" }, "page_header": { "dashboard": "لوحة القيادة / الصفحة الرئيسية", @@ -825,13 +827,15 @@ "reseller": " لوحة القيادة / البائعين", "add_reseller": " لوحة القيادة / البائعين / إضافة بائع ", "param": "معامل", - "student_package": "حزمة الطالب" + "student_package": "حزمة الطالب", + "QuestionBank":"لوحة القيادة / بنك الأسئلة" }, "table": { "student": "قائمة الطلاب", "reseller": "البائعين", "grade": "قائمة الصفوف", - "subjects": "مواد الصف" + "subjects": "مواد الصف", + "QuestionBank":"بنك الأسئلة" }, "alphabet": { "A": "A", diff --git a/src/utils/hasAbilityFn.ts b/src/utils/hasAbilityFn.ts index 221883b..dc4e751 100644 --- a/src/utils/hasAbilityFn.ts +++ b/src/utils/hasAbilityFn.ts @@ -677,3 +677,25 @@ export const canDeleteStudent_Package = hasAbility( ); + + +/// QuestionBank + +export const canAddQuestionBank = hasAbility( + ABILITIES_ENUM.QUESTION_BANK, + ABILITIES_VALUES_ENUM.STORE, +); + +export const canEditQuestionBank = hasAbility( + ABILITIES_ENUM.QUESTION_BANK, + ABILITIES_VALUES_ENUM.UPDATE, +); +export const canDeleteQuestionBank = hasAbility( + ABILITIES_ENUM.QUESTION_BANK, + ABILITIES_VALUES_ENUM.DELETE, +); + +export const canShowQuestionBank = hasAbility( + ABILITIES_ENUM.QUESTION_BANK, + ABILITIES_VALUES_ENUM.SHOW, +); From 091c0bf15c5edc9d22dd8f67b97ca09de987102c Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 16:40:10 +0300 Subject: [PATCH 10/12] add filter lessonsIds --- .../Admin/QuestionBank/useTableColumns.tsx | 1 + src/Pages/Admin/question/Table.tsx | 2 +- src/Pages/Auth/FormField.tsx | 22 +++++-------------- src/Pages/Auth/LoginForm.tsx | 2 +- src/api/auth.ts | 2 +- src/api/helper/useAxios.ts | 2 ++ src/translate/ar.json | 2 +- 7 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Pages/Admin/QuestionBank/useTableColumns.tsx b/src/Pages/Admin/QuestionBank/useTableColumns.tsx index da5680c..9bbac06 100644 --- a/src/Pages/Admin/QuestionBank/useTableColumns.tsx +++ b/src/Pages/Admin/QuestionBank/useTableColumns.tsx @@ -66,6 +66,7 @@ export const useColumns = () => { align: "center", render: (_text, record, index) => { + return ( { const { filterState } = useFilterState(); const response = useGetAllQuestion({ - lesson_id: lesson_id, + lessonsIds: [lesson_id], pagination: true, ...filterState, }); diff --git a/src/Pages/Auth/FormField.tsx b/src/Pages/Auth/FormField.tsx index 28ec2d0..50ba4f1 100644 --- a/src/Pages/Auth/FormField.tsx +++ b/src/Pages/Auth/FormField.tsx @@ -1,18 +1,5 @@ -import React, { useEffect, useState } from "react"; -import { Form, Field, useFormikContext } from "formik"; -import Image from "../../Components/Ui/Image"; -import { Input } from "antd"; -import AuthSelect from "../../Components/Ui/Custom/AuthSelect"; -// import { useGetAllCycle } from "../../api/cycle"; -// import { useGetAllBranch } from "../../api/branch"; -import { useGetAllTerm } from "../../api/term"; -import { FormValues } from "../../types/Auth"; -import { - BRANCH_OBJECT_KEY, - CYCLE_OBJECT_KEY, - TERM_OBJECT_KEY, -} from "../../config/AppKey"; -import useFormatAuthDataToSelect from "../../utils/useFormatAuthDataToSelect"; +import { Form, useFormikContext } from "formik"; + import { useTranslation } from "react-i18next"; import ValidationField from "../../Components/ValidationField/ValidationField"; @@ -22,6 +9,9 @@ type FormFieldType = { const FormField = ({ isLoading }: FormFieldType) => { const [t] = useTranslation(); + const {isValid} = useFormikContext(); + console.log(isValid,"isValid"); + return (
{/* */} @@ -45,7 +35,7 @@ const FormField = ({ isLoading }: FormFieldType) => { /> */} - diff --git a/src/Pages/Auth/LoginForm.tsx b/src/Pages/Auth/LoginForm.tsx index b5699fe..ffbcbf8 100644 --- a/src/Pages/Auth/LoginForm.tsx +++ b/src/Pages/Auth/LoginForm.tsx @@ -39,7 +39,7 @@ const LoginForm = () => { return (
- + {(formikProps) => }
diff --git a/src/api/auth.ts b/src/api/auth.ts index 16d5a99..b29bbe4 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -5,4 +5,4 @@ const API = { LOGIN: `login`, LOGOUT: `logout`, }; -export const useLoginAdmin = () => useAddMutation(KEY, API.LOGIN, false); +export const useLoginAdmin = () => useAddMutation(KEY, API.LOGIN, true); diff --git a/src/api/helper/useAxios.ts b/src/api/helper/useAxios.ts index b2f39fc..69da961 100644 --- a/src/api/helper/useAxios.ts +++ b/src/api/helper/useAxios.ts @@ -50,6 +50,8 @@ function useAxios() { return response; }, function (error) { + console.log(error?.response); + const status = error?.request?.status; const errorMsg = error?.response?.data?.message; const errorField = error?.response?.data; diff --git a/src/translate/ar.json b/src/translate/ar.json index bd36428..0c62043 100644 --- a/src/translate/ar.json +++ b/src/translate/ar.json @@ -754,7 +754,7 @@ "param": "معامل", "student_package": "حزمة الطالب", "quiz":"الاختبارات", - "QuestionBank":"بنك الأسئلة" + "questionBank":"بنك الأسئلة" }, "message": { "some_thing_went_wrong": "حدث خطأ ما", From b7276a2c6a40aca15468b774f6565db80d04bff1 Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 17:02:32 +0300 Subject: [PATCH 11/12] fix question column --- .../Admin/QuestionBank/useTableColumns.tsx | 49 +++++++++++++++++-- src/Pages/Admin/question/useTableColumns.tsx | 48 ++++++++++++++++-- src/translate/ar.json | 7 ++- 3 files changed, 94 insertions(+), 10 deletions(-) diff --git a/src/Pages/Admin/QuestionBank/useTableColumns.tsx b/src/Pages/Admin/QuestionBank/useTableColumns.tsx index 9bbac06..632669b 100644 --- a/src/Pages/Admin/QuestionBank/useTableColumns.tsx +++ b/src/Pages/Admin/QuestionBank/useTableColumns.tsx @@ -45,19 +45,59 @@ export const useColumns = () => { }, { title: `${t("columns.content")}`, - dataIndex: "name", - key: "name", + dataIndex: "content", + key: "content", align: "center", render: (text, record) => record?.content, ellipsis: true, }, { - title: t("columns.isBase"), + title: `${t("columns.hint")}`, + dataIndex: "hint", + key: "hint", + align: "center", + render: (text, record) => { + + return ( + <>{record?.hint ?? "karim"} + ); + }, + ellipsis: true, + }, + { + title: `${t("columns.tags")}`, + dataIndex: "tags", + key: "tags", + align: "center", + + render: (text, record) => { + const tags = record?.tags?.map((item:any)=>{ + return item?.name + }) ?? []; + return ( +
+ {tags.length > 0 ? ( + tags.map((tag, index) => ( + + {tag} + {index < tags.length - 1 && ', '} + + )) + ) : ( + _ + )} +
+ ); + }, + ellipsis: true, + }, + { + title: t("columns.question_type"), dataIndex: "isBase", key: "isBase", align: "center", render: (text, record) => - record?.isBase ? t("practical.yes") : t("practical.no"), + record?.isBase ? t("columns.base_question") : t("columns.normal_question"), }, { @@ -66,7 +106,6 @@ export const useColumns = () => { align: "center", render: (_text, record, index) => { - return ( { }, { title: `${t("columns.content")}`, - dataIndex: "name", - key: "name", + dataIndex: "content", + key: "content", align: "center", render: (text, record) => record?.content, ellipsis: true, }, { - title: t("columns.isBase"), + title: `${t("columns.hint")}`, + dataIndex: "hint", + key: "hint", + align: "center", + render: (text, record) => { + + return ( + <>{record?.hint ?? "_"} + ); + }, + ellipsis: true, + }, + { + title: `${t("columns.tags")}`, + dataIndex: "tags", + key: "tags", + align: "center", + + render: (text, record) => { + const tags = record?.tags?.map((item:any)=>{ + return item?.name + }) ?? []; + return ( +
+ {tags.length > 0 ? ( + tags.map((tag, index) => ( + + {tag} + {index < tags.length - 1 && ', '} + + )) + ) : ( + _ + )} +
+ ); + }, + ellipsis: true, + }, + { + title: t("columns.question_type"), dataIndex: "isBase", key: "isBase", align: "center", render: (text, record) => - record?.isBase ? t("practical.yes") : t("practical.no"), + record?.isBase ? t("columns.base_question") : t("columns.normal_question"), }, { diff --git a/src/translate/ar.json b/src/translate/ar.json index 0c62043..f81bbce 100644 --- a/src/translate/ar.json +++ b/src/translate/ar.json @@ -187,7 +187,12 @@ "subject":"المادة", "quiz_status":"حالة الاختبار", "creator_name":"اسم المنشئ", - "created_by":"أنشئ بواسطة" + "created_by":"أنشئ بواسطة", + "question_type": "نوع تمرين", + "base_question": " تمرين متعدد ", + "normal_question": " تمرين عادي", + "hint":"شرح ", + "tags":"كلمات مفتاحية" }, "practical": { "to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال", From 0f54e215462df94a10f9b9e3fc47f5cd262d7727 Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sun, 15 Sep 2024 10:03:06 +0300 Subject: [PATCH 12/12] add new route navigater --- .../utils/ValidationField.scss | 14 +++++ src/Layout/Dashboard/PageHeader.tsx | 14 +++-- src/Layout/Dashboard/PageTitle.tsx | 30 +++++++++++ src/Pages/Admin/Grade/Page.tsx | 5 +- src/Pages/Admin/Param/Page.tsx | 6 ++- src/Pages/Admin/QuestionBank/Page.tsx | 5 +- src/Pages/Admin/Report/Page.tsx | 7 ++- src/Pages/Admin/Reseller/Page.tsx | 5 +- src/Pages/Admin/Student/Page.tsx | 6 ++- src/Pages/Admin/Tags/Page.tsx | 11 ++-- src/Pages/Admin/Unit/Page.tsx | 14 +++-- src/Pages/Admin/User/Page.tsx | 5 +- src/Pages/Admin/lesson/Page.tsx | 20 +++---- src/Pages/Admin/question/Page.tsx | 20 ++++--- src/Pages/Admin/subject/Table/Page.tsx | 14 +++-- src/Pages/Home/Dummy.tsx | 4 +- src/Styles/Layout/PageHeader.scss | 12 +++++ src/Styles/Pages/exercise.scss | 13 ++++- src/translate/ar.json | 52 +++++++++---------- 19 files changed, 171 insertions(+), 86 deletions(-) create mode 100644 src/Layout/Dashboard/PageTitle.tsx diff --git a/src/Components/ValidationField/utils/ValidationField.scss b/src/Components/ValidationField/utils/ValidationField.scss index 3f797be..d158b96 100644 --- a/src/Components/ValidationField/utils/ValidationField.scss +++ b/src/Components/ValidationField/utils/ValidationField.scss @@ -15,6 +15,8 @@ .text, .ant-form-item { margin-bottom: 7px !important; + font-weight: bold; + font-size: 19px; > span { color: transparent; } @@ -65,3 +67,15 @@ .ant-input-textarea-affix-wrapper.ant-input-affix-wrapper { height: 120px; } + + + +//// malty select +/// + .ant-select-multiple{ + height: auto !important; + min-height: 40px; + .ant-select-selector{ + min-height: 40px; + } + } \ No newline at end of file diff --git a/src/Layout/Dashboard/PageHeader.tsx b/src/Layout/Dashboard/PageHeader.tsx index c1e30dc..85085c8 100644 --- a/src/Layout/Dashboard/PageHeader.tsx +++ b/src/Layout/Dashboard/PageHeader.tsx @@ -1,5 +1,4 @@ -import React from "react"; -import SearchBar from "../../Components/Ui/SearchBar/SearchBar"; + import { Button } from "antd"; import { BsPlusCircleFill } from "react-icons/bs"; import { useNavigate } from "react-router-dom"; @@ -8,8 +7,7 @@ import useModalHandler from "../../utils/useModalHandler"; import { MdOutlineArrowForwardIos } from "react-icons/md"; import { deletePathSegments } from "../../utils/deletePathSegments"; import { getPrevPathRoute } from "../../utils/getPrevPathRoute"; -import { usePageTitleState } from "../../zustand/PageTitleState"; -import FillterForm from "../Ui/FillterForm"; +import PageTitleComponent from "./PageTitle"; const PageHeader = ({ canAdd, @@ -35,20 +33,20 @@ const PageHeader = ({ if (PrevPath === 0) { return; } - navigate(deletePathSegments(location.pathname, PrevPath)); + // navigate(deletePathSegments(location.pathname, PrevPath)); }; const handleNavigateToPage = (location: string) => { - navigate(location); + // navigate(location); }; + console.log(); - const { PageTitle } = usePageTitleState(); return (

{t(`PageTitle.${pageTitle}`)}

- {PageTitle} +
{ addModal ? canAdd && ( diff --git a/src/Layout/Dashboard/PageTitle.tsx b/src/Layout/Dashboard/PageTitle.tsx new file mode 100644 index 0000000..4c3d757 --- /dev/null +++ b/src/Layout/Dashboard/PageTitle.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import { useLocation, useNavigate } from 'react-router-dom' +import { usePageTitleState } from '../../zustand/PageTitleState' + +const PageTitleComponent = () => { + + const {PageTitle,setPageTitle} = usePageTitleState() + const navigate = useNavigate() + const location = useLocation() + const handleNavigate = (path:string)=>{ + const currentPath = location.pathname ; + const newPath = currentPath?.split(path)?.[0] + path ; + if(newPath !== currentPath){ + navigate(newPath) + } + } + return ( +
+ {(Array.isArray(PageTitle) ? PageTitle : [])?.map((item,index)=>{ + return ( +
handleNavigate(item?.path)}> + {item?.name} / +
+ ) + })} +
+ ) +} + +export default PageTitleComponent \ No newline at end of file diff --git a/src/Pages/Admin/Grade/Page.tsx b/src/Pages/Admin/Grade/Page.tsx index 05bf248..b068d9b 100644 --- a/src/Pages/Admin/Grade/Page.tsx +++ b/src/Pages/Admin/Grade/Page.tsx @@ -20,7 +20,10 @@ const TableHeader = () => { const [t] = useTranslation(); const deleteMutation = useDeleteGrade(); - useSetPageTitle(t(`page_header.grade`)); + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.grade`)}`, path:"grade"} + ]); return (
diff --git a/src/Pages/Admin/Param/Page.tsx b/src/Pages/Admin/Param/Page.tsx index 183af03..63b0320 100644 --- a/src/Pages/Admin/Param/Page.tsx +++ b/src/Pages/Admin/Param/Page.tsx @@ -18,7 +18,11 @@ const DeleteModalForm = lazy( const TableHeader = () => { const [t] = useTranslation(); - useSetPageTitle(t(`page_header.param`)); + + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.param`)}`, path:"param"} + ]); const deleteMutation = useDeleteParam(); return (
diff --git a/src/Pages/Admin/QuestionBank/Page.tsx b/src/Pages/Admin/QuestionBank/Page.tsx index e905425..91c7f43 100644 --- a/src/Pages/Admin/QuestionBank/Page.tsx +++ b/src/Pages/Admin/QuestionBank/Page.tsx @@ -20,8 +20,11 @@ const TableHeader = () => { const [t] = useTranslation(); const deleteMutation = useDeleteQuestion(); - useSetPageTitle(t(`page_header.QuestionBank`)); + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.Question`)}`, path:"Question"} + ]); return (
}> diff --git a/src/Pages/Admin/Report/Page.tsx b/src/Pages/Admin/Report/Page.tsx index 8904c4d..33d9d49 100644 --- a/src/Pages/Admin/Report/Page.tsx +++ b/src/Pages/Admin/Report/Page.tsx @@ -21,9 +21,12 @@ const SearchField = lazy( ); const TableHeader = () => { - const { handel_open_model } = useModalHandler(); const [t] = useTranslation(); - useSetPageTitle(t(`page_header.report`)); + + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.report`)}`, path:"report"} + ]); const deleteMutation = useDeleteTag(); return (
diff --git a/src/Pages/Admin/Reseller/Page.tsx b/src/Pages/Admin/Reseller/Page.tsx index 2f3b885..fab96da 100644 --- a/src/Pages/Admin/Reseller/Page.tsx +++ b/src/Pages/Admin/Reseller/Page.tsx @@ -24,7 +24,10 @@ const SearchField = lazy( const TableHeader = () => { const [t] = useTranslation(); - useSetPageTitle(t(`page_header.reseller`)); + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.reseller`)}`, path:"reseller"} + ]); const deleteMutation = useDeleteTag(); return (
diff --git a/src/Pages/Admin/Student/Page.tsx b/src/Pages/Admin/Student/Page.tsx index 24693aa..cc7b8a5 100644 --- a/src/Pages/Admin/Student/Page.tsx +++ b/src/Pages/Admin/Student/Page.tsx @@ -20,8 +20,10 @@ const TableHeader = () => { const [t] = useTranslation(); const deleteMutation = useDeleteStudent(); - useSetPageTitle(t(`page_header.student`)); - + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.student`)}`, path:"student"} + ]); return (
}> diff --git a/src/Pages/Admin/Tags/Page.tsx b/src/Pages/Admin/Tags/Page.tsx index 116abe5..2b61ec2 100644 --- a/src/Pages/Admin/Tags/Page.tsx +++ b/src/Pages/Admin/Tags/Page.tsx @@ -16,14 +16,15 @@ const EditModalForm = lazy(() => import("./Model/EditModel")); const DeleteModalForm = lazy( () => import("../../../Layout/Dashboard/DeleteModels"), ); -const SearchField = lazy( - () => import("../../../Components/DataTable/SearchField"), -); const TableHeader = () => { - const { handel_open_model } = useModalHandler(); const [t] = useTranslation(); - useSetPageTitle(t(`page_header.tags`)); + + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.tags`)}`, path:"tag"} + ]); + const deleteMutation = useDeleteTag(); return (
diff --git a/src/Pages/Admin/Unit/Page.tsx b/src/Pages/Admin/Unit/Page.tsx index f1a312e..9011f94 100644 --- a/src/Pages/Admin/Unit/Page.tsx +++ b/src/Pages/Admin/Unit/Page.tsx @@ -35,15 +35,13 @@ const TableHeader = () => { }); const gradeName = grade?.data?.name ?? ""; - const SubjectName = Subject?.data?.name ?? ""; - useSetPageTitle( - t(`page_header.grade`) + - " / " + - ` ${t("header.subject_of_class")} (${gradeName})` + - " / " + - SubjectName, - ); + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.grade`)}`, path:"grade"}, + {name:` ${t("header.subject_of_class")} (${gradeName})`, path:`grade/${grade_id}`}, + {name:SubjectName, path:`subject/${subject_id}`} + ]); return (
diff --git a/src/Pages/Admin/User/Page.tsx b/src/Pages/Admin/User/Page.tsx index fa14056..83a8f2f 100644 --- a/src/Pages/Admin/User/Page.tsx +++ b/src/Pages/Admin/User/Page.tsx @@ -18,7 +18,10 @@ const DeleteModalForm = lazy( const TableHeader = () => { const [t] = useTranslation(); - useSetPageTitle(t(`page_header.user`)); + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.user`)}`, path:"user"} + ]); const deleteMutation = useDeleteUser(); return (
diff --git a/src/Pages/Admin/lesson/Page.tsx b/src/Pages/Admin/lesson/Page.tsx index ffc67f3..52f1781 100644 --- a/src/Pages/Admin/lesson/Page.tsx +++ b/src/Pages/Admin/lesson/Page.tsx @@ -26,7 +26,7 @@ const TableHeader = () => { const [t] = useTranslation(); const deleteMutation = useDeleteLesson(); - const { unit_id, curriculum_id, grade_id, subject_id } = + const { unit_id, grade_id, subject_id } = useParams(); const { data: unit } = useGetAllUnit({ show: unit_id }); @@ -41,15 +41,15 @@ const TableHeader = () => { const SubjectName = Subject?.data?.name ?? ""; const unitName = unit?.data?.name ?? ""; - useSetPageTitle( - t(`page_header.grade`) + - " / " + - ` ${t("header.subject_of_class")} (${gradeName})` + - " / " + - SubjectName + - " / " + - unitName, - ); + + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.grade`)}`, path:"grade"}, + {name:` ${t("header.subject_of_class")} (${gradeName})`, path:`grade/${grade_id}`}, + {name:SubjectName, path:`subject/${subject_id}`}, + {name:unitName, path:`unit/${unit_id}`} + ]); + return (
diff --git a/src/Pages/Admin/question/Page.tsx b/src/Pages/Admin/question/Page.tsx index 244d272..6584a49 100644 --- a/src/Pages/Admin/question/Page.tsx +++ b/src/Pages/Admin/question/Page.tsx @@ -42,17 +42,15 @@ const TableHeader = () => { const unitName = unit?.data?.name ?? ""; const LessonName = Lesson?.data?.name ?? ""; - useSetPageTitle( - t(`page_header.grade`) + - " / " + - ` ${t("header.subject_of_class")} (${gradeName})` + - " / " + - SubjectName + - " / " + - unitName + - " / " + - LessonName, - ); + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.grade`)}`, path:"grade"}, + {name:` ${t("header.subject_of_class")} (${gradeName})`, path:`grade/${grade_id}`}, + {name:SubjectName, path:`subject/${subject_id}`}, + {name:unitName, path:`unit/${unit_id}`}, + {name:LessonName, path:`lesson/${lesson_id }`} + ]); + return (
diff --git a/src/Pages/Admin/subject/Table/Page.tsx b/src/Pages/Admin/subject/Table/Page.tsx index 5eb9789..03addb0 100644 --- a/src/Pages/Admin/subject/Table/Page.tsx +++ b/src/Pages/Admin/subject/Table/Page.tsx @@ -32,11 +32,15 @@ const TableWithHeader = () => { }); const gradeName = grade?.data?.name ?? ""; - useSetPageTitle( - t(`page_header.grade`) + - " / " + - ` ${t("header.subject_of_class")} (${gradeName})`, - ); + + + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.grade`)}`, path:"grade"}, + {name:` ${t("header.subject_of_class")} (${gradeName})`, path:`grade/${grade_id}`} + ]); + + return (
diff --git a/src/Pages/Home/Dummy.tsx b/src/Pages/Home/Dummy.tsx index cbf55f7..0776ba5 100644 --- a/src/Pages/Home/Dummy.tsx +++ b/src/Pages/Home/Dummy.tsx @@ -4,6 +4,7 @@ import { ABILITIES_ENUM } from "../../enums/abilities"; import useSetPageTitle from "../../Hooks/useSetPageTitle"; import useFilter from "../../Components/FilterField/components/useFilter"; import { Button, Popconfirm } from "antd"; +import PageTitle from "../../Layout/Dashboard/PageTitle"; const Dummy = () => { const [t] = useTranslation(); @@ -11,8 +12,7 @@ const Dummy = () => { const { FilterButton, FilterBody } = useFilter(); return (
- {/* - karim */} +
); diff --git a/src/Styles/Layout/PageHeader.scss b/src/Styles/Layout/PageHeader.scss index e276dba..4368f36 100644 --- a/src/Styles/Layout/PageHeader.scss +++ b/src/Styles/Layout/PageHeader.scss @@ -9,6 +9,9 @@ } .page_links { color: var(--opacity); + display: flex; + align-items: center; + gap: 10px; } } } @@ -16,3 +19,12 @@ .filter_header_top { color: #202c4b; } + + +.PageTitle{ + display: flex; + gap: 10px; + .PageTitleItems{ + cursor: pointer; + } +} \ No newline at end of file diff --git a/src/Styles/Pages/exercise.scss b/src/Styles/Pages/exercise.scss index 5e0736f..2ba2a34 100644 --- a/src/Styles/Pages/exercise.scss +++ b/src/Styles/Pages/exercise.scss @@ -127,12 +127,14 @@ display: flex; justify-content: space-between; width: 100%; - padding: 14px 10px; + padding: 14px 20px; background: #f2f4f8; border-radius: 10px 10px 0 0; margin: 0 !important; box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.1); - + div{ + margin-left: 25px; + } img { cursor: pointer; } @@ -245,4 +247,11 @@ >header{ padding: 30px 2vw 10px 2vw; } +} + +.SelectTag{ + label{ + font-weight: bold; + font-size: 19px; + } } \ No newline at end of file diff --git a/src/translate/ar.json b/src/translate/ar.json index f81bbce..81c2b58 100644 --- a/src/translate/ar.json +++ b/src/translate/ar.json @@ -798,14 +798,14 @@ "QuestionBank":"بنك الأسئلة" }, "page_header": { - "dashboard": "لوحة القيادة / الصفحة الرئيسية", - "course": " لوحة القيادة / الصفوف ", - "teacher": " لوحة القيادة / المعلمون", - "payment": " لوحة القيادة / الدفعات", - "branch": " لوحة القيادة / الفروع", - "role": " لوحة القيادة / الادوار", - "student": " لوحة القيادة / قائمة الطلاب ", - "admin": " لوحة القيادة / المسؤولون", + "home": "لوحة القيادة", + "course": " الصفوف ", + "teacher": " المعلمون", + "payment": " الدفعات", + "branch": " الفروع", + "role": " الادوار", + "student": " قائمة الطلاب ", + "admin": " المسؤولون", "student_details": "تفاصيل الطالب", "create_student": "إنشاء طالب", "course_details": "تفاصيل الصف", @@ -813,27 +813,27 @@ "student_payment": "دفع الطالب", "student_note": "ملاحظات الطالب", "student_status": "حالة الطالب", - "education_class": "لوحة القيادة / الصفوف / الشعب", - "education_class_details": " لوحة القيادة / الصفوف / الشعب / تفاصيل الشعبة", - "subject_details": " لوحة القيادة / تفاصيل المادة ", - "cycle": "لوحة القيادة / السنة دراسية ", - "term": "لوحة القيادة / الفصل ", - "unit_details": "لوحة القيادة / تفاصيل المادة / تفاصيل الوحدة", - "lesson_details": "لوحة القيادة / تفاصيل المادة / تفاصيل الوحدة / تفاصيل الدرس", - "exercise_add": "لوحة القيادة / تفاصيل الدرس / إضافة تمارين ", - "subject": "لوحة القيادة / المادة", - "tags": "لوحة القيادة / كلمات مفتاحية", - "Question": "لوحة القيادة /اسئلة ", - "add_Question": "لوحة القيادة /إضافة اسئلة ", - "edit_Question": "لوحة القيادة /تعديل اسئلة ", - "grade": "لوحة القيادة / الصفوف", + "education_class": "الصفوف / الشعب", + "education_class_details": " الصفوف / الشعب / تفاصيل الشعبة", + "subject_details": " تفاصيل المادة ", + "cycle": " السنة دراسية ", + "term": "الفصل ", + "unit_details": "تفاصيل المادة / تفاصيل الوحدة", + "lesson_details": "تفاصيل المادة / تفاصيل الوحدة / تفاصيل الدرس", + "exercise_add": "تفاصيل الدرس / إضافة تمارين ", + "subject": "المادة", + "tags": "كلمات مفتاحية", + "Question": "سئلة ", + "add_Question": "ضافة اسئلة ", + "edit_Question": "عديل اسئلة ", + "grade": "الصفوف", "report": "تقرير", - "users": "لوحة القيادة / المستخدمون", - "reseller": " لوحة القيادة / البائعين", - "add_reseller": " لوحة القيادة / البائعين / إضافة بائع ", + "users": "المستخدمون", + "reseller": " البائعين", + "add_reseller": " البائعين / إضافة بائع ", "param": "معامل", "student_package": "حزمة الطالب", - "QuestionBank":"لوحة القيادة / بنك الأسئلة" + "QuestionBank":"بنك الأسئلة" }, "table": { "student": "قائمة الطلاب",