Compare commits

..

No commits in common. "ce1a1843a08df32e84b94d85ba6b31a5fabfe1a4" and "f095644f2513dcd9eb8cba5eff197111384b982e" have entirely different histories.

31 changed files with 285 additions and 224 deletions

View File

@ -1,18 +1,24 @@
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,14 +48,8 @@ const SearchField = ({
} }
}, [page]); }, [page]);
const SelectableChange = (value: any,option:any) => { const SelectableChange = (value: any) => {
if(isMulti){ formik?.setFieldValue(name, value);
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) {
@ -96,8 +90,8 @@ const SearchField = ({
const handleScroll = (event: any) => { const handleScroll = (event: any) => {
const target = event.target; const target = event.target;
const isAtBottom = const isAtBottom =
target.scrollHeight - 10 <= Math.floor(target.scrollTop + target.clientHeight); target.scrollHeight === 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!");
let newPage = page + 1; let newPage = page + 1;
@ -109,11 +103,7 @@ 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">
<ValidationFieldLabel <ValidationFieldLabel
@ -131,8 +121,8 @@ const SearchField = ({
options={AllPagesOption} options={AllPagesOption}
size="large" size="large"
className={`${className} w-100`} className={`${className} w-100`}
value={value} value={formik.values[name]}
loading={isLoading} // loading={isLoading}
allowClear allowClear
{...(isMulti && { mode: "multiple" })} {...(isMulti && { mode: "multiple" })}
onChange={onChange || SelectableChange} onChange={onChange || SelectableChange}
@ -143,7 +133,7 @@ const SearchField = ({
onBlur={handleBlur} onBlur={handleBlur}
id={name} id={name}
onPopupScroll={handleScroll} onPopupScroll={handleScroll}
fieldNames={{ label: "name", value: "name" }} fieldNames={{ label: "name", value: "id" }}
{...props} {...props}
/> />
</ValidationFieldContainer> </ValidationFieldContainer>

View File

@ -6,7 +6,6 @@ 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();
@ -17,10 +16,7 @@ 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,6 +6,7 @@ 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();
@ -13,7 +14,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, grade_id:values?.grade_id?.id ?? "" }; const Data_to_send = { ...values , due_to };
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?.current_page; const GradePage = Grade?.meta?.currentPage;
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 ?? "", grade_id: objectToEdit?.grade_id ?? "",
}; };
}; };

View File

@ -12,7 +12,6 @@ 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, grade_id:values?.grade_id?.id }; const Data_to_send = { ...values };
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?.current_page; const GradePage = Grade?.meta?.currentPage;
const sex = [ const sex = [
{ name: "male", id: "male" }, { name: "male", id: "male" },

View File

@ -30,9 +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?.current_page; const GradePage = Grade?.meta?.currentPage;
console.log(Grade?.meta?.current_page);
/// subject_id /// subject_id
const { data: Subject, isLoading: isLoadingSubject } = useGetAllSubject({ const { data: Subject, isLoading: isLoadingSubject } = useGetAllSubject({
@ -41,7 +40,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?.current_page; const SubjectPage = Subject?.meta?.currentPage;
/// unit_id /// unit_id
const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({ const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({
@ -50,7 +49,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?.current_page; const UnitPage = Unit?.meta?.currentPage;
/// lessonsIds /// lessonsIds
const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({ const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({
@ -59,7 +58,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?.current_page; const LessonPage = Lesson?.meta?.currentPage;
/// TagsIds /// TagsIds
@ -69,7 +68,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?.current_page; const TagPage = Tag?.meta?.currentPage;
return ( return (
@ -89,7 +88,6 @@ const FilterForm = () => {
canChangePage={canChangeGradePage} canChangePage={canChangeGradePage}
PageName={"GradeCurrentPage"} PageName={"GradeCurrentPage"}
page={GradePage} page={GradePage}
/> />

View File

@ -7,6 +7,7 @@ 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,7 +5,6 @@ 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();
@ -18,11 +17,6 @@ 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,66 +69,19 @@ export const useColumns = () => {
}, },
ellipsis: true, ellipsis: true,
}, },
{
title: `${t("columns.subject")}`,
dataIndex: "lessons",
key: "lessons",
align: "center",
render: (text, record) => {
const lesson = record?.lessons?.[0] ;
const unit = lesson?.unit;
const subject = unit?.subject;
return (
<> {subject?.name} </>
)
},
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")}`,
// title: `${t("columns.hint")}`, dataIndex: "hint",
// dataIndex: "hint", key: "hint",
// key: "hint", align: "center",
// align: "center", render: (text, record) => {
// render: (text, record) => { return (
// return ( <>{record?.hint ?? "_"}</>
// <>{record?.hint ?? "_"}</> );
// ); },
// }, ellipsis: true,
// 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?.current_page; const GradePage = Grade?.meta?.currentPage;
const sex = [ const sex = [
{ name: "male", id: "male" }, { name: "male", id: "male" },

View File

@ -19,7 +19,6 @@ 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,7 +9,10 @@ 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/ValidationFn"; import { handleValidateBaseQuestion, handleValidateSingleQuestion } from "./Model/AddForm/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,30 +19,28 @@ 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,setObjectToEdit } = const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions, ShowHint, setShowHint, ShowLatexOption, setShowLatexOption } =
useObjectToEdit(); useObjectToEdit();
const { mutate, isSuccess ,isLoading:isLoadingUpdate } = useUpdateQuestion(); const { mutate, isSuccess, isLoading } = useUpdateQuestion();
const { mutate: DeleteQuestion } = useDeleteQuestion(); const { mutate: DeleteQuestion } = useDeleteQuestion();
const { mutate: mutateAdd } = useAddQuestion(); const { mutate: mutateAdd, isLoading: LoadingAsync } = useAddQuestion();
const { data, isLoading: dataLoading ,isRefetching } = useGetAllQuestion({ const { data, isLoading: dataLoading } = useGetAllQuestion({
show: question_id, show: question_id,
}); });
const { data: Questions, isLoading: QuestionsDataLoading,isRefetching:isRefetchingParent } = const { data: Questions, isLoading: QuestionsDataLoading } =
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) {
setIsBseQuestion(true); setIsBseQuestion(true);
@ -177,39 +175,136 @@ 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]);
console.log(objectToEdit); const Loading = LoadingAsync || isLoading
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={LoadingButton} handleSubmit={handleSubmit} handleValidateBaseQuestion={handleValidateBaseQuestion} objectToEdit={objectToEdit} /> <BaseFormContainer t={t} Loading={Loading} handleSubmit={handleSubmit} handleValidateBaseQuestion={handleValidateBaseQuestion} objectToEdit={objectToEdit} />
); );
} }
return ( return (
<FormContainer t={t} Loading={LoadingButton} handleSubmit={handleSubmit} handleValidateSingleQuestion={handleValidateSingleQuestion} objectToEdit={objectToEdit} /> <FormContainer t={t} Loading={Loading} 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?.current_page; const GradePage = Grade?.meta?.currentPage;
/// 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?.current_page; const SubjectPage = Subject?.meta?.currentPage;
/// 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?.current_page; const UnitPage = Unit?.meta?.currentPage;
/// 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?.current_page; const LessonPage = Lesson?.meta?.currentPage;
return ( return (
<div> <div>

View File

@ -1,13 +1,9 @@
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 ;
@ -29,11 +25,8 @@ 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)
@ -44,18 +37,12 @@ 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 ;
const haveDuplicatedContent = hasDuplicateArrayValue(values?.Questions,"content") console.log(2);
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) => {
@ -64,7 +51,6 @@ 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;
@ -77,10 +63,7 @@ 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);
@ -104,11 +87,6 @@ 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

@ -13,10 +13,9 @@ 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 ,setObjectToEdit} = const { ShowHint,setShowHint , ShowLatexOption,setShowLatexOption } =
useObjectToEdit(); useObjectToEdit();
const handleCancel = () => { const handleCancel = () => {
setObjectToEdit({})
navigate(-1); navigate(-1);
}; };
const handleNavigateToPage = () => { const handleNavigateToPage = () => {
@ -85,8 +84,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,t) }} onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit,t) }} onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
> {t("practical.edit")} > {t("practical.edit")}
{Loading && ( {Loading && (

View File

@ -13,15 +13,13 @@ 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,setObjectToEdit } = const { ShowHint,setShowHint , ShowLatexOption,setShowLatexOption } =
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

@ -0,0 +1,100 @@
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,5 +1,5 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { lazy, Suspense, useEffect } from "react"; import { lazy, Suspense } 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,7 +16,6 @@ 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 = () => {
@ -51,15 +50,7 @@ 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,13 +1,8 @@
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">
<div>asd</div> karim is op
<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 { useGetAllCollections } from "../../../../api/collections"; import { useGetCollection } 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 = useGetAllCollections({ const response = useGetCollection({
name: searchQuery, name: searchQuery,
pagination: true, pagination: true,
...filterState, ...filterState,

View File

@ -1,8 +1,7 @@
.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-block: 10px 30px; padding-top: 10px;
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,7 +48,6 @@
// 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;
@ -60,15 +59,15 @@
outline: none; outline: none;
border: none; border: none;
border-radius: 10px; border-radius: 10px;
padding: 5px 10px; padding: 0.4vw 0.2vw;
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: 16px; font-size: 1vw;
min-width: 130px; width: 10vw;
cursor: pointer; cursor: pointer;
transition: .5s ease-in-out; transition: .5s ease-in-out;
&:hover{ &:hover{

View File

@ -55,8 +55,7 @@
"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": "تسجيل الطلاب",
@ -238,9 +237,7 @@
"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: any; // URL of the user's amount grade_id: string; // 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: string; // URL of the user's amount grade_id: string; // URL of the user's amount
}; };
export type CouponInitialValues = Partial<Nullable<InitialValues>>; export type CouponInitialValues = Partial<Nullable<InitialValues>>;

View File

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

View File

@ -1,22 +0,0 @@
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
};