Compare commits
No commits in common. "a05bb8b46d5d4eeb4846da90ed3d7e3883b11221" and "e470e902e58d9d922f404014ea9e559b6184a07c" have entirely different histories.
a05bb8b46d
...
e470e902e5
|
|
@ -1,33 +1,43 @@
|
||||||
import {
|
import {
|
||||||
|
DownloadOutlined,
|
||||||
RotateLeftOutlined,
|
RotateLeftOutlined,
|
||||||
RotateRightOutlined,
|
RotateRightOutlined,
|
||||||
SwapOutlined,
|
SwapOutlined,
|
||||||
ZoomInOutlined,
|
ZoomInOutlined,
|
||||||
ZoomOutOutlined,
|
ZoomOutOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import React, { useState } from "react";
|
import React from "react";
|
||||||
import { Image, Space } from "antd";
|
import { Image, Space } from "antd";
|
||||||
import { CiImageOff } from "react-icons/ci"; // Assuming you're using this icon from react-icons
|
import useImageError from "../../Hooks/useImageError";
|
||||||
|
import { ErrorImage } from "../../Layout/app/Const";
|
||||||
|
|
||||||
const ColumnsImage = ({ src }: any) => {
|
const ColumnsImage = ({ src }: any) => {
|
||||||
const [hasError, setHasError] = useState(false); // Track if the image has an error
|
const imageUrl = src || ErrorImage;
|
||||||
|
|
||||||
const imageUrl = src;
|
const handleError = useImageError;
|
||||||
|
// or you can download flipped and rotated image
|
||||||
|
// https://codesandbox.io/s/zi-ding-yi-gong-ju-lan-antd-5-7-0-forked-c9jvmp
|
||||||
|
const onDownload = () => {
|
||||||
|
fetch(src)
|
||||||
|
.then((response) => response.blob())
|
||||||
|
.then((blob) => {
|
||||||
|
const url = URL.createObjectURL(new Blob([blob]));
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = url;
|
||||||
|
link.download = "image.png";
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
link.remove();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (hasError) {
|
|
||||||
// If there is an error, display the fallback icon
|
|
||||||
return <CiImageOff />;
|
|
||||||
}
|
|
||||||
if(!imageUrl){
|
|
||||||
return <CiImageOff />;
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
width={45}
|
width={45}
|
||||||
height={45}
|
height={45}
|
||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
className="p-1 mb-1 columnImage"
|
className="p-1 mb-1 columnImage "
|
||||||
onError={() => setHasError(true)} // Triggered when image fails to load
|
|
||||||
preview={{
|
preview={{
|
||||||
toolbarRender: (
|
toolbarRender: (
|
||||||
_,
|
_,
|
||||||
|
|
@ -44,6 +54,7 @@ const ColumnsImage = ({ src }: any) => {
|
||||||
},
|
},
|
||||||
) => (
|
) => (
|
||||||
<Space size={12} className="toolbar-wrapper">
|
<Space size={12} className="toolbar-wrapper">
|
||||||
|
{/* <DownloadOutlined onClick={onDownload} /> */}
|
||||||
<SwapOutlined rotate={90} onClick={onFlipY} />
|
<SwapOutlined rotate={90} onClick={onFlipY} />
|
||||||
<SwapOutlined onClick={onFlipX} />
|
<SwapOutlined onClick={onFlipX} />
|
||||||
<RotateLeftOutlined onClick={onRotateLeft} />
|
<RotateLeftOutlined onClick={onRotateLeft} />
|
||||||
|
|
@ -53,8 +64,19 @@ const ColumnsImage = ({ src }: any) => {
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
|
onError={handleError}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ColumnsImage;
|
export default ColumnsImage;
|
||||||
|
|
||||||
|
// {
|
||||||
|
// name: t("image"),
|
||||||
|
// center: "true",
|
||||||
|
// cell: (row: any) => {
|
||||||
|
// return (
|
||||||
|
// <ColumnsImage src={row?.image} />
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import React, { useState, useEffect, useRef } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { IoSearch } from "react-icons/io5";
|
||||||
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { useFilterStateState } from "../../zustand/Filter";
|
import { useFilterStateState } from "../../zustand/Filter";
|
||||||
import { useDebounce } from "../../utils/useDebounce";
|
import { useDebounce } from "../../utils/useDebounce";
|
||||||
|
|
||||||
|
|
@ -13,16 +15,15 @@ const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => {
|
||||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const { setFilter,Filter } = useFilterStateState();
|
const { setFilter } = useFilterStateState();
|
||||||
|
|
||||||
const handleInputChange = (value: string) => {
|
const handleInputChange = (value: string) => {
|
||||||
setSearchQuery(value);
|
setSearchQuery(value);
|
||||||
};
|
};
|
||||||
console.log(searchBy,"searchBy");
|
|
||||||
|
|
||||||
const handleInputChangeWithDebounce = useDebounce((value: string) => {
|
const handleInputChangeWithDebounce = useDebounce((value: string) => {
|
||||||
setFilter({
|
setFilter({
|
||||||
[searchBy]: value,
|
name: value,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
// padding-inline: 20px;
|
padding-inline: 20px;
|
||||||
> * {
|
> * {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,9 @@ import useFilter from "../../Components/Utils/Filter/useFilter";
|
||||||
const FilterLayout = ({
|
const FilterLayout = ({
|
||||||
filterTitle,
|
filterTitle,
|
||||||
sub_children,
|
sub_children,
|
||||||
search_by = "name",
|
|
||||||
width = "500px",
|
|
||||||
haveFilter=true
|
|
||||||
}: {
|
}: {
|
||||||
filterTitle: string;
|
filterTitle: string;
|
||||||
sub_children: any;
|
sub_children: any;
|
||||||
search_by?:string
|
|
||||||
width?:string
|
|
||||||
haveFilter?:boolean
|
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const translateArray = translateOptions(search_array, t);
|
const translateArray = translateOptions(search_array, t);
|
||||||
|
|
@ -43,23 +37,17 @@ const FilterLayout = ({
|
||||||
ModelClassName="filter_model_direction"
|
ModelClassName="filter_model_direction"
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
setIsOpen={setIsOpen}
|
setIsOpen={setIsOpen}
|
||||||
width={width}
|
|
||||||
>
|
>
|
||||||
<div className="model_sub_children">{sub_children}</div>
|
<div className="model_sub_children">{sub_children}</div>
|
||||||
<FilterSubmit />
|
<FilterSubmit />
|
||||||
</FilterBody>
|
</FilterBody>
|
||||||
{haveFilter &&
|
<div className="filter_button" onClick={() => setIsOpen(true)}>
|
||||||
|
|
||||||
<div className="filter_button" onClick={() => setIsOpen(true)}>
|
|
||||||
<span>
|
<span>
|
||||||
<BiFilterAlt className="addition_select_icon" />
|
<BiFilterAlt className="addition_select_icon" />
|
||||||
{t("header.filter")}
|
{t("header.filter")}
|
||||||
</span>
|
</span>
|
||||||
<MdKeyboardArrowDown />
|
<MdKeyboardArrowDown />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
|
|
@ -78,7 +66,7 @@ const FilterLayout = ({
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div className="header_search">
|
<div className="header_search">
|
||||||
<SearchField searchBy={search_by} placeholder={t("practical.search_here")} />
|
<SearchField searchBy="" placeholder={t("practical.search_here")} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ const FormikFormModel: React.FC<FormikFormProps> = ({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen === "") {
|
if (isOpen === "") {
|
||||||
formik.setErrors({});
|
formik.setErrors({});
|
||||||
|
}
|
||||||
|
if (isOpen === "isSuccess") {
|
||||||
|
formik.setErrors({});
|
||||||
formik.resetForm();
|
formik.resetForm();
|
||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,12 @@ const PageHeader = ({
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const PrevPath = getPrevPathRoute(location.pathname);
|
const PrevPath = getPrevPathRoute(location.pathname);
|
||||||
|
const handelNavigate = () => {
|
||||||
|
if (PrevPath === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
navigate(deletePathSegments(location.pathname, PrevPath));
|
||||||
|
};
|
||||||
const handleNavigateToPage = (location: string) => {
|
const handleNavigateToPage = (location: string) => {
|
||||||
navigate(location);
|
navigate(location);
|
||||||
};
|
};
|
||||||
|
|
@ -35,7 +41,7 @@ const PageHeader = ({
|
||||||
return (
|
return (
|
||||||
<div className="page_header">
|
<div className="page_header">
|
||||||
<header className="d-flex justify-content-between">
|
<header className="d-flex justify-content-between">
|
||||||
<span className="page_header_links" >
|
<span className="page_header_links" onClick={handelNavigate}>
|
||||||
<h1 className="page_title">{t(`PageTitle.${pageTitle}`)}</h1>
|
<h1 className="page_title">{t(`PageTitle.${pageTitle}`)}</h1>
|
||||||
<span className="page_links">
|
<span className="page_links">
|
||||||
<PageTitleComponent/>
|
<PageTitleComponent/>
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ import {
|
||||||
import ActionButtons from "../../../Components/Table/ActionButtons";
|
import ActionButtons from "../../../Components/Table/ActionButtons";
|
||||||
import ColumnsImage from "../../../Components/Columns/ColumnsImage";
|
import ColumnsImage from "../../../Components/Columns/ColumnsImage";
|
||||||
import { Grade } from "../../../types/Grade";
|
import { Grade } from "../../../types/Grade";
|
||||||
import { CiImageOff } from "react-icons/ci";
|
|
||||||
import { isValidImage } from "../../../utils/isValidImage";
|
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
const { handel_open_model } = useModalHandler();
|
const { handel_open_model } = useModalHandler();
|
||||||
|
|
@ -61,11 +59,20 @@ export const useColumns = () => {
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_text: any, record: Grade) => {
|
render: (_text: any, record: Grade) => {
|
||||||
let str = record?.icon;
|
let str = record?.icon;
|
||||||
|
return <ColumnsImage src={str} />;
|
||||||
return <ColumnsImage src={str}/> ;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// canAddGrade ? (
|
||||||
|
// <button
|
||||||
|
// onClick={() => handel_open_model(ModalEnum?.GRADE_ADD)}
|
||||||
|
// className="add_button"
|
||||||
|
// >
|
||||||
|
// {t("practical.add")} {t("models.grade")} <FaPlus />
|
||||||
|
// </button>
|
||||||
|
// ) : (
|
||||||
|
// ""
|
||||||
|
// ),
|
||||||
|
|
||||||
title: t("columns.procedure"),
|
title: t("columns.procedure"),
|
||||||
key: "actions",
|
key: "actions",
|
||||||
|
|
|
||||||
33
src/Pages/Admin/QuestionBank/Model/AddModel.tsx
Normal file
33
src/Pages/Admin/QuestionBank/Model/AddModel.tsx
Normal file
|
|
@ -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 (
|
||||||
|
<>
|
||||||
|
<LayoutModel
|
||||||
|
status={status as QueryStatusEnum}
|
||||||
|
ModelEnum={ModalEnum.GRADE_ADD}
|
||||||
|
modelTitle="grade"
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
getInitialValues={getInitialValues({})}
|
||||||
|
getValidationSchema={getValidationSchema}
|
||||||
|
>
|
||||||
|
<ModelForm />
|
||||||
|
</LayoutModel>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddModel;
|
||||||
38
src/Pages/Admin/QuestionBank/Model/EditModel.tsx
Normal file
38
src/Pages/Admin/QuestionBank/Model/EditModel.tsx
Normal file
|
|
@ -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 (
|
||||||
|
<>
|
||||||
|
<LayoutModel
|
||||||
|
status={status as QueryStatusEnum}
|
||||||
|
ModelEnum={ModalEnum.QUESTION_BANK_EDIT}
|
||||||
|
modelTitle="QuestionBank"
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
getInitialValues={getInitialValues(objectToEdit)}
|
||||||
|
getValidationSchema={getValidationSchema}
|
||||||
|
isAddModal={false}
|
||||||
|
>
|
||||||
|
<ModelForm />
|
||||||
|
</LayoutModel>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditModel;
|
||||||
|
|
@ -2,141 +2,15 @@ import React from "react";
|
||||||
import ValidationField from "../../../../Components/ValidationField/ValidationField";
|
import ValidationField from "../../../../Components/ValidationField/ValidationField";
|
||||||
import { Col, Row } from "reactstrap";
|
import { Col, Row } from "reactstrap";
|
||||||
import { useFormikContext } from "formik";
|
import { useFormikContext } from "formik";
|
||||||
import { useGetAllGrade } from "../../../../api/grade";
|
|
||||||
import { useValidationValidationParamState } from "../../../../Components/ValidationField/state/ValidationValidationParamState";
|
|
||||||
import { useGetAllUnit } from "../../../../api/unit";
|
|
||||||
import { useGetAllSubject } from "../../../../api/subject";
|
|
||||||
import { useGetAllLesson } from "../../../../api/lesson";
|
|
||||||
|
|
||||||
const FilterForm = () => {
|
const FilterForm = () => {
|
||||||
|
const formik = useFormikContext();
|
||||||
const { ValidationParamState } = useValidationValidationParamState();
|
|
||||||
const {
|
|
||||||
GradeName, GradeCurrentPage,
|
|
||||||
SubjectName, SubjectCurrentPage,
|
|
||||||
UnitName, UnitCurrentPage,
|
|
||||||
LessonName, LessonCurrentPage
|
|
||||||
|
|
||||||
|
|
||||||
} = ValidationParamState;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { data: Grade, isLoading: isLoadingGrade } = useGetAllGrade({
|
|
||||||
name: GradeName,
|
|
||||||
page: GradeCurrentPage
|
|
||||||
});
|
|
||||||
const GradeOption = Grade?.data ?? []
|
|
||||||
const canChangeGradePage = !!Grade?.links?.next;
|
|
||||||
const GradePage = Grade?.meta?.currentPage;
|
|
||||||
|
|
||||||
|
|
||||||
/// subject_id
|
|
||||||
const { data: Subject, isLoading: isLoadingSubject } = useGetAllSubject({
|
|
||||||
name: SubjectName,
|
|
||||||
page: SubjectCurrentPage
|
|
||||||
});
|
|
||||||
const SubjectOption = Subject?.data ?? []
|
|
||||||
const canChangeSubjectPage = !!Subject?.links?.next;
|
|
||||||
const SubjectPage = Subject?.meta?.currentPage;
|
|
||||||
|
|
||||||
/// unit_id
|
|
||||||
const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({
|
|
||||||
name: UnitName,
|
|
||||||
page: UnitCurrentPage
|
|
||||||
});
|
|
||||||
const UnitOption = Unit?.data ?? []
|
|
||||||
const canChangeUnitPage = !!Unit?.links?.next;
|
|
||||||
const UnitPage = Unit?.meta?.currentPage;
|
|
||||||
|
|
||||||
/// lessonsIds
|
|
||||||
const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({
|
|
||||||
name: LessonName,
|
|
||||||
page: LessonCurrentPage
|
|
||||||
});
|
|
||||||
const LessonOption = Lesson?.data ?? []
|
|
||||||
const canChangeLessonPage = !!Lesson?.links?.next;
|
|
||||||
const LessonPage = Lesson?.meta?.currentPage;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
{/*
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
grade_id
|
|
||||||
*/}
|
|
||||||
<ValidationField
|
|
||||||
searchBy="GradeName"
|
|
||||||
name="grade_id"
|
|
||||||
label="grade"
|
|
||||||
type="Search"
|
|
||||||
option={GradeOption}
|
|
||||||
isLoading={isLoadingGrade}
|
|
||||||
canChangePage={canChangeGradePage}
|
|
||||||
PageName={"GradeCurrentPage"}
|
|
||||||
page={GradePage}
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
{/*
|
|
||||||
subject_id
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
searchBy="SubjectName"
|
|
||||||
name="subject_id"
|
|
||||||
label="subject"
|
|
||||||
type="Search"
|
|
||||||
option={SubjectOption}
|
|
||||||
isLoading={isLoadingSubject}
|
|
||||||
canChangePage={canChangeSubjectPage}
|
|
||||||
PageName={"SubjectCurrentPage"}
|
|
||||||
page={SubjectPage}
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
{/*
|
|
||||||
unit_id
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
searchBy="UnitName"
|
|
||||||
name="unit_id"
|
|
||||||
label="unit"
|
|
||||||
type="Search"
|
|
||||||
option={UnitOption}
|
|
||||||
isLoading={isLoadingUnit}
|
|
||||||
canChangePage={canChangeUnitPage}
|
|
||||||
PageName={"UnitCurrentPage"}
|
|
||||||
page={UnitPage}
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
{/*
|
|
||||||
lessonsIds
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
searchBy="LessonName"
|
|
||||||
name="lessonsIds"
|
|
||||||
label="lesson"
|
|
||||||
type="Search"
|
|
||||||
option={LessonOption}
|
|
||||||
isMulti
|
|
||||||
isLoading={isLoadingLesson}
|
|
||||||
canChangePage={canChangeLessonPage}
|
|
||||||
PageName={"LessonCurrentPage"}
|
|
||||||
page={LessonPage}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
19
src/Pages/Admin/QuestionBank/Model/formUtil.ts
Normal file
19
src/Pages/Admin/QuestionBank/Model/formUtil.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import { Grade, GradeInitialValues } from "../../../../types/Grade";
|
||||||
|
|
||||||
|
export const getInitialValues = (
|
||||||
|
objectToEdit: Partial<Grade>,
|
||||||
|
): 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"),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -10,6 +10,8 @@ import FilterForm from "./Model/FilterForm";
|
||||||
import { canAddQuestionBank } from "../../../utils/hasAbilityFn";
|
import { canAddQuestionBank } from "../../../utils/hasAbilityFn";
|
||||||
|
|
||||||
const Table = lazy(() => import("./Table"));
|
const Table = lazy(() => import("./Table"));
|
||||||
|
const AddModalForm = lazy(() => import("./Model/AddModel"));
|
||||||
|
const EditModalForm = lazy(() => import("./Model/EditModel"));
|
||||||
const DeleteModalForm = lazy(
|
const DeleteModalForm = lazy(
|
||||||
() => import("../../../Layout/Dashboard/DeleteModels"),
|
() => import("../../../Layout/Dashboard/DeleteModels"),
|
||||||
);
|
);
|
||||||
|
|
@ -31,8 +33,10 @@ const TableHeader = () => {
|
||||||
ModelAbility={ModalEnum?.QUESTION_BANK_ADD}
|
ModelAbility={ModalEnum?.QUESTION_BANK_ADD}
|
||||||
canAdd={canAddQuestionBank}
|
canAdd={canAddQuestionBank}
|
||||||
/>
|
/>
|
||||||
<FilterLayout width="700px" search_by="content" sub_children={<FilterForm />} filterTitle="table.QuestionBank" />
|
<FilterLayout sub_children={<FilterForm />} filterTitle="table.QuestionBank" />
|
||||||
<Table />
|
<Table />
|
||||||
|
<AddModalForm />
|
||||||
|
<EditModalForm />
|
||||||
<DeleteModalForm
|
<DeleteModalForm
|
||||||
deleteMutation={deleteMutation}
|
deleteMutation={deleteMutation}
|
||||||
ModelEnum={ModalEnum?.QUESTION_BANK_DELETE}
|
ModelEnum={ModalEnum?.QUESTION_BANK_DELETE}
|
||||||
|
|
|
||||||
|
|
@ -3,20 +3,13 @@ import React from "react";
|
||||||
import DataTable from "../../../Layout/Dashboard/Table/DataTable";
|
import DataTable from "../../../Layout/Dashboard/Table/DataTable";
|
||||||
import { useGetAllQuestion } from "../../../api/Question";
|
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 { useFilterStateState } from "../../../zustand/Filter";
|
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const { filterState } = useFilterState();
|
const { filterState } = useFilterState();
|
||||||
const { setFilter,Filter } = useFilterStateState();
|
|
||||||
|
|
||||||
console.log(filterState,"filterState");
|
|
||||||
|
|
||||||
const response = useGetAllQuestion({
|
const response = useGetAllQuestion({
|
||||||
pagination: true,
|
pagination: true,
|
||||||
...filterState,
|
...filterState,
|
||||||
content:Filter?.content
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { TableColumnsType } from "antd";
|
import { TableColumnsType } from "antd";
|
||||||
import { Question } from "../../../types/Item";
|
import { Question } from "../../../types/Item";
|
||||||
|
import { FaPlus } from "react-icons/fa";
|
||||||
import { ModalEnum } from "../../../enums/Model";
|
import { ModalEnum } from "../../../enums/Model";
|
||||||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
@ -7,6 +8,7 @@ import { ABILITIES_ENUM } from "../../../enums/abilities";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useModalState } from "../../../zustand/Modal";
|
import { useModalState } from "../../../zustand/Modal";
|
||||||
import {
|
import {
|
||||||
|
canAddQuestion,
|
||||||
canDeleteQuestion,
|
canDeleteQuestion,
|
||||||
canEditQuestion,
|
canEditQuestion,
|
||||||
} from "../../../utils/hasAbilityFn";
|
} from "../../../utils/hasAbilityFn";
|
||||||
|
|
@ -17,18 +19,19 @@ export const useColumns = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { setIsOpen } = useModalState((state) => state);
|
const { setIsOpen } = useModalState((state) => state);
|
||||||
|
|
||||||
|
const handelAdd = () => {
|
||||||
|
setObjectToEdit({});
|
||||||
|
navigate(`${ABILITIES_ENUM?.QUESTION}/add`);
|
||||||
|
};
|
||||||
|
|
||||||
const handelDelete = (data: any) => {
|
const handelDelete = (data: any) => {
|
||||||
setObjectToEdit(data);
|
setObjectToEdit(data);
|
||||||
setIsOpen(ModalEnum?.QUESTION_DELETE);
|
setIsOpen(ModalEnum?.QUESTION_DELETE);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEdit = (record: any) => {
|
const handleEdit = (record: any) => {
|
||||||
console.log(record,"record");
|
setObjectToEdit(record);
|
||||||
const lesson = record?.lessons?.[0] ;
|
navigate(`${ABILITIES_ENUM?.QUESTION}/${record?.id}`);
|
||||||
const unit = lesson?.unit;
|
|
||||||
const subject = unit?.subject;
|
|
||||||
const grade = subject?.grade;
|
|
||||||
navigate(`/${ABILITIES_ENUM?.GRADE}/${grade?.id}/${ABILITIES_ENUM?.SUBJECT}/${subject?.id}/${ABILITIES_ENUM?.UNIT}/${unit?.id}/${ABILITIES_ENUM?.LESSON}/${lesson?.id}/${ABILITIES_ENUM?.QUESTION}/${record?.id}`);
|
|
||||||
};
|
};
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
|
@ -48,24 +51,6 @@ export const useColumns = () => {
|
||||||
render: (text, record) => record?.content,
|
render: (text, record) => record?.content,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: `${t("columns.course")}`,
|
|
||||||
dataIndex: "lessons",
|
|
||||||
key: "lessons",
|
|
||||||
align: "center",
|
|
||||||
render: (text, record) => {
|
|
||||||
const lesson = record?.lessons?.[0] ;
|
|
||||||
const unit = lesson?.unit;
|
|
||||||
const subject = unit?.subject;
|
|
||||||
const grade = subject?.grade;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<> {grade?.name} </>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
title: `${t("columns.hint")}`,
|
title: `${t("columns.hint")}`,
|
||||||
dataIndex: "hint",
|
dataIndex: "hint",
|
||||||
|
|
|
||||||
|
|
@ -1,143 +1,27 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ValidationField from "../../../Components/ValidationField/ValidationField";
|
import ValidationField from "../../../Components/ValidationField/ValidationField";
|
||||||
import { Col, Row } from "reactstrap";
|
import { Col, Row } from "reactstrap";
|
||||||
import { useFormikContext } from "formik";
|
import useFormatDataToSelect from "../../../utils/useFormatDataToSelect";
|
||||||
import { useGetAllGrade } from "../../../api/grade";
|
|
||||||
import { useValidationValidationParamState } from "../../../Components/ValidationField/state/ValidationValidationParamState";
|
|
||||||
import { useGetAllUnit } from "../../../api/unit";
|
|
||||||
import { useGetAllSubject } from "../../../api/subject";
|
|
||||||
import { useGetAllLesson } from "../../../api/lesson";
|
|
||||||
|
|
||||||
const FilterForm = () => {
|
const FilterForm = () => {
|
||||||
|
const yesNoArray = [
|
||||||
const { ValidationParamState } = useValidationValidationParamState();
|
{ id: "لا", name: "لا" },
|
||||||
const {
|
{ id: "نعم", name: "نعم" },
|
||||||
GradeName, GradeCurrentPage,
|
];
|
||||||
SubjectName, SubjectCurrentPage,
|
|
||||||
UnitName, UnitCurrentPage,
|
|
||||||
LessonName, LessonCurrentPage
|
|
||||||
|
|
||||||
|
|
||||||
} = ValidationParamState;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { data: Grade, isLoading: isLoadingGrade } = useGetAllGrade({
|
|
||||||
name: GradeName,
|
|
||||||
page: GradeCurrentPage
|
|
||||||
});
|
|
||||||
const GradeOption = Grade?.data ?? []
|
|
||||||
const canChangeGradePage = !!Grade?.links?.next;
|
|
||||||
const GradePage = Grade?.meta?.currentPage;
|
|
||||||
|
|
||||||
|
|
||||||
/// subject_id
|
|
||||||
const { data: Subject, isLoading: isLoadingSubject } = useGetAllSubject({
|
|
||||||
name: SubjectName,
|
|
||||||
page: SubjectCurrentPage
|
|
||||||
});
|
|
||||||
const SubjectOption = Subject?.data ?? []
|
|
||||||
const canChangeSubjectPage = !!Subject?.links?.next;
|
|
||||||
const SubjectPage = Subject?.meta?.currentPage;
|
|
||||||
|
|
||||||
/// unit_id
|
|
||||||
const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({
|
|
||||||
name: UnitName,
|
|
||||||
page: UnitCurrentPage
|
|
||||||
});
|
|
||||||
const UnitOption = Unit?.data ?? []
|
|
||||||
const canChangeUnitPage = !!Unit?.links?.next;
|
|
||||||
const UnitPage = Unit?.meta?.currentPage;
|
|
||||||
|
|
||||||
/// lessonsIds
|
|
||||||
const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({
|
|
||||||
name: LessonName,
|
|
||||||
page: LessonCurrentPage
|
|
||||||
});
|
|
||||||
const LessonOption = Lesson?.data ?? []
|
|
||||||
const canChangeLessonPage = !!Lesson?.links?.next;
|
|
||||||
const LessonPage = Lesson?.meta?.currentPage;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
{/*
|
<ValidationField
|
||||||
grade_id
|
placeholder="content"
|
||||||
*/}
|
label="content"
|
||||||
<ValidationField
|
name="content"
|
||||||
searchBy="GradeName"
|
/>
|
||||||
name="grade_id"
|
{/* <ValidationField type="Select" option={yesNoArray} placeholder="isBase" label="isBase" name="isBase" /> */}
|
||||||
label="grade"
|
|
||||||
type="Search"
|
|
||||||
option={GradeOption}
|
|
||||||
isLoading={isLoadingGrade}
|
|
||||||
canChangePage={canChangeGradePage}
|
|
||||||
PageName={"GradeCurrentPage"}
|
|
||||||
page={GradePage}
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
{/*
|
|
||||||
subject_id
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
searchBy="SubjectName"
|
|
||||||
name="subject_id"
|
|
||||||
label="subject"
|
|
||||||
type="Search"
|
|
||||||
option={SubjectOption}
|
|
||||||
isLoading={isLoadingSubject}
|
|
||||||
canChangePage={canChangeSubjectPage}
|
|
||||||
PageName={"SubjectCurrentPage"}
|
|
||||||
page={SubjectPage}
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
{/*
|
|
||||||
unit_id
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
searchBy="UnitName"
|
|
||||||
name="unit_id"
|
|
||||||
label="unit"
|
|
||||||
type="Search"
|
|
||||||
option={UnitOption}
|
|
||||||
isLoading={isLoadingUnit}
|
|
||||||
canChangePage={canChangeUnitPage}
|
|
||||||
PageName={"UnitCurrentPage"}
|
|
||||||
page={UnitPage}
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
{/*
|
|
||||||
lessonsIds
|
|
||||||
*/}
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
searchBy="LessonName"
|
|
||||||
name="lessonsIds"
|
|
||||||
label="lesson"
|
|
||||||
type="Search"
|
|
||||||
option={LessonOption}
|
|
||||||
isMulti
|
|
||||||
isLoading={isLoadingLesson}
|
|
||||||
canChangePage={canChangeLessonPage}
|
|
||||||
PageName={"LessonCurrentPage"}
|
|
||||||
page={LessonPage}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
|
{/* <Col>
|
||||||
|
<ValidationField type="Select" option={yesNoArray} placeholder="canAnswersBeShuffled" label="canAnswersBeShuffled" name="canAnswersBeShuffled" />
|
||||||
|
</Col> */}
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,6 @@ const TableHeader = () => {
|
||||||
<FilterLayout
|
<FilterLayout
|
||||||
sub_children={<FilterForm />}
|
sub_children={<FilterForm />}
|
||||||
filterTitle={` ${unitName} (${LessonName}) `}
|
filterTitle={` ${unitName} (${LessonName}) `}
|
||||||
search_by="content"
|
|
||||||
haveFilter={false}
|
|
||||||
/>
|
/>
|
||||||
<Table />
|
<Table />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,15 @@ import { useGetAllQuestion } from "../../../api/Question";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../../enums/params";
|
import { ParamsEnum } from "../../../enums/params";
|
||||||
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
|
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
|
||||||
import { useFilterStateState } from "../../../zustand/Filter";
|
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const { lesson_id } = useParams<ParamsEnum>();
|
const { lesson_id } = useParams<ParamsEnum>();
|
||||||
const { filterState } = useFilterState();
|
const { filterState } = useFilterState();
|
||||||
const { setFilter,Filter } = useFilterStateState();
|
|
||||||
|
|
||||||
const response = useGetAllQuestion({
|
const response = useGetAllQuestion({
|
||||||
lessonsIds: [lesson_id],
|
lessonsIds: [lesson_id],
|
||||||
pagination: true,
|
pagination: true,
|
||||||
...filterState,
|
...filterState,
|
||||||
content:Filter?.content
|
|
||||||
});
|
});
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import {
|
||||||
} from "../../../../utils/hasAbilityFn";
|
} from "../../../../utils/hasAbilityFn";
|
||||||
import { ABILITIES_ENUM } from "../../../../enums/abilities";
|
import { ABILITIES_ENUM } from "../../../../enums/abilities";
|
||||||
import { Subject } from "../../../../types/Subject";
|
import { Subject } from "../../../../types/Subject";
|
||||||
import { CiImageOff } from "react-icons/ci";
|
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
@ -55,7 +54,7 @@ export const useColumns = () => {
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (row: Subject, record) => {
|
render: (row: Subject, record) => {
|
||||||
let str = record.icon;
|
let str = record.icon;
|
||||||
return <ColumnsImage src={str}/> ;
|
return <ColumnsImage src={str} />;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,6 @@
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
transition: 1s ease-in-out;
|
transition: 1s ease-in-out;
|
||||||
animation: fadeInRight 1s ease-in-out;
|
animation: fadeInRight 1s ease-in-out;
|
||||||
max-height: 90vh;
|
|
||||||
overflow-y: scroll;
|
|
||||||
@include Scrollbar;
|
|
||||||
|
|
||||||
> header {
|
> header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,3 @@
|
||||||
font-size: 8px !important;
|
font-size: 8px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.model_sub_children{
|
|
||||||
padding-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
@ -209,12 +209,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.SelectTag {
|
.SelectTag {
|
||||||
// padding-inline: 20px;
|
padding-inline: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exercise_add {
|
.exercise_add {
|
||||||
.add_new_button {
|
.add_new_button {
|
||||||
// padding-inline: 20px !important;
|
padding-inline: 20px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,12 +229,12 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
// >{
|
>{
|
||||||
// flex: 1;
|
flex: 1;
|
||||||
// min-height: auto;
|
min-height: auto;
|
||||||
// min-width: 30px;
|
min-width: 30px;
|
||||||
|
|
||||||
// }
|
}
|
||||||
.ant-btn{
|
.ant-btn{
|
||||||
min-height: 30px !important;
|
min-height: 30px !important;
|
||||||
max-height: 30px !important;
|
max-height: 30px !important;
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,6 @@
|
||||||
"normal_question": " تمرين عادي",
|
"normal_question": " تمرين عادي",
|
||||||
"hint":"شرح ",
|
"hint":"شرح ",
|
||||||
"tags":"كلمات مفتاحية",
|
"tags":"كلمات مفتاحية",
|
||||||
"course":" الصفوف",
|
|
||||||
"student_full_name":"اسم الطالب الثلاثي",
|
"student_full_name":"اسم الطالب الثلاثي",
|
||||||
"amount_paid":"المبلغ المدفوع",
|
"amount_paid":"المبلغ المدفوع",
|
||||||
"sale_date":"تاريخ البيع",
|
"sale_date":"تاريخ البيع",
|
||||||
|
|
@ -445,10 +444,6 @@
|
||||||
"city": "المحافظة",
|
"city": "المحافظة",
|
||||||
"personal_image": "صورة شخصية",
|
"personal_image": "صورة شخصية",
|
||||||
"id_image": "صورة الهوية",
|
"id_image": "صورة الهوية",
|
||||||
"grade":"الصفوف",
|
|
||||||
"subject":"المادة",
|
|
||||||
"unit":"الوحدة",
|
|
||||||
"lesson":"الدرس",
|
|
||||||
"date_of_receipt":"تاريخ الاستلام",
|
"date_of_receipt":"تاريخ الاستلام",
|
||||||
"amount_value":"قيمة المبلغ"
|
"amount_value":"قيمة المبلغ"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -315,8 +315,7 @@ export interface Question {
|
||||||
question_options_count?: any;
|
question_options_count?: any;
|
||||||
answers: QuestionOption[];
|
answers: QuestionOption[];
|
||||||
hint?: string;
|
hint?: string;
|
||||||
tags: tags[];
|
tags: tags[]; // Assuming tags are strings, adjust as per actual data type
|
||||||
lessons:any
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type report = {
|
export type report = {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
export const isValidImage = (url: string): Promise<boolean> => {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const img = new Image();
|
|
||||||
img.src = url;
|
|
||||||
|
|
||||||
img.onload = () => resolve(true); // Image loaded successfully
|
|
||||||
img.onerror = () => resolve(false); // Error loading image
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Loading…
Reference in New Issue
Block a user