This commit is contained in:
karimaldeen 2024-09-09 16:23:12 +03:00
parent 4f944eab55
commit b2ea58b19e
18 changed files with 403 additions and 57 deletions

View File

@ -4,6 +4,10 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.3.7", "@ant-design/icons": "^5.3.7",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"antd": "^5.17.4", "antd": "^5.17.4",
"axios": "^1.7.2", "axios": "^1.7.2",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",

View File

@ -11,6 +11,18 @@ importers:
'@ant-design/icons': '@ant-design/icons':
specifier: ^5.3.7 specifier: ^5.3.7
version: 5.3.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 5.3.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@dnd-kit/core':
specifier: ^6.1.0
version: 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@dnd-kit/modifiers':
specifier: ^7.0.0
version: 7.0.0(@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
'@dnd-kit/sortable':
specifier: ^8.0.0
version: 8.0.0(@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
'@dnd-kit/utilities':
specifier: ^3.2.2
version: 3.2.2(react@18.3.1)
antd: antd:
specifier: ^5.17.4 specifier: ^5.17.4
version: 5.17.4(date-fns@3.3.1)(luxon@3.4.4)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 5.17.4(date-fns@3.3.1)(luxon@3.4.4)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -865,6 +877,34 @@ packages:
resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
'@dnd-kit/accessibility@3.1.0':
resolution: {integrity: sha512-ea7IkhKvlJUv9iSHJOnxinBcoOI3ppGnnL+VDJ75O45Nss6HtZd8IdN8touXPDtASfeI2T2LImb8VOZcL47wjQ==}
peerDependencies:
react: '>=16.8.0'
'@dnd-kit/core@6.1.0':
resolution: {integrity: sha512-J3cQBClB4TVxwGo3KEjssGEXNJqGVWx17aRTZ1ob0FliR5IjYgTxl5YJbKTzA6IzrtelotH19v6y7uoIRUZPSg==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@dnd-kit/modifiers@7.0.0':
resolution: {integrity: sha512-BG/ETy3eBjFap7+zIti53f0PCLGDzNXyTmn6fSdrudORf+OH04MxrW4p5+mPu4mgMk9kM41iYONjc3DOUWTcfg==}
peerDependencies:
'@dnd-kit/core': ^6.1.0
react: '>=16.8.0'
'@dnd-kit/sortable@8.0.0':
resolution: {integrity: sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==}
peerDependencies:
'@dnd-kit/core': ^6.1.0
react: '>=16.8.0'
'@dnd-kit/utilities@3.2.2':
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
peerDependencies:
react: '>=16.8.0'
'@emotion/hash@0.8.0': '@emotion/hash@0.8.0':
resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
@ -4731,6 +4771,38 @@ snapshots:
'@discoveryjs/json-ext@0.5.7': {} '@discoveryjs/json-ext@0.5.7': {}
'@dnd-kit/accessibility@3.1.0(react@18.3.1)':
dependencies:
react: 18.3.1
tslib: 2.6.2
'@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@dnd-kit/accessibility': 3.1.0(react@18.3.1)
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
tslib: 2.6.2
'@dnd-kit/modifiers@7.0.0(@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
dependencies:
'@dnd-kit/core': 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
react: 18.3.1
tslib: 2.6.2
'@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
dependencies:
'@dnd-kit/core': 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
react: 18.3.1
tslib: 2.6.2
'@dnd-kit/utilities@3.2.2(react@18.3.1)':
dependencies:
react: 18.3.1
tslib: 2.6.2
'@emotion/hash@0.8.0': {} '@emotion/hash@0.8.0': {}
'@emotion/unitless@0.7.5': {} '@emotion/unitless@0.7.5': {}

View File

@ -1,4 +1,4 @@
import React, { useContext, useEffect, useMemo } from "react"; import React, { Suspense, useContext, useEffect, useMemo } from "react";
import { HolderOutlined } from "@ant-design/icons"; import { HolderOutlined } from "@ant-design/icons";
import type { DragEndEvent } from "@dnd-kit/core"; import type { DragEndEvent } from "@dnd-kit/core";
import { DndContext } from "@dnd-kit/core"; import { DndContext } from "@dnd-kit/core";
@ -12,10 +12,16 @@ import {
} from "@dnd-kit/sortable"; } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities"; import { CSS } from "@dnd-kit/utilities";
import { Button, Table } from "antd"; import { Button, Table } from "antd";
import type { TableColumnsType } from "antd";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { ParamsEnum } from "../../enums/params"; import { ParamsEnum } from "../../../enums/params";
import { useGetAllUnit } from "../../api/unit"; import { useGetAllUnit, useUpdateUnitOrder } from "../../../api/unit";
const NotFoundLottie = React.lazy(() => import("../../../Components/Lottie/NotFound/NotFoundLottie"));
const LoadingLottie = React.lazy(() => import("../../../Components/Lottie/Loading/LoadingLottie" ));
import { useTranslation } from "react-i18next";
import { useColumns } from "./useTableColumns";
interface DataType { interface DataType {
id: string; // Unique identifier for each row id: string; // Unique identifier for each row
@ -32,7 +38,7 @@ interface RowContextProps {
const RowContext = React.createContext<RowContextProps>({}); const RowContext = React.createContext<RowContextProps>({});
const DragHandle: React.FC = () => { export const DragHandleUnit: React.FC = () => {
const { setActivatorNodeRef, listeners } = useContext(RowContext); const { setActivatorNodeRef, listeners } = useContext(RowContext);
return ( return (
<Button <Button
@ -46,12 +52,6 @@ const DragHandle: React.FC = () => {
); );
}; };
const columns: TableColumnsType<DataType> = [
{ key: "sort", align: "center", width: 80, render: () => <DragHandle /> },
{ title: "Name", dataIndex: "name" },
{ title: "Age", dataIndex: "age" },
{ title: "Address", dataIndex: "address" },
];
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> { interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
"data-row-key": string; "data-row-key": string;
@ -96,13 +96,10 @@ const DrapableTable: React.FC = () => {
response?.data?.data?.map((item: any, index: number) => ({ response?.data?.data?.map((item: any, index: number) => ({
id: item.id, // Ensure this is a unique identifier id: item.id, // Ensure this is a unique identifier
order: index + 1, // Assign order based on index order: index + 1, // Assign order based on index
name: item.name, ...item
age: item.age,
address: item.address,
})) ?? []; })) ?? [];
const [dataSource, setDataSource] = React.useState<DataType[]>(data); const [dataSource, setDataSource] = React.useState<DataType[]>(data);
console.log(dataSource, "dataSource");
useEffect(() => { useEffect(() => {
// Update dataSource when the fetched data changes // Update dataSource when the fetched data changes
@ -110,28 +107,51 @@ const DrapableTable: React.FC = () => {
setDataSource(sortedData); setDataSource(sortedData);
}, [response?.data?.data]); }, [response?.data?.data]);
const {mutate:orderUnit} = useUpdateUnitOrder({},{
retry:false
})
const onDragEnd = ({ active, over }: DragEndEvent) => { const onDragEnd = ({ active, over }: DragEndEvent) => {
if (active.id !== over?.id) { if (active.id !== over?.id) {
setDataSource((prevState) => { setDataSource((prevState) => {
const activeIndex = prevState.findIndex( const activeIndex = prevState.findIndex(
(record) => record.id === active.id, (record) => record.id === active.id,
); );
const overIndex = prevState.findIndex( const overIndex = prevState.findIndex(
//@ts-ignore
(record) => record.id === over.id, (record) => record.id === over.id,
); );
// Move the items in the array // Move the items in the array
const newState = arrayMove(prevState, activeIndex, overIndex); const newState = arrayMove(prevState, activeIndex, overIndex);
const orderedNewState = newState.map((item, index) => ({
// Update the order based on the new positions
return newState.map((item, index) => ({
...item, ...item,
order: index + 1, // Update the order based on the new index order: index + 1, // Update the order based on the new index
})); }));
// Update the order based on the new positions
const orderedNewStateWithNewChape = orderedNewState?.map((item:any)=>{
return {
"unit_id":item?.id,
"order":item?.order
}
})
orderUnit({units: orderedNewStateWithNewChape, _method:"PUT"})
return orderedNewState
}); });
} }
}; };
const getRowClassName = (record: any, index: number): string => {
return index % 2 === 0 ? "even-row" : "odd-row";
};
const isLoading = response?.isLoading;
const [t] = useTranslation()
const columns = useColumns();
const sortedDataSource = dataSource.sort((a, b) => a.order - b.order) ;
console.log(sortedDataSource,"sortedDataSource");
return ( return (
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}> <DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
<SortableContext <SortableContext
@ -141,9 +161,32 @@ const DrapableTable: React.FC = () => {
<Table <Table
rowKey="id" rowKey="id"
components={{ body: { row: Row } }} components={{ body: { row: Row } }}
//@ts-ignore
columns={columns} columns={columns}
dataSource={dataSource.sort((a, b) => a.order - b.order)} // Sort by order for rendering dataSource={sortedDataSource}
pagination={false} pagination={false}
rowClassName={(record, index) => getRowClassName(record, index)}
className="DataTable"
loading={{
spinning: isLoading,
indicator:<Suspense fallback={<></>}>
<LoadingLottie />
</Suspense> ,
size: "large",
}}
locale={{
emptyText: (
isLoading ?
<></>
:
<Suspense fallback={<></>}>
<NotFoundLottie
/>
</Suspense>
),
}}
/> />
</SortableContext> </SortableContext>
</DndContext> </DndContext>

View File

@ -10,7 +10,7 @@ import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
const AddModel: React.FC = () => { const AddModel: React.FC = () => {
const { mutate, status } = useAddUnit(); const { mutate, status } = useAddUnit();
const { curriculum_id } = useParams(); const { subject_id } = useParams();
const { OldObjectToEdit } = useObjectToEdit(); const { OldObjectToEdit } = useObjectToEdit();
const handleSubmit = (values: any) => { const handleSubmit = (values: any) => {
@ -21,7 +21,7 @@ const AddModel: React.FC = () => {
mutate({ mutate({
...values, ...values,
curriculum_id: curriculum_id, subject_id: subject_id,
order: order, order: order,
}); });
}; };

View File

@ -7,7 +7,6 @@ import { useGetAllSubject } from "../../../api/subject";
import useSetPageTitle from "../../../Hooks/useSetPageTitle"; import useSetPageTitle from "../../../Hooks/useSetPageTitle";
import { ModalEnum } from "../../../enums/Model"; import { ModalEnum } from "../../../enums/Model";
import { useDeleteUnit } from "../../../api/unit"; import { useDeleteUnit } from "../../../api/unit";
import DrapableTable from "./DrapableTable";
import { useGetAllGrade } from "../../../api/grade"; import { useGetAllGrade } from "../../../api/grade";
import { useGetAllCurriculum } from "../../../api/curriculum"; import { useGetAllCurriculum } from "../../../api/curriculum";
import PageHeader from "../../../Layout/Dashboard/PageHeader"; import PageHeader from "../../../Layout/Dashboard/PageHeader";
@ -15,7 +14,7 @@ import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
import FilterForm from "./Model/FilterForm"; import FilterForm from "./Model/FilterForm";
import { canAddUnit } from "../../../utils/hasAbilityFn"; import { canAddUnit } from "../../../utils/hasAbilityFn";
const Table = lazy(() => import("./Table")); const Table = lazy(() => import("./DrapableTable"));
const AddModalForm = lazy(() => import("./Model/AddModel")); const AddModalForm = lazy(() => import("./Model/AddModel"));
const EditModalForm = lazy(() => import("./Model/EditModel")); const EditModalForm = lazy(() => import("./Model/EditModel"));
const DeleteModalForm = lazy( const DeleteModalForm = lazy(

View File

@ -18,6 +18,7 @@ import {
import ActionButtons from "../../../Components/Table/ActionButtons"; import ActionButtons from "../../../Components/Table/ActionButtons";
import { Unit } from "../../../types/Unit"; import { Unit } from "../../../types/Unit";
import { ConvertEnumToTranslate } from "../../../utils/ConvertEnumToTranslate"; import { ConvertEnumToTranslate } from "../../../utils/ConvertEnumToTranslate";
import { DragHandleUnit } from "./DrapableTable";
export const useColumns = () => { export const useColumns = () => {
const { handel_open_model } = useModalHandler(); const { handel_open_model } = useModalHandler();
@ -41,6 +42,8 @@ export const useColumns = () => {
const [t] = useTranslation(); const [t] = useTranslation();
const columns: TableColumnsType<Unit> = [ const columns: TableColumnsType<Unit> = [
{ key: "sort", align: "center", width: 80, render: () => <DragHandleUnit /> },
{ {
title: t("columns.id"), title: t("columns.id"),
dataIndex: "id", dataIndex: "id",

View File

@ -0,0 +1,194 @@
import React, { Suspense, useContext, useEffect, useMemo } from "react";
import { HolderOutlined } from "@ant-design/icons";
import type { DragEndEvent } from "@dnd-kit/core";
import { DndContext } from "@dnd-kit/core";
import type { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities";
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
import {
arrayMove,
SortableContext,
useSortable,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Button, Table } from "antd";
import { useParams } from "react-router-dom";
import { ParamsEnum } from "../../../enums/params";
import { useGetAllLesson, useUpdateLessonOrder } from "../../../api/lesson";
const NotFoundLottie = React.lazy(() => import("../../../Components/Lottie/NotFound/NotFoundLottie"));
const LoadingLottie = React.lazy(() => import("../../../Components/Lottie/Loading/LoadingLottie" ));
import { useTranslation } from "react-i18next";
import { useColumns } from "./useTableColumns";
interface DataType {
id: string; // Unique identifier for each row
order: number;
name: string;
age: number;
address: string;
}
interface RowContextProps {
setActivatorNodeRef?: (element: HTMLElement | null) => void;
listeners?: SyntheticListenerMap;
}
const RowContext = React.createContext<RowContextProps>({});
export const DragHandleLesson: React.FC = () => {
const { setActivatorNodeRef, listeners } = useContext(RowContext);
return (
<Button
type="text"
size="small"
icon={<HolderOutlined />}
style={{ cursor: "move" }}
ref={setActivatorNodeRef}
{...listeners}
/>
);
};
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
"data-row-key": string;
}
const Row: React.FC<RowProps> = (props) => {
const {
attributes,
listeners,
setNodeRef,
setActivatorNodeRef,
transform,
transition,
isDragging,
} = useSortable({ id: props["data-row-key"] });
const style: React.CSSProperties = {
...props.style,
transform: CSS.Translate.toString(transform),
transition,
...(isDragging ? { position: "relative", zIndex: 9999 } : {}),
};
const contextValue = useMemo<RowContextProps>(
() => ({ setActivatorNodeRef, listeners }),
[setActivatorNodeRef, listeners],
);
return (
<RowContext.Provider value={contextValue}>
<tr {...props} ref={setNodeRef} style={style} {...attributes} />
</RowContext.Provider>
);
};
const DrapableTable: React.FC = () => {
const { subject_id } = useParams<ParamsEnum>();
const response = useGetAllLesson({ subject_id: subject_id, pagination: false });
// Assuming the response contains a unique id for each item
const data =
response?.data?.data?.map((item: any, index: number) => ({
id: item.id, // Ensure this is a unique identifier
order: index + 1, // Assign order based on index
...item
})) ?? [];
const [dataSource, setDataSource] = React.useState<DataType[]>(data);
useEffect(() => {
// Update dataSource when the fetched data changes
const sortedData = data.sort((a: any, b: any) => a.order - b.order);
setDataSource(sortedData);
}, [response?.data?.data]);
const {mutate:orderLesson} = useUpdateLessonOrder()
const onDragEnd = ({ active, over }: DragEndEvent) => {
if (active.id !== over?.id) {
setDataSource((prevState) => {
const activeIndex = prevState.findIndex(
(record) => record.id === active.id,
);
const overIndex = prevState.findIndex(
//@ts-ignore
(record) => record.id === over.id,
);
// Move the items in the array
const newState = arrayMove(prevState, activeIndex, overIndex);
const orderedNewState = newState.map((item, index) => ({
...item,
order: index + 1, // Update the order based on the new index
}));
// Update the order based on the new positions
const orderedNewStateWithNewChape = orderedNewState?.map((item:any)=>{
return {
"lesson_id":item?.id,
"order":item?.order
}
})
orderLesson({lessons: orderedNewStateWithNewChape, _method:"PUT"})
return orderedNewState
});
}
};
const getRowClassName = (record: any, index: number): string => {
return index % 2 === 0 ? "even-row" : "odd-row";
};
const [t] = useTranslation()
const columns = useColumns();
const sortedDataSource = dataSource.sort((a, b) => a.order - b.order) ;
console.log(sortedDataSource,"sortedDataSource");
const isLoading = response?.isLoading
return (
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
<SortableContext
items={dataSource.map((i) => i.id)}
strategy={verticalListSortingStrategy}
>
<Table
rowKey="id"
components={{ body: { row: Row } }}
//@ts-ignore
columns={columns}
dataSource={sortedDataSource}
pagination={false}
rowClassName={(record, index) => getRowClassName(record, index)}
className="DataTable"
loading={{
spinning: isLoading,
indicator:<Suspense fallback={<></>}>
<LoadingLottie />
</Suspense> ,
size: "large",
}}
locale={{
emptyText: (
isLoading ?
<></>
:
<Suspense fallback={<></>}>
<NotFoundLottie
/>
</Suspense>
),
}}
/>
</SortableContext>
</DndContext>
);
};
export default DrapableTable;

View File

@ -42,6 +42,7 @@ const AddModel: React.FC = () => {
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
getInitialValues={getInitialValues({})} getInitialValues={getInitialValues({})}
getValidationSchema={getValidationSchema} getValidationSchema={getValidationSchema}
width="500px"
> >
<ModelForm /> <ModelForm />
</LayoutModel> </LayoutModel>

View File

@ -43,6 +43,7 @@ const ModalForm: React.FC = () => {
getInitialValues={getInitialValues(objectToEdit)} getInitialValues={getInitialValues(objectToEdit)}
getValidationSchema={getValidationSchema} getValidationSchema={getValidationSchema}
isAddModal={false} isAddModal={false}
width="500px"
> >
<ModelForm /> <ModelForm />
</LayoutModel> </LayoutModel>

View File

@ -15,7 +15,7 @@ import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
import FilterForm from "./Model/FilterForm"; import FilterForm from "./Model/FilterForm";
import { canAddLesson } from "../../../utils/hasAbilityFn"; import { canAddLesson } from "../../../utils/hasAbilityFn";
const Table = lazy(() => import("./Table")); const Table = lazy(() => import("./DrapableTable"));
const AddModalForm = lazy(() => import("./Model/AddModel")); const AddModalForm = lazy(() => import("./Model/AddModel"));
const EditModalForm = lazy(() => import("./Model/EditModel")); const EditModalForm = lazy(() => import("./Model/EditModel"));
const DeleteModelsForm = lazy( const DeleteModelsForm = lazy(

View File

@ -14,6 +14,7 @@ import {
canShowLesson, canShowLesson,
} from "../../../utils/hasAbilityFn"; } from "../../../utils/hasAbilityFn";
import ActionButtons from "../../../Components/Table/ActionButtons"; import ActionButtons from "../../../Components/Table/ActionButtons";
import { DragHandleLesson } from "./DrapableTable";
export const useColumns = () => { export const useColumns = () => {
const { handel_open_model } = useModalHandler(); const { handel_open_model } = useModalHandler();
@ -37,6 +38,7 @@ export const useColumns = () => {
const [t] = useTranslation(); const [t] = useTranslation();
const columns: TableColumnsType<Lesson> = [ const columns: TableColumnsType<Lesson> = [
{ key: "sort", align: "center", width: 80, render: () => <DragHandleLesson /> },
{ {
title: t("columns.id"), title: t("columns.id"),
dataIndex: "id", dataIndex: "id",

View File

@ -0,0 +1,25 @@
import React from 'react'
import ValidationField from '../../../Components/ValidationField/ValidationField'
import { Col, Row } from "reactstrap";
const FilterForm = () => {
return (
<div>
<Row>
<Col>
<ValidationField placeholder="name" label="name" name="name" />
<ValidationField placeholder="name" label="name" name="name" />
</Col>
<Col>
<ValidationField placeholder="name" label="name" name="name" />
<ValidationField placeholder="name" label="name" name="name" />
</Col>
</Row>
</div>
)
}
export default FilterForm

View File

@ -12,6 +12,11 @@ import { ModalEnum } from "../../../enums/Model";
import { useGetAllSubject } from "../../../api/subject"; import { useGetAllSubject } from "../../../api/subject";
import { useGetAllGrade } from "../../../api/grade"; import { useGetAllGrade } from "../../../api/grade";
import { useGetAllCurriculum } from "../../../api/curriculum"; import { useGetAllCurriculum } from "../../../api/curriculum";
import PageHeader from "../../../Layout/Dashboard/PageHeader";
import { ABILITIES_ENUM } from "../../../enums/abilities";
import { canAddQuestion } from "../../../utils/hasAbilityFn";
import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
import FilterForm from "./FilterForm";
const Table = lazy(() => import("./Table")); const Table = lazy(() => import("./Table"));
const TableHeader = () => { const TableHeader = () => {
@ -69,9 +74,15 @@ const TableHeader = () => {
return ( return (
<div className="TableWithHeader"> <div className="TableWithHeader">
<Suspense fallback={<Spin />}> <Suspense fallback={<Spin />}>
<header> <PageHeader
<h6>{t("models.Question")}</h6> pageTitle="question"
</header> ModelAbility={ModalEnum?.QUESTION_ACCEPT}
canAdd={canAddQuestion}
locationToNavigate={`${ABILITIES_ENUM?.QUESTION}/add`}
openModel={false}/>
<FilterLayout
sub_children={<FilterForm/>}
filterTitle="sidebar.question"/>
<Table /> <Table />
</Suspense> </Suspense>
<DeleteModels <DeleteModels

View File

@ -69,16 +69,10 @@ export const useColumns = () => {
}, },
{ {
title: canAddQuestion ? ( title: '#',
<button onClick={() => handelAdd()} className="add_button">
{t("practical.add")} {t("models.Question")} <FaPlus />
</button>
) : (
""
),
key: "actions", key: "actions",
align: "end", align: "center",
width: "25vw",
render: (_text, record, index) => { render: (_text, record, index) => {
return ( return (
<ActionButtons <ActionButtons

View File

@ -129,7 +129,7 @@ export const menuItems: TMenuItem[] = [
export const CrudRoute: TCrudRoute[] = [ export const CrudRoute: TCrudRoute[] = [
{ {
header: "page_header.grade_details", header: "page_header.Subject",
element: <Subject />, element: <Subject />,
path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}`, path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}`,
abilities: ABILITIES_ENUM?.SUBJECT, abilities: ABILITIES_ENUM?.SUBJECT,
@ -138,34 +138,26 @@ export const CrudRoute: TCrudRoute[] = [
}, },
{ {
header: "page_header.subject_details", header: "page_header.unit",
element: <Curriculum />,
path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}`,
abilities: ABILITIES_ENUM?.CURRICULUM,
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 2,
},
{
header: "page_header.curriculum_details",
element: <Unit />, element: <Unit />,
path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.CURRICULUM}/:${ParamsEnum?.CURRICULUM_ID}`, path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}`,
abilities: ABILITIES_ENUM?.UNIT, abilities: ABILITIES_ENUM?.UNIT,
abilities_value: ABILITIES_VALUES_ENUM.INDEX, abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 2, prevPath: 2,
}, },
{ {
header: "page_header.unit_details", header: "page_header.lesson",
element: <Lesson />, element: <Lesson />,
path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.CURRICULUM}/:${ParamsEnum?.CURRICULUM_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}`, path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}`,
abilities: ABILITIES_ENUM?.LESSON, abilities: ABILITIES_ENUM?.LESSON,
abilities_value: ABILITIES_VALUES_ENUM.INDEX, abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 2, prevPath: 2,
}, },
{ {
header: "page_header.lesson_details", header: "page_header.question",
element: <Question />, element: <Question />,
path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.CURRICULUM}/:${ParamsEnum?.CURRICULUM_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}/${ABILITIES_ENUM?.LESSON}/:${ParamsEnum?.LESSON_ID}`, path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}/${ABILITIES_ENUM?.LESSON}/:${ParamsEnum?.LESSON_ID}`,
abilities: ABILITIES_ENUM?.QUESTION, abilities: ABILITIES_ENUM?.QUESTION,
abilities_value: ABILITIES_VALUES_ENUM.INDEX, abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 2, prevPath: 2,
@ -173,7 +165,7 @@ export const CrudRoute: TCrudRoute[] = [
{ {
header: "page_header.add_Question", header: "page_header.add_Question",
element: <AddQuestionPage />, element: <AddQuestionPage />,
path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.CURRICULUM}/:${ParamsEnum?.CURRICULUM_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}/${ABILITIES_ENUM?.LESSON}/:${ParamsEnum?.LESSON_ID}/${ABILITIES_ENUM?.QUESTION}/add`, path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}/${ABILITIES_ENUM?.LESSON}/:${ParamsEnum?.LESSON_ID}/${ABILITIES_ENUM?.QUESTION}/add`,
abilities: ABILITIES_ENUM?.QUESTION, abilities: ABILITIES_ENUM?.QUESTION,
abilities_value: ABILITIES_VALUES_ENUM.INDEX, abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 2, prevPath: 2,
@ -181,7 +173,7 @@ export const CrudRoute: TCrudRoute[] = [
{ {
header: "page_header.edit_Question", header: "page_header.edit_Question",
element: <EditQuestionPage />, element: <EditQuestionPage />,
path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.CURRICULUM}/:${ParamsEnum?.CURRICULUM_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}/${ABILITIES_ENUM?.LESSON}/:${ParamsEnum?.LESSON_ID}/${ABILITIES_ENUM?.QUESTION}/:${ParamsEnum?.QUESTION_ID}`, path: `/${ABILITIES_ENUM?.GRADE}/:${ParamsEnum?.GRADE_ID}/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}/${ABILITIES_ENUM?.LESSON}/:${ParamsEnum?.LESSON_ID}/${ABILITIES_ENUM?.QUESTION}/:${ParamsEnum?.QUESTION_ID}`,
abilities: ABILITIES_ENUM?.QUESTION, abilities: ABILITIES_ENUM?.QUESTION,
abilities_value: ABILITIES_VALUES_ENUM.INDEX, abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 2, prevPath: 2,

View File

@ -1,5 +1,5 @@
export const BaseURL = "https://exercise-automation.point-dev.net/api/"; export const BaseURL = "https://nerd-back.point-dev.net/api/";
export const ImageBaseURL = "https://exercise-automation.point-dev.net/"; export const ImageBaseURL = "https://nerd-back.point-dev.net/api/";
export const HEADER_KEY = "X-Custom-Query-Key"; export const HEADER_KEY = "X-Custom-Query-Key";

View File

@ -8,6 +8,7 @@ const API = {
ADD: "/lesson", ADD: "/lesson",
DELETE: "/lesson", DELETE: "/lesson",
UPDATE: "/lesson", UPDATE: "/lesson",
ORDER: "/lesson/order",
}; };
const KEY = "lesson"; const KEY = "lesson";
@ -19,3 +20,5 @@ export const useUpdateLesson = (params?: any) =>
useUpdateMutation(KEY, API.GET); useUpdateMutation(KEY, API.GET);
export const useDeleteLesson = (params?: any) => export const useDeleteLesson = (params?: any) =>
useDeleteMutation(KEY, API.DELETE); useDeleteMutation(KEY, API.DELETE);
export const useUpdateLessonOrder = (params?: any) => useAddMutation("karim", API.ORDER);

View File

@ -8,6 +8,7 @@ const API = {
ADD: "/unit", ADD: "/unit",
DELETE: "/unit", DELETE: "/unit",
UPDATE: "/unit", UPDATE: "/unit",
ORDER: "/unit/order",
}; };
const KEY = "unit"; const KEY = "unit";
@ -15,5 +16,6 @@ export const useGetAllUnit = (params?: any, options?: any) =>
useGetQuery(KEY, API.GET, params, options); useGetQuery(KEY, API.GET, params, options);
export const useAddUnit = () => useAddMutation(KEY, API.ADD); export const useAddUnit = () => useAddMutation(KEY, API.ADD);
export const useUpdateUnit = (params?: any) => useUpdateMutation(KEY, API.GET); export const useUpdateUnit = (params?: any) => useUpdateMutation(KEY, API.GET);
export const useUpdateUnitOrder = (params?: any,option?: any,) => useAddMutation("karim", API.ORDER,true);
export const useDeleteUnit = (params?: any) => export const useDeleteUnit = (params?: any) =>
useDeleteMutation(KEY, API.DELETE); useDeleteMutation(KEY, API.DELETE);