This commit is contained in:
karimaldeen 2024-10-02 17:13:42 +03:00
parent ccbebf99a1
commit 865f785112
31 changed files with 218 additions and 279 deletions

View File

@ -1,24 +1,18 @@
import { create } from "zustand"; import { create } from "zustand";
interface FilterState { interface FilterState {
filterState: any[]; filterState: any;
setFilterState: (data: any) => void; setFilterState: (data: any) => void;
clearFilterState: () => void; clearFilterState: () => void;
setWithOldValue: (data: any) => void; setWithOldValue: (data: any) => void;
setInitialValue: (data: any) => void;
} }
export const useFilterState = create<FilterState>((set, get) => ({ export const useFilterState = create<FilterState>((set, get) => ({
filterState: [], filterState: {},
setFilterState: (data) => set(() => ({ filterState: data })), setFilterState: (data) => set(() => ({ filterState: data })),
clearFilterState: () => set(() => ({ filterState: [] })), clearFilterState: () => set(() => ({ filterState: [] })),
setWithOldValue: (data) => setWithOldValue: (data) =>
set((state) => ({ filterState: [...state.filterState, data] })), set((state) => ({ filterState: [...state.filterState, data] })),
setInitialValue: (data) => {
if (get().filterState.length < 1) {
set(() => ({ filterState: data }));
}
},
})); }));
// import { create } from "zustand"; // import { create } from "zustand";

View File

@ -48,8 +48,14 @@ const SearchField = ({
} }
}, [page]); }, [page]);
const SelectableChange = (value: any) => { const SelectableChange = (value: any,option:any) => {
formik?.setFieldValue(name, value); if(isMulti){
formik?.setFieldValue(name, option ?? []);
}else{
formik?.setFieldValue(name, option ?? {});
}
const isCleared = value?.length === 0 || !value; const isCleared = value?.length === 0 || !value;
if (isCleared) { if (isCleared) {
@ -90,7 +96,7 @@ const SearchField = ({
const handleScroll = (event: any) => { const handleScroll = (event: any) => {
const target = event.target; const target = event.target;
const isAtBottom = const isAtBottom =
target.scrollHeight === target.scrollTop + target.clientHeight; target.scrollHeight - 10 <= Math.floor(target.scrollTop + target.clientHeight);
if (isAtBottom && canChangePage && PageName && page) { if (isAtBottom && canChangePage && PageName && page) {
console.log("Scrolled to the last option!"); console.log("Scrolled to the last option!");
@ -103,6 +109,10 @@ const SearchField = ({
console.log(AllPagesOption); console.log(AllPagesOption);
console.log(option, "option"); console.log(option, "option");
const value = isMulti ? formik.values[name]?.map((item:any)=>{
return item?.name ?? item
}) : formik.values[name]?.["name"] ?? ""
console.log(value);
return ( return (
<div className="ValidationField w-100"> <div className="ValidationField w-100">
@ -121,8 +131,8 @@ const SearchField = ({
options={AllPagesOption} options={AllPagesOption}
size="large" size="large"
className={`${className} w-100`} className={`${className} w-100`}
value={formik.values[name]} value={value}
// loading={isLoading} loading={isLoading}
allowClear allowClear
{...(isMulti && { mode: "multiple" })} {...(isMulti && { mode: "multiple" })}
onChange={onChange || SelectableChange} onChange={onChange || SelectableChange}
@ -133,7 +143,7 @@ const SearchField = ({
onBlur={handleBlur} onBlur={handleBlur}
id={name} id={name}
onPopupScroll={handleScroll} onPopupScroll={handleScroll}
fieldNames={{ label: "name", value: "id" }} fieldNames={{ label: "name", value: "name" }}
{...props} {...props}
/> />
</ValidationFieldContainer> </ValidationFieldContainer>

View File

@ -6,6 +6,7 @@ import { QueryStatusEnum } from "../../../../enums/QueryStatus";
import ModelForm from "./ModelForm"; import ModelForm from "./ModelForm";
import { useAddCoupon } from "../../../../api/Coupon"; import { useAddCoupon } from "../../../../api/Coupon";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { ConvertArrayToArrayOfIds } from "../../../../utils/ConvertArrayToArrayOfIds";
const AddModel: React.FC = () => { const AddModel: React.FC = () => {
const { mutate, status } = useAddCoupon(); const { mutate, status } = useAddCoupon();
@ -16,7 +17,10 @@ const AddModel: React.FC = () => {
console.log(due_to); console.log(due_to);
mutate({ mutate({
...values, ...values,
due_to due_to,
grade_id:values?.grade_id?.id
}); });
}; };
return ( return (

View File

@ -6,7 +6,6 @@ import ModelForm from "./ModelForm";
import { QueryStatusEnum } from "../../../../enums/QueryStatus"; import { QueryStatusEnum } from "../../../../enums/QueryStatus";
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState"; import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
import { useUpdateCoupon } from "../../../../api/Coupon"; import { useUpdateCoupon } from "../../../../api/Coupon";
import { handelImageState } from "../../../../utils/DataToSendImageState";
const EditModel: React.FC = () => { const EditModel: React.FC = () => {
const { mutate, status } = useUpdateCoupon(); const { mutate, status } = useUpdateCoupon();
@ -14,7 +13,7 @@ const EditModel: React.FC = () => {
const handleSubmit = (values: any) => { const handleSubmit = (values: any) => {
const due_to = typeof values?.due_to === "string" ? values?.due_to : values?.due_to.format("YYYY-MM-DD HH:mm:ss") const due_to = typeof values?.due_to === "string" ? values?.due_to : values?.due_to.format("YYYY-MM-DD HH:mm:ss")
const Data_to_send = { ...values , due_to }; const Data_to_send = { ...values , due_to, grade_id:values?.grade_id?.id ?? "" };
mutate(Data_to_send); mutate(Data_to_send);
}; };

View File

@ -18,7 +18,7 @@ const Form = ({Hide = false}:{Hide?:boolean }) => {
}); });
const GradeOption = Grade?.data ?? [] const GradeOption = Grade?.data ?? []
const canChangeGradePage = !!Grade?.links?.next; const canChangeGradePage = !!Grade?.links?.next;
const GradePage = Grade?.meta?.currentPage; const GradePage = Grade?.meta?.current_page;
return ( return (
<Row className="w-100"> <Row className="w-100">
<Col> <Col>

View File

@ -11,7 +11,7 @@ export const getInitialValues = (
amount: objectToEdit?.amount ?? "", amount: objectToEdit?.amount ?? "",
code: objectToEdit?.code ?? "", code: objectToEdit?.code ?? "",
due_to: objectToEdit?.due_to ? dayjs(objectToEdit?.due_to,"YYYY-MM-DD HH:mm:ss") : "", due_to: objectToEdit?.due_to ? dayjs(objectToEdit?.due_to,"YYYY-MM-DD HH:mm:ss") : "",
grade_id: objectToEdit?.grade_id ?? "", grade_id: objectToEdit?.grade ?? "",
}; };
}; };

View File

@ -12,6 +12,7 @@ const AddModel: React.FC = () => {
const handleSubmit = (values: any) => { const handleSubmit = (values: any) => {
mutate({ mutate({
...values, ...values,
grade_id:values?.grade_id?.id
}); });
}; };
return ( return (

View File

@ -12,7 +12,7 @@ const EditModel: React.FC = () => {
const { objectToEdit } = useObjectToEdit((state) => state); const { objectToEdit } = useObjectToEdit((state) => state);
const handleSubmit = (values: any) => { const handleSubmit = (values: any) => {
const Data_to_send = { ...values }; const Data_to_send = { ...values, grade_id:values?.grade_id?.id };
mutate(Data_to_send); mutate(Data_to_send);
}; };

View File

@ -13,7 +13,7 @@ const Form = ({ isEdit = false }: { isEdit?: boolean }) => {
}); });
const GradeOption = Grade?.data ?? []; const GradeOption = Grade?.data ?? [];
const canChangeGradePage = !!Grade?.links?.next; const canChangeGradePage = !!Grade?.links?.next;
const GradePage = Grade?.meta?.currentPage; const GradePage = Grade?.meta?.current_page;
const sex = [ const sex = [
{ name: "male", id: "male" }, { name: "male", id: "male" },

View File

@ -30,7 +30,8 @@ const FilterForm = () => {
}); });
const GradeOption = Grade?.data ?? [] const GradeOption = Grade?.data ?? []
const canChangeGradePage = !!Grade?.links?.next; const canChangeGradePage = !!Grade?.links?.next;
const GradePage = Grade?.meta?.currentPage; const GradePage = Grade?.meta?.current_page;
console.log(Grade?.meta?.current_page);
/// subject_id /// subject_id
@ -40,7 +41,7 @@ const FilterForm = () => {
}); });
const SubjectOption = Subject?.data ?? [] const SubjectOption = Subject?.data ?? []
const canChangeSubjectPage = !!Subject?.links?.next; const canChangeSubjectPage = !!Subject?.links?.next;
const SubjectPage = Subject?.meta?.currentPage; const SubjectPage = Subject?.meta?.current_page;
/// unit_id /// unit_id
const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({ const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({
@ -49,7 +50,7 @@ const FilterForm = () => {
}); });
const UnitOption = Unit?.data ?? [] const UnitOption = Unit?.data ?? []
const canChangeUnitPage = !!Unit?.links?.next; const canChangeUnitPage = !!Unit?.links?.next;
const UnitPage = Unit?.meta?.currentPage; const UnitPage = Unit?.meta?.current_page;
/// lessonsIds /// lessonsIds
const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({ const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({
@ -58,7 +59,7 @@ const FilterForm = () => {
}); });
const LessonOption = Lesson?.data ?? [] const LessonOption = Lesson?.data ?? []
const canChangeLessonPage = !!Lesson?.links?.next; const canChangeLessonPage = !!Lesson?.links?.next;
const LessonPage = Lesson?.meta?.currentPage; const LessonPage = Lesson?.meta?.current_page;
/// TagsIds /// TagsIds
@ -68,7 +69,7 @@ const FilterForm = () => {
}); });
const TagOption = Tag?.data ?? [] const TagOption = Tag?.data ?? []
const canChangeTagPage = !!Tag?.links?.next; const canChangeTagPage = !!Tag?.links?.next;
const TagPage = Tag?.meta?.currentPage; const TagPage = Tag?.meta?.current_page;
return ( return (
@ -89,6 +90,7 @@ const FilterForm = () => {
PageName={"GradeCurrentPage"} PageName={"GradeCurrentPage"}
page={GradePage} page={GradePage}
/> />

View File

@ -7,7 +7,6 @@ import { useDeleteQuestion } from "../../../api/Question";
import PageHeader from "../../../Layout/Dashboard/PageHeader"; import PageHeader from "../../../Layout/Dashboard/PageHeader";
import FilterLayout from "../../../Layout/Dashboard/FilterLayout"; import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
import FilterForm from "./Model/FilterForm"; import FilterForm from "./Model/FilterForm";
import { canAddQuestionBank } from "../../../utils/hasAbilityFn";
const Table = lazy(() => import("./Table")); const Table = lazy(() => import("./Table"));
const DeleteModalForm = lazy( const DeleteModalForm = lazy(

View File

@ -5,6 +5,7 @@ import { useGetAllQuestion } from "../../../api/Question";
import { useFilterState } from "../../../Components/Utils/Filter/FilterState"; import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
import { useFilterStateState } from "../../../zustand/Filter"; import { useFilterStateState } from "../../../zustand/Filter";
import { ConvertArrayToArrayOfIds } from "../../../utils/ConvertArrayToArrayOfIds";
const App: React.FC = () => { const App: React.FC = () => {
const { filterState } = useFilterState(); const { filterState } = useFilterState();
@ -17,6 +18,11 @@ const App: React.FC = () => {
nullable_parent:"null", nullable_parent:"null",
pagination: true, pagination: true,
...filterState, ...filterState,
tagsIds:ConvertArrayToArrayOfIds(filterState?.tagsIds) ,
grade_id:filterState?.grade_id?.id,
subject_id:filterState?.subject_id?.id,
unit_id:filterState?.unit_id?.id,
lessonsIds:ConvertArrayToArrayOfIds(filterState?.lessonsIds),
content:Filter?.content, content:Filter?.content,
sort_by, sort_by,

View File

@ -69,19 +69,66 @@ export const useColumns = () => {
}, },
ellipsis: true, ellipsis: true,
}, },
{ {
title: `${t("columns.hint")}`, title: `${t("columns.subject")}`,
dataIndex: "hint", dataIndex: "lessons",
key: "hint", key: "lessons",
align: "center", align: "center",
render: (text, record) => { render: (text, record) => {
const lesson = record?.lessons?.[0] ;
const unit = lesson?.unit;
const subject = unit?.subject;
return ( return (
<>{record?.hint ?? "_"}</> <> {subject?.name} </>
); )
}, },
ellipsis: true, ellipsis: true,
}, },
{
title: `${t("columns.unit")}`,
dataIndex: "lessons",
key: "lessons",
align: "center",
render: (text, record) => {
const lesson = record?.lessons?.[0] ;
const unit = lesson?.unit;
return (
<> {unit?.name} </>
)
},
ellipsis: true,
},
{
title: `${t("columns.lesson")}`,
dataIndex: "lessons",
key: "lessons",
align: "center",
render: (text, record) => {
const lesson = record?.lessons?.[0] ;
console.log(lesson,"lesson");
return (
<> {lesson?.name} </>
)
},
ellipsis: true,
},
// {
// title: `${t("columns.hint")}`,
// dataIndex: "hint",
// key: "hint",
// align: "center",
// render: (text, record) => {
// return (
// <>{record?.hint ?? "_"}</>
// );
// },
// ellipsis: true,
// },
{ {
title: `${t("columns.tags")}`, title: `${t("columns.tags")}`,
dataIndex: "tags", dataIndex: "tags",

View File

@ -13,7 +13,7 @@ const Form = ({ isEdit = false }: { isEdit?: boolean }) => {
}); });
const GradeOption = Grade?.data ?? []; const GradeOption = Grade?.data ?? [];
const canChangeGradePage = !!Grade?.links?.next; const canChangeGradePage = !!Grade?.links?.next;
const GradePage = Grade?.meta?.currentPage; const GradePage = Grade?.meta?.current_page;
const sex = [ const sex = [
{ name: "male", id: "male" }, { name: "male", id: "male" },

View File

@ -19,6 +19,7 @@ const App: React.FC = () => {
sort_by, sort_by,
pagination: true, pagination: true,
...filterState, ...filterState,
grade_id:filterState?.grade_id?.id,
}); });
return <DataTable response={response} useColumns={useColumns} />; return <DataTable response={response} useColumns={useColumns} />;

View File

@ -9,10 +9,7 @@ import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
import { Question } from "../../../types/Item"; import { Question } from "../../../types/Item";
import BaseFormContainer from "./Model/AddForm/BaseForm"; import BaseFormContainer from "./Model/AddForm/BaseForm";
import FormContainer from "./Model/AddForm/Form"; import FormContainer from "./Model/AddForm/Form";
import { handleValidateBaseQuestion, handleValidateSingleQuestion } from "./Model/AddForm/ValidationFn"; import { handleValidateBaseQuestion, handleValidateSingleQuestion } from "./Model/ValidationFn";
import useUnsavedChangesWarning from "../../../Hooks/useUnsavedChangesWarning";
import { useFormikContext } from "formik";
const AddPage: React.FC = () => { const AddPage: React.FC = () => {
const { mutateAsync, isLoading: LoadingAsync } = useAddQuestionAsync(); const { mutateAsync, isLoading: LoadingAsync } = useAddQuestionAsync();

View File

@ -19,27 +19,29 @@ import { toast } from "react-toastify";
import { deletePathSegments } from "../../../utils/deletePathSegments"; import { deletePathSegments } from "../../../utils/deletePathSegments";
import BaseFormContainer from "./Model/EditForm/BaseFormContainer"; import BaseFormContainer from "./Model/EditForm/BaseFormContainer";
import FormContainer from "./Model/EditForm/FormContainer"; import FormContainer from "./Model/EditForm/FormContainer";
import { handleValidateBaseQuestion, handleValidateSingleQuestion } from "./Model/ValidationFn";
const EditPage: React.FC = () => { const EditPage: React.FC = () => {
const { subject_id, lesson_id, question_id } = useParams<ParamsEnum>(); const { subject_id, lesson_id, question_id } = useParams<ParamsEnum>();
const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions, ShowHint, setShowHint, ShowLatexOption, setShowLatexOption } = const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions,setObjectToEdit } =
useObjectToEdit(); useObjectToEdit();
const { mutate, isSuccess, isLoading } = useUpdateQuestion(); const { mutate, isSuccess ,isLoading:isLoadingUpdate } = useUpdateQuestion();
const { mutate: DeleteQuestion } = useDeleteQuestion(); const { mutate: DeleteQuestion } = useDeleteQuestion();
const { mutate: mutateAdd, isLoading: LoadingAsync } = useAddQuestion(); const { mutate: mutateAdd } = useAddQuestion();
const { data, isLoading: dataLoading } = useGetAllQuestion({ const { data, isLoading: dataLoading ,isRefetching } = useGetAllQuestion({
show: question_id, show: question_id,
}); });
const { data: Questions, isLoading: QuestionsDataLoading } = const { data: Questions, isLoading: QuestionsDataLoading,isRefetching:isRefetchingParent } =
useGetAllQuestion({ useGetAllQuestion({
parent_id: question_id, parent_id: question_id,
isPaginated: false isPaginated: false
}); });
const objectToEdit = { ...data?.data, Questions: Questions?.data }; const objectToEdit = { ...data?.data, Questions: Questions?.data };
console.log(objectToEdit);
useEffect(() => { useEffect(() => {
if (objectToEdit?.isBase && isBseQuestion !== true) { if (objectToEdit?.isBase && isBseQuestion !== true) {
@ -175,136 +177,39 @@ const EditPage: React.FC = () => {
} }
}; };
const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const handleValidateSingleQuestion = (values: any, isValid: boolean, handleSubmit: any) => {
const haveMoreThanOneAnswer = values?.answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true)
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item: any) => !(item?.content) && !(item.content_image))
const content = values.content;
const content_image = values.content_image;
const haveContentOrContentImage = !!content || !!content_image;
console.log(haveImageOrContent, "haveImageOrContent");
if (!haveContentOrContentImage) {
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
if (!haveMoreThanOneAnswer) {
toast.error(t("validation.it_should_have_more_than_one_answers"));
return false;
}
if (!haveOneAnswerRight) {
toast.error(t("validation.it_should_have_more_than_one_correct_answers"));
return false;
}
if (haveImageOrContent) {
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
return false
}
console.log(1);
if (isValid) {
handleSubmit(values)
}
}
const handleValidateBaseQuestion = (values: any, isValid: boolean, handleSubmit: any) => {
const content = values.content;
const content_image = values.content_image;
const haveContentOrContentImage = !!content || !!content_image;
console.log(2);
if (!haveContentOrContentImage) {
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
console.log(1);
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
const content = Question.content;
const content_image = Question.content_image;
const haveContentOrContentImage = !!content || !!content_image;
if (!haveContentOrContentImage) {
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
//// answers
const answers = Question?.answers;
const haveAnswers = answers?.length > 0;
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
const haveImageOrContent = haveOneAnswerRight && answers?.some((item: any) => !(item?.content) && !(item.content_image))
if (!haveAnswers) {
toast.error(t("validation.it_should_have_more_than_one_answers"));
return false;
}
if (!haveMoreThanOneAnswer) {
toast.error(t("validation.it_should_have_more_than_one_answers"));
return false;
}
if (!haveOneAnswerRight) {
toast.error(t("validation.it_should_have_more_than_one_correct_answers"));
return false;
}
if (haveImageOrContent) {
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
return false
}
return true
});
console.log(1);
if (isValid && isValidate) {
console.log(2);
handleSubmit(values)
}
};
useEffect(() => { useEffect(() => {
console.log(location.pathname);
console.log(deletePathSegments(location.pathname, 2));
if (isSuccess) { if (isSuccess) {
toast.success(t("validation.the_possess_done_successful")); // toast.success(t("validation.the_possess_done_successful"));
setObjectToEdit(null)
navigate(-1); navigate(-1);
} }
}, [isSuccess]); }, [isSuccess]);
const Loading = LoadingAsync || isLoading console.log(objectToEdit);
if (dataLoading || QuestionsDataLoading) {
const Loading = QuestionsDataLoading || dataLoading || isRefetchingParent || isRefetching
console.log(Loading);
const LoadingButton = isLoadingUpdate
if (Loading) {
return <SpinContainer />; return <SpinContainer />;
} }
if (objectToEdit?.isBase) { if (objectToEdit?.isBase) {
return ( return (
<BaseFormContainer t={t} Loading={Loading} handleSubmit={handleSubmit} handleValidateBaseQuestion={handleValidateBaseQuestion} objectToEdit={objectToEdit} /> <BaseFormContainer t={t} Loading={LoadingButton} handleSubmit={handleSubmit} handleValidateBaseQuestion={handleValidateBaseQuestion} objectToEdit={objectToEdit} />
); );
} }
return ( return (
<FormContainer t={t} Loading={Loading} handleSubmit={handleSubmit} handleValidateSingleQuestion={handleValidateSingleQuestion} objectToEdit={objectToEdit} /> <FormContainer t={t} Loading={LoadingButton} handleSubmit={handleSubmit} handleValidateSingleQuestion={handleValidateSingleQuestion} objectToEdit={objectToEdit} />
); );
}; };

View File

@ -28,7 +28,7 @@ const FilterForm = () => {
}); });
const GradeOption = Grade?.data ?? [] const GradeOption = Grade?.data ?? []
const canChangeGradePage = !!Grade?.links?.next; const canChangeGradePage = !!Grade?.links?.next;
const GradePage = Grade?.meta?.currentPage; const GradePage = Grade?.meta?.current_page;
/// subject_id /// subject_id
@ -38,7 +38,7 @@ const FilterForm = () => {
}); });
const SubjectOption = Subject?.data ?? [] const SubjectOption = Subject?.data ?? []
const canChangeSubjectPage = !!Subject?.links?.next; const canChangeSubjectPage = !!Subject?.links?.next;
const SubjectPage = Subject?.meta?.currentPage; const SubjectPage = Subject?.meta?.current_page;
/// unit_id /// unit_id
const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({ const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({
@ -47,7 +47,7 @@ const FilterForm = () => {
}); });
const UnitOption = Unit?.data ?? [] const UnitOption = Unit?.data ?? []
const canChangeUnitPage = !!Unit?.links?.next; const canChangeUnitPage = !!Unit?.links?.next;
const UnitPage = Unit?.meta?.currentPage; const UnitPage = Unit?.meta?.current_page;
/// lessonsIds /// lessonsIds
const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({ const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({
@ -56,7 +56,7 @@ const FilterForm = () => {
}); });
const LessonOption = Lesson?.data ?? [] const LessonOption = Lesson?.data ?? []
const canChangeLessonPage = !!Lesson?.links?.next; const canChangeLessonPage = !!Lesson?.links?.next;
const LessonPage = Lesson?.meta?.currentPage; const LessonPage = Lesson?.meta?.current_page;
return ( return (
<div> <div>

View File

@ -13,9 +13,10 @@ import ModelForm from "../../Model/Malty/Form";
const BaseFormContainer = ({objectToEdit,handleSubmit,Loading,handleValidateBaseQuestion,t}:{objectToEdit:any,handleSubmit:any,Loading:any,handleValidateBaseQuestion:any,t:any}) => { const BaseFormContainer = ({objectToEdit,handleSubmit,Loading,handleValidateBaseQuestion,t}:{objectToEdit:any,handleSubmit:any,Loading:any,handleValidateBaseQuestion:any,t:any}) => {
const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const { ShowHint,setShowHint , ShowLatexOption,setShowLatexOption } = const { ShowHint,setShowHint , ShowLatexOption,setShowLatexOption ,setObjectToEdit} =
useObjectToEdit(); useObjectToEdit();
const handleCancel = () => { const handleCancel = () => {
setObjectToEdit({})
navigate(-1); navigate(-1);
}; };
const handleNavigateToPage = () => { const handleNavigateToPage = () => {
@ -84,8 +85,8 @@ const BaseFormContainer = ({objectToEdit,handleSubmit,Loading,handleValidateBase
<div className="exercise_add_buttons"> <div className="exercise_add_buttons">
<div onClick={handleCancel}>{t("practical.back")}</div> <div onClick={handleCancel}>{t("practical.back")}</div>
<button disabled={Loading} className={`relative ${dirty ? "" : "disabled"}`} type="button" <button disabled={Loading} className={`relative ${dirty ? "" : "disabled"}`} type="button"
onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }} onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit,t) }}
onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }} onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit,t) }}
> {t("practical.edit")} > {t("practical.edit")}
{Loading && ( {Loading && (

View File

@ -13,13 +13,15 @@ import ModelForm from "../../Model/ModelForm";
const FormContainer = ({objectToEdit,handleSubmit,Loading,handleValidateSingleQuestion,t}:{objectToEdit:any,handleSubmit:any,Loading:any,handleValidateSingleQuestion:any,t:any}) => { const FormContainer = ({objectToEdit,handleSubmit,Loading,handleValidateSingleQuestion,t}:{objectToEdit:any,handleSubmit:any,Loading:any,handleValidateSingleQuestion:any,t:any}) => {
const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const { ShowHint,setShowHint , ShowLatexOption,setShowLatexOption } = const { ShowHint,setShowHint , ShowLatexOption,setShowLatexOption,setObjectToEdit } =
useObjectToEdit(); useObjectToEdit();
const handleCancel = () => { const handleCancel = () => {
setObjectToEdit({})
navigate(-1); navigate(-1);
}; };
const handleNavigateToPage = () => { const handleNavigateToPage = () => {
const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, ""); const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, "");
setObjectToEdit({})
navigate(cleanedUrl); navigate(cleanedUrl);
}; };

View File

@ -1,100 +0,0 @@
import { toast } from "react-toastify";
export const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any,t:any)=>{
const haveMoreThanOneAnswer = values?.answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
const content = values.content ;
const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ;
console.log(haveImageOrContent,"haveImageOrContent");
if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
if(!haveMoreThanOneAnswer){
toast.error(t("validation.it_should_have_more_than_one_answers")) ;
return false ;
}
if(!haveOneAnswerRight){
toast.error(t("validation.it_should_have_more_than_one_correct_answers")) ;
return false ;
}
if(haveImageOrContent){
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
return false
}
console.log(1);
if(isValid){
handleSubmit(values)
}
}
export const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any,t:any) => {
const content = values.content ;
const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ;
console.log(2);
if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
console.log(1);
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
const content = Question.content ;
const content_image = Question.content_image ;
const haveContentOrContentImage = !!content || !!content_image ;
if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
//// answers
const answers = Question?.answers;
const haveAnswers = answers?.length > 0;
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
if (!haveAnswers) {
toast.error(t("validation.it_should_have_more_than_one_answers"));
return false;
}
if (!haveMoreThanOneAnswer) {
toast.error(t("validation.it_should_have_more_than_one_answers"));
return false;
}
if (!haveOneAnswerRight) {
toast.error(t("validation.it_should_have_more_than_one_correct_answers"));
return false;
}
if(haveImageOrContent){
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
return false
}
return true
});
console.log(1);
if(isValid && isValidate){
console.log(2);
handleSubmit(values)
}
};

View File

@ -1,9 +1,13 @@
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { hasDuplicateArrayValue } from "../../../../utils/hasDuplicateArrayValue";
export const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any,t:any)=>{ export const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any,t:any)=>{
const haveMoreThanOneAnswer = values?.answers?.length > 1; const haveMoreThanOneAnswer = values?.answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true ) const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) ) const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
const haveDuplicatedContent = hasDuplicateArrayValue(values?.answers,"content")
const content = values.content ; const content = values.content ;
const content_image = values.content_image ; const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ; const haveContentOrContentImage = !!content || !!content_image ;
@ -25,8 +29,11 @@ export const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSu
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer")) toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
return false return false
} }
if(haveDuplicatedContent){
toast.error(t("validation.haveDuplicatedContent"))
return false
}
console.log(1);
if(isValid){ if(isValid){
handleSubmit(values) handleSubmit(values)
@ -37,12 +44,18 @@ export const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSub
const content = values.content ; const content = values.content ;
const content_image = values.content_image ; const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ; const haveContentOrContentImage = !!content || !!content_image ;
console.log(2); const haveDuplicatedContent = hasDuplicateArrayValue(values?.Questions,"content")
if(!haveContentOrContentImage){ if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`); toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false; return false;
} }
if(haveDuplicatedContent){
toast.error(t("validation.haveDuplicatedContent"))
return false
}
console.log(1); console.log(1);
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => { const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
@ -51,6 +64,7 @@ export const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSub
const content = Question.content ; const content = Question.content ;
const content_image = Question.content_image ; const content_image = Question.content_image ;
const haveContentOrContentImage = !!content || !!content_image ; const haveContentOrContentImage = !!content || !!content_image ;
if(!haveContentOrContentImage){ if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`); toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false; return false;
@ -63,7 +77,10 @@ export const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSub
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1; const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true); const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) ) const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
const haveDuplicatedContent = hasDuplicateArrayValue(answers,"content")
console.log(haveDuplicatedContent);
console.log(answers);
@ -87,6 +104,11 @@ export const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSub
return false return false
} }
if(haveDuplicatedContent){
toast.error(t("validation.haveDuplicatedContent"))
return false
}
return true return true
}); });

View File

@ -1,5 +1,5 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { lazy, Suspense } from "react"; import { lazy, Suspense, useEffect } from "react";
import { Spin } from "antd"; import { Spin } from "antd";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { ParamsEnum } from "../../../enums/params"; import { ParamsEnum } from "../../../enums/params";
@ -16,6 +16,7 @@ import { ABILITIES_ENUM } from "../../../enums/abilities";
import { canAddQuestion } from "../../../utils/hasAbilityFn"; import { canAddQuestion } from "../../../utils/hasAbilityFn";
import FilterLayout from "../../../Layout/Dashboard/FilterLayout"; import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
import FilterForm from "./FilterForm"; import FilterForm from "./FilterForm";
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
const Table = lazy(() => import("./Table")); const Table = lazy(() => import("./Table"));
const TableHeader = () => { const TableHeader = () => {
@ -50,7 +51,15 @@ const TableHeader = () => {
{name:unitName, path:`unit/${unit_id}`}, {name:unitName, path:`unit/${unit_id}`},
{name:LessonName, path:`lesson/${lesson_id }`} {name:LessonName, path:`lesson/${lesson_id }`}
]); ]);
const { objectToEdit,setObjectToEdit } =
useObjectToEdit();
useEffect(() => {
if(objectToEdit){
setObjectToEdit(null)
}
}, [])
console.log(objectToEdit);
return ( return (
<div className="TableWithHeader"> <div className="TableWithHeader">

View File

@ -1,8 +1,13 @@
import { HaveDuplicatedArrayValue } from "../../utils/hasDuplicateArrayValue";
const Dummy = () => { const Dummy = () => {
const isDuplicated = HaveDuplicatedArrayValue([{name:"name"},{name:"name3"},{name:"nam"}],"name")
console.log(isDuplicated,"isDuplicated");
return ( return (
<div className="DummyHomePage"> <div className="DummyHomePage">
karim is op <div>asd</div>
<div> asd </div>
</div> </div>
); );
}; };

View File

@ -3,7 +3,7 @@ import DataTable from "../../../../Layout/Dashboard/Table/DataTable";
import { useColumns } from "./useTableColumns"; import { useColumns } from "./useTableColumns";
import useSearchQuery from "../../../../api/utils/useSearchQuery"; import useSearchQuery from "../../../../api/utils/useSearchQuery";
import { useFilterState } from "../../../../Components/Utils/Filter/FilterState"; import { useFilterState } from "../../../../Components/Utils/Filter/FilterState";
import { useGetCollection } from "../../../../api/collections"; import { useGetAllCollections } from "../../../../api/collections";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
const App: React.FC = () => { const App: React.FC = () => {
@ -12,7 +12,7 @@ const App: React.FC = () => {
const {collection_id}= useParams() const {collection_id}= useParams()
console.log(collection_id); console.log(collection_id);
const response = useGetCollection({ const response = useGetAllCollections({
name: searchQuery, name: searchQuery,
pagination: true, pagination: true,
...filterState, ...filterState,

View File

@ -1,7 +1,8 @@
.DataTable { .DataTable {
width: 100%; width: 100%;
border-radius: 0 0 10px 10px; border-radius: 0 0 10px 10px;
box-shadow: 0px 0px 32px 2px #080F3414; // box-shadow: 0px 0px 32px 2px #080F3414;
} }
.ant-table-cell { .ant-table-cell {

View File

@ -1,7 +1,7 @@
.exercise_form_container { .exercise_form_container {
display: flex; display: flex;
width: 100% !important; width: 100% !important;
padding-top: 10px; padding-block: 10px 30px;
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.1); box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.1);
margin-right: 0px !important; margin-right: 0px !important;
border-radius: 0 0 10px 10px; border-radius: 0 0 10px 10px;
@ -48,6 +48,7 @@
// max-height: 84vh; // max-height: 84vh;
overflow-y: scroll; overflow-y: scroll;
@include Scrollbar(); @include Scrollbar();
overflow-x: hidden;
} }
.exercise_add_buttons { .exercise_add_buttons {
display: flex; display: flex;
@ -59,15 +60,15 @@
outline: none; outline: none;
border: none; border: none;
border-radius: 10px; border-radius: 10px;
padding: 0.4vw 0.2vw; padding: 5px 10px;
background: var(--primary); background: var(--primary);
color: var(--white); color: var(--white);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 5px; gap: 5px;
font-size: 1vw; font-size: 16px;
width: 10vw; min-width: 130px;
cursor: pointer; cursor: pointer;
transition: .5s ease-in-out; transition: .5s ease-in-out;
&:hover{ &:hover{

View File

@ -55,7 +55,8 @@
"one_of_image_and_content_should_be_enter_in_answer":"يجب إدخال صورة أو محتوى واحد على الأقل في الاجابة", "one_of_image_and_content_should_be_enter_in_answer":"يجب إدخال صورة أو محتوى واحد على الأقل في الاجابة",
"one_of_image_and_content_should_be_enter_in_question":"يجب إدخال صورة أو محتوى واحد على الأقل في السؤال", "one_of_image_and_content_should_be_enter_in_question":"يجب إدخال صورة أو محتوى واحد على الأقل في السؤال",
"that_is_not_a_valid_mml":"هذا ليس mml صالح", "that_is_not_a_valid_mml":"هذا ليس mml صالح",
"Are_you_sure_you_want_to_leave_Your_changes_may_not_be_saved":"هل أنت متأكد من أنك تريد المغادرة ؟ قد لا يتم حفظ التغييرات التي أجريتها" "Are_you_sure_you_want_to_leave_Your_changes_may_not_be_saved":"هل أنت متأكد من أنك تريد المغادرة ؟ قد لا يتم حفظ التغييرات التي أجريتها",
"haveDuplicatedContent":"يحتوي عل محتوي مكرر"
}, },
"header": { "header": {
"register_students": "تسجيل الطلاب", "register_students": "تسجيل الطلاب",
@ -237,7 +238,9 @@
"read":"قراءة", "read":"قراءة",
"managers":"مدراء", "managers":"مدراء",
"show":"عرض", "show":"عرض",
"paid_price":"المبلغ المدفوع" "paid_price":"المبلغ المدفوع",
"unit":"الوحدة",
"lesson":"الدرس"
}, },
"practical": { "practical": {
"to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال", "to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال",

View File

@ -8,7 +8,7 @@ export interface InitialValues {
amount: string; // URL of the user's amount amount: string; // URL of the user's amount
due_to: any; // URL of the user's amount due_to: any; // URL of the user's amount
code: string; // URL of the user's amount code: string; // URL of the user's amount
grade_id: string; // URL of the user's amount grade_id: any; // URL of the user's amount
} }
export type Coupon = { export type Coupon = {
id: number; // Unique identifier for the user id: number; // Unique identifier for the user
@ -16,6 +16,6 @@ export type Coupon = {
amount: string; // URL of the user's amount amount: string; // URL of the user's amount
due_to: string; // URL of the user's amount due_to: string; // URL of the user's amount
code: string; // URL of the user's amount code: string; // URL of the user's amount
grade_id: string; // URL of the user's amount grade: string; // URL of the user's amount
}; };
export type CouponInitialValues = Partial<Nullable<InitialValues>>; export type CouponInitialValues = Partial<Nullable<InitialValues>>;

View File

@ -0,0 +1,8 @@
export const ConvertArrayToArrayOfIds = (data:any[])=>{
if(data?.length < 1){
return []
}
return data?.map((item:any)=>{
return item?.id ?? item
})
}

View File

@ -0,0 +1,22 @@
export const hasDuplicateArrayValue = <T>(data: T[], key: keyof T): boolean => {
console.log(data);
if (data.length < 1) {
return false; // Early return for empty array
}
const hashMap = new Map<any, boolean>(); // Using 'any' type for flexibility
for (const item of data) {
const value = item[key]; // Accessing the value using the key
if (hashMap.has(value)) {
return true; // Duplicate found
} else {
hashMap.set(value, true); // Store the value as a key in the map
}
}
return false; // No duplicates found
};