work on question
This commit is contained in:
parent
e8cc73ecc3
commit
aece39ae8f
|
|
@ -4,17 +4,26 @@
|
||||||
"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",
|
||||||
|
"@types/react-beautiful-dnd": "^13.1.8",
|
||||||
|
"@types/react-dragula": "^1.1.3",
|
||||||
"antd": "^5.17.4",
|
"antd": "^5.17.4",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"bootstrap": "^5.3.3",
|
"bootstrap": "^5.3.3",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
|
"dragula": "^3.7.3",
|
||||||
"formik": "^2.4.6",
|
"formik": "^2.4.6",
|
||||||
"html-to-image": "^1.11.11",
|
"html-to-image": "^1.11.11",
|
||||||
"i18next": "^23.11.5",
|
"i18next": "^23.11.5",
|
||||||
"path-to-regexp": "^6.2.2",
|
"path-to-regexp": "^6.2.2",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-dragula": "^1.1.17",
|
||||||
"react-i18next": "^13.5.0",
|
"react-i18next": "^13.5.0",
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^4.12.0",
|
||||||
"react-query": "^3.39.3",
|
"react-query": "^3.39.3",
|
||||||
|
|
|
||||||
8759
pnpm-lock.yaml
8759
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
26
src/Components/DrapableTable/DragHandle.tsx
Normal file
26
src/Components/DrapableTable/DragHandle.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { HolderOutlined } from "@ant-design/icons";
|
||||||
|
import { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities";
|
||||||
|
import { Button } from "antd";
|
||||||
|
import React, { useContext } from "react";
|
||||||
|
|
||||||
|
export const DragHandle: React.FC = () => {
|
||||||
|
|
||||||
|
interface RowContextProps {
|
||||||
|
setActivatorNodeRef?: (element: HTMLElement | null) => void;
|
||||||
|
listeners?: SyntheticListenerMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RowContext = React.createContext<RowContextProps>({});
|
||||||
|
const { setActivatorNodeRef, listeners } = useContext(RowContext);
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<HolderOutlined />}
|
||||||
|
style={{ cursor: 'move' }}
|
||||||
|
ref={setActivatorNodeRef}
|
||||||
|
{...listeners}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
128
src/Components/DrapableTable/DrapableTable.tsx
Normal file
128
src/Components/DrapableTable/DrapableTable.tsx
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
import React, { useContext, 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 type { TableColumnsType } from 'antd';
|
||||||
|
|
||||||
|
interface DataType {
|
||||||
|
key: string;
|
||||||
|
order: number;
|
||||||
|
name: string;
|
||||||
|
age: number;
|
||||||
|
address: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RowContextProps {
|
||||||
|
setActivatorNodeRef?: (element: HTMLElement | null) => void;
|
||||||
|
listeners?: SyntheticListenerMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RowContext = React.createContext<RowContextProps>({});
|
||||||
|
|
||||||
|
const DragHandle: React.FC = () => {
|
||||||
|
const { setActivatorNodeRef, listeners } = useContext(RowContext);
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<HolderOutlined />}
|
||||||
|
style={{ cursor: 'move' }}
|
||||||
|
ref={setActivatorNodeRef}
|
||||||
|
{...listeners}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: TableColumnsType<DataType> = [
|
||||||
|
{ key: 'sort', align: 'center', width: 80, render: () => <DragHandle /> },
|
||||||
|
{ title: 'Name', dataIndex: 'name' },
|
||||||
|
{ title: 'Age', dataIndex: 'age' },
|
||||||
|
{ title: 'Address', dataIndex: 'address' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const initialData: DataType[] = [
|
||||||
|
{ key: '1', order: 1, name: '1', age: 32, address: 'Long text Long' },
|
||||||
|
{ key: '4', order: 4, name: '4', age: 42, address: 'London No. 1 Lake Park' },
|
||||||
|
{ key: '3', order: 3, name: '3', age: 32, address: 'Sidney No. 1 Lake Park' },
|
||||||
|
].sort((a, b) => a.order - b.order);
|
||||||
|
|
||||||
|
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 [dataSource, setDataSource] = React.useState<DataType[]>(initialData);
|
||||||
|
|
||||||
|
const onDragEnd = ({ active, over }: DragEndEvent) => {
|
||||||
|
if (active.id !== over?.id) {
|
||||||
|
// Log the old state before reordering
|
||||||
|
console.log("Old Data:", dataSource);
|
||||||
|
|
||||||
|
setDataSource((prevState) => {
|
||||||
|
const activeIndex = prevState.findIndex((record) => record.key === active?.id);
|
||||||
|
const overIndex = prevState.findIndex((record) => record.key === over?.id);
|
||||||
|
const newState = arrayMove(prevState, activeIndex, overIndex);
|
||||||
|
|
||||||
|
// Log the new state after reordering
|
||||||
|
console.log("New Data:", newState);
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
|
||||||
|
<SortableContext items={dataSource.map((i) => i.key)} strategy={verticalListSortingStrategy}>
|
||||||
|
<Table
|
||||||
|
rowKey="key"
|
||||||
|
components={{ body: { row: Row } }}
|
||||||
|
columns={columns}
|
||||||
|
dataSource={dataSource}
|
||||||
|
/>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DrapableTable;
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { Checkbox, Form } from "antd";
|
import { Checkbox, Form } from "antd";
|
||||||
|
|
@ -13,7 +14,7 @@ const CheckboxField = ({
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { t, formik, isError, errorMsg } = useFormField(name, props);
|
const { t, formik, isError, errorMsg } = useFormField(name, props);
|
||||||
const CheckboxhandleChange = (value: any) => {
|
const CheckboxhandleChange = (value: any) => {
|
||||||
formik.setFieldValue(name, value?.target?.checked);
|
formik.setFieldValue(name, value?.target?.checked ? 1 : 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -26,7 +27,7 @@ const CheckboxField = ({
|
||||||
<Checkbox
|
<Checkbox
|
||||||
onChange={onChange || CheckboxhandleChange}
|
onChange={onChange || CheckboxhandleChange}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
checked={formik.values?.[name] ?? false}
|
checked={formik.values?.[name] === 1}
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
{t(`input.${label ? label : name}`)}
|
{t(`input.${label ? label : name}`)}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@ const File = ({
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { formik, t, isError, errorMsg } = useFormField(name, props);
|
const { formik, t, isError, errorMsg } = useFormField(name, props);
|
||||||
let imageUrl = formik?.values?.[name] ?? null;
|
let imageUrl = formik?.values?.[name] ?? null;
|
||||||
console.log(imageUrl);
|
|
||||||
console.log(typeof imageUrl === "string");
|
|
||||||
|
|
||||||
const fileList: UploadFile[] = useMemo(() => {
|
const fileList: UploadFile[] = useMemo(() => {
|
||||||
if (!imageUrl) return [];
|
if (!imageUrl) return [];
|
||||||
|
|
|
||||||
128
src/Layout/Dashboard/Table/DataTableWithDrag.tsx
Normal file
128
src/Layout/Dashboard/Table/DataTableWithDrag.tsx
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
import React, { useContext, 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 type { TableColumnsType } from 'antd';
|
||||||
|
|
||||||
|
interface DataType {
|
||||||
|
key: string;
|
||||||
|
order: number;
|
||||||
|
name: string;
|
||||||
|
age: number;
|
||||||
|
address: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RowContextProps {
|
||||||
|
setActivatorNodeRef?: (element: HTMLElement | null) => void;
|
||||||
|
listeners?: SyntheticListenerMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RowContext = React.createContext<RowContextProps>({});
|
||||||
|
|
||||||
|
const DragHandle: React.FC = () => {
|
||||||
|
const { setActivatorNodeRef, listeners } = useContext(RowContext);
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<HolderOutlined />}
|
||||||
|
style={{ cursor: 'move' }}
|
||||||
|
ref={setActivatorNodeRef}
|
||||||
|
{...listeners}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: TableColumnsType<DataType> = [
|
||||||
|
{ key: 'sort', align: 'center', width: 80, render: () => <DragHandle /> },
|
||||||
|
{ title: 'Name', dataIndex: 'name' },
|
||||||
|
{ title: 'Age', dataIndex: 'age' },
|
||||||
|
{ title: 'Address', dataIndex: 'address' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const initialData: DataType[] = [
|
||||||
|
{ key: '1', order: 1, name: '1', age: 32, address: 'Long text Long' },
|
||||||
|
{ key: '4', order: 4, name: '4', age: 42, address: 'London No. 1 Lake Park' },
|
||||||
|
{ key: '3', order: 3, name: '3', age: 32, address: 'Sidney No. 1 Lake Park' },
|
||||||
|
].sort((a, b) => a.order - b.order);
|
||||||
|
|
||||||
|
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 App: React.FC = () => {
|
||||||
|
const [dataSource, setDataSource] = React.useState<DataType[]>(initialData);
|
||||||
|
|
||||||
|
const onDragEnd = ({ active, over }: DragEndEvent) => {
|
||||||
|
if (active.id !== over?.id) {
|
||||||
|
// Log the old state before reordering
|
||||||
|
console.log("Old Data:", dataSource);
|
||||||
|
|
||||||
|
setDataSource((prevState) => {
|
||||||
|
const activeIndex = prevState.findIndex((record) => record.key === active?.id);
|
||||||
|
const overIndex = prevState.findIndex((record) => record.key === over?.id);
|
||||||
|
const newState = arrayMove(prevState, activeIndex, overIndex);
|
||||||
|
|
||||||
|
// Log the new state after reordering
|
||||||
|
console.log("New Data:", newState);
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
|
||||||
|
<SortableContext items={dataSource.map((i) => i.key)} strategy={verticalListSortingStrategy}>
|
||||||
|
<Table
|
||||||
|
rowKey="key"
|
||||||
|
components={{ body: { row: Row } }}
|
||||||
|
columns={columns}
|
||||||
|
dataSource={dataSource}
|
||||||
|
/>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
|
@ -7,6 +7,7 @@ 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 { useDeleteCurriculum } from "../../api/curriculum";
|
import { useDeleteCurriculum } from "../../api/curriculum";
|
||||||
|
import { useGetAllGrade } from "../../api/grade";
|
||||||
|
|
||||||
const Table = lazy(() => import('./Table'));
|
const Table = lazy(() => import('./Table'));
|
||||||
const AddModalForm = lazy(() => import('./Model/AddModel'));
|
const AddModalForm = lazy(() => import('./Model/AddModel'));
|
||||||
|
|
@ -17,22 +18,28 @@ const TableHeader = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const deleteMutation = useDeleteCurriculum();
|
const deleteMutation = useDeleteCurriculum();
|
||||||
|
|
||||||
const { subject_id} = useParams<ParamsEnum>();
|
const { subject_id,grade_id} = useParams<ParamsEnum>();
|
||||||
|
|
||||||
const { data: Subject } = useGetAllSubject({
|
const { data: Subject } = useGetAllSubject({
|
||||||
show: subject_id,
|
show: subject_id,
|
||||||
});
|
});
|
||||||
|
const { data: grade } = useGetAllGrade({
|
||||||
|
show: grade_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const gradeName = grade?.data?.name ?? "";
|
||||||
|
|
||||||
const SubjectName = Subject?.data?.name ?? "";
|
const SubjectName = Subject?.data?.name ?? "";
|
||||||
|
|
||||||
useSetPageTitle(t(`page_header.curriculum`) + "/" + t(`${SubjectName}`));
|
useSetPageTitle( t(`page_header.grade`)+ "/"+ gradeName +"/"+t(`PageTitle.subject`)+"/"+SubjectName+"/"+t("PageTitle.curriculum"));
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
<Suspense fallback={<Spin />}>
|
<Suspense fallback={<Spin />}>
|
||||||
<header>
|
<header>
|
||||||
<h6>
|
<h6>
|
||||||
{t("models.curriculum")} {SubjectName}
|
{t("models.curriculum")}
|
||||||
</h6>
|
</h6>
|
||||||
</header>
|
</header>
|
||||||
<Table />
|
<Table />
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@ const TableHeader = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const deleteMutation = useDeleteGrade();
|
const deleteMutation = useDeleteGrade();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useSetPageTitle(t(`page_header.grade`));
|
useSetPageTitle(t(`page_header.grade`));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
145
src/Pages/Unit/DrapableTable.tsx
Normal file
145
src/Pages/Unit/DrapableTable.tsx
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
import React, { 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 type { TableColumnsType } from 'antd';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { ParamsEnum } from '../../enums/params';
|
||||||
|
import { useGetAllUnit } from '../../api/unit';
|
||||||
|
|
||||||
|
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>({});
|
||||||
|
|
||||||
|
const DragHandle: React.FC = () => {
|
||||||
|
const { setActivatorNodeRef, listeners } = useContext(RowContext);
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<HolderOutlined />}
|
||||||
|
style={{ cursor: 'move' }}
|
||||||
|
ref={setActivatorNodeRef}
|
||||||
|
{...listeners}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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> {
|
||||||
|
'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 = useGetAllUnit({ 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
|
||||||
|
name: item.name,
|
||||||
|
age: item.age,
|
||||||
|
address: item.address,
|
||||||
|
})) ?? [];
|
||||||
|
|
||||||
|
const [dataSource, setDataSource] = React.useState<DataType[]>(data);
|
||||||
|
console.log(dataSource,"dataSource");
|
||||||
|
|
||||||
|
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 onDragEnd = ({ active, over }: DragEndEvent) => {
|
||||||
|
if (active.id !== over?.id) {
|
||||||
|
setDataSource((prevState) => {
|
||||||
|
const activeIndex = prevState.findIndex((record) => record.id === active.id);
|
||||||
|
const overIndex = prevState.findIndex((record) => record.id === over.id);
|
||||||
|
|
||||||
|
// Move the items in the array
|
||||||
|
const newState = arrayMove(prevState, activeIndex, overIndex);
|
||||||
|
|
||||||
|
// Update the order based on the new positions
|
||||||
|
return newState.map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
order: index + 1, // Update the order based on the new index
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
|
||||||
|
<SortableContext items={dataSource.map((i) => i.id)} strategy={verticalListSortingStrategy}>
|
||||||
|
<Table
|
||||||
|
rowKey="id"
|
||||||
|
components={{ body: { row: Row } }}
|
||||||
|
columns={columns}
|
||||||
|
dataSource={dataSource.sort((a, b) => a.order - b.order)} // Sort by order for rendering
|
||||||
|
pagination={false}
|
||||||
|
/>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DrapableTable;
|
||||||
|
|
@ -6,15 +6,25 @@ import { QueryStatusEnum } from "../../../enums/QueryStatus";
|
||||||
import ModelForm from "./ModelForm";
|
import ModelForm from "./ModelForm";
|
||||||
import { useAddUnit } from "../../../api/unit";
|
import { useAddUnit } from "../../../api/unit";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
const AddModel: React.FC = () => {
|
const AddModel: React.FC = () => {
|
||||||
const { mutate, status } = useAddUnit();
|
const { mutate, status } = useAddUnit();
|
||||||
const { subject_id } = useParams();
|
const { curriculum_id } = useParams();
|
||||||
|
const {OldObjectToEdit} = useObjectToEdit()
|
||||||
|
|
||||||
const handleSubmit = (values: any) => {
|
const handleSubmit = (values: any) => {
|
||||||
|
let order = 0 ;
|
||||||
|
if(OldObjectToEdit?.order || OldObjectToEdit?.order === 0){
|
||||||
|
order = Number(OldObjectToEdit.order) + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mutate({
|
mutate({
|
||||||
...values,
|
...values,
|
||||||
subject_id: subject_id,
|
curriculum_id: curriculum_id,
|
||||||
|
order:order
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
|
@ -26,7 +36,7 @@ const AddModel: React.FC = () => {
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
getInitialValues={getInitialValues({})}
|
getInitialValues={getInitialValues({})}
|
||||||
getValidationSchema={getValidationSchema}
|
getValidationSchema={getValidationSchema}
|
||||||
width="40vw"
|
width="60vw"
|
||||||
>
|
>
|
||||||
<ModelForm />
|
<ModelForm />
|
||||||
</LayoutModel>
|
</LayoutModel>
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,16 @@ import LayoutModel from "../../../Layout/Dashboard/LayoutModel";
|
||||||
import ModelForm from "./ModelForm";
|
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 { useUpdateTag } from "../../../api/tags";
|
|
||||||
import { useUpdateUnit } from "../../../api/unit";
|
import { useUpdateUnit } from "../../../api/unit";
|
||||||
import { useParams } from "react-router-dom";
|
|
||||||
|
|
||||||
const EditModel: React.FC = () => {
|
const EditModel: React.FC = () => {
|
||||||
const { mutate, status } = useUpdateUnit();
|
const { mutate, status } = useUpdateUnit();
|
||||||
const { objectToEdit } = useObjectToEdit((state) => state);
|
const { objectToEdit } = useObjectToEdit((state) => state);
|
||||||
|
|
||||||
const { subject_id } = useParams();
|
|
||||||
|
|
||||||
const handleSubmit = (values: any) => {
|
const handleSubmit = (values: any) => {
|
||||||
mutate({
|
mutate({
|
||||||
...values,
|
...values,
|
||||||
subject_id: subject_id,
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -32,7 +28,7 @@ const EditModel: React.FC = () => {
|
||||||
getInitialValues={getInitialValues(objectToEdit)}
|
getInitialValues={getInitialValues(objectToEdit)}
|
||||||
getValidationSchema={getValidationSchema}
|
getValidationSchema={getValidationSchema}
|
||||||
isAddModal={false}
|
isAddModal={false}
|
||||||
width="40vw"
|
width="60vw"
|
||||||
>
|
>
|
||||||
<ModelForm />
|
<ModelForm />
|
||||||
</LayoutModel>
|
</LayoutModel>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,21 @@
|
||||||
import { Col, Row } from "reactstrap";
|
import { Col, Row } from "reactstrap";
|
||||||
import ValidationField from "../../../Components/ValidationField/ValidationField";
|
import ValidationField from "../../../Components/ValidationField/ValidationField";
|
||||||
|
import { TermEnum } from "../../../enums/Term";
|
||||||
|
import { enumToArray } from "../../../utils/enumToArray";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
|
|
||||||
|
const termsArray = enumToArray(TermEnum);
|
||||||
|
console.log(termsArray,"termsArray");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="w-100">
|
<Row className="w-100">
|
||||||
<Col>
|
<Col>
|
||||||
<ValidationField name="name" placeholder="name" label="name" />
|
<ValidationField name="name" placeholder="name" label="name" />
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<ValidationField name="term" type="Select" placeholder="term" label="term" option={termsArray} />
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
|
import { UnitInitialValues,Unit } from "../../../types/Unit";
|
||||||
|
|
||||||
export const getInitialValues = (objectToEdit: any): any => {
|
export const getInitialValues = (objectToEdit: Partial<Unit>): UnitInitialValues => {
|
||||||
return {
|
return {
|
||||||
id: objectToEdit?.id,
|
id: objectToEdit?.id,
|
||||||
name: objectToEdit?.name ?? "",
|
name: objectToEdit?.name ?? null,
|
||||||
|
term: objectToEdit?.term ?? null,
|
||||||
|
order: objectToEdit?.order ?? null,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -11,6 +14,7 @@ export const getValidationSchema = () => {
|
||||||
// validate input
|
// validate input
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
name: Yup.string().required("validation.required"),
|
name: Yup.string().required("validation.required"),
|
||||||
|
term: Yup.string().required("validation.required"),
|
||||||
// subject_id: Yup.string().required('validation.required'),
|
// subject_id: Yup.string().required('validation.required'),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ 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 { useGetAllCurriculum } from "../../api/curriculum";
|
||||||
|
|
||||||
const Table = lazy(() => import('./Table'));
|
const Table = lazy(() => import('./Table'));
|
||||||
const AddModalForm = lazy(() => import('./Model/AddModel'));
|
const AddModalForm = lazy(() => import('./Model/AddModel'));
|
||||||
|
|
@ -17,23 +20,34 @@ const TableHeader = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const deleteMutation = useDeleteUnit();
|
const deleteMutation = useDeleteUnit();
|
||||||
|
|
||||||
const { subject_id} = useParams<ParamsEnum>();
|
const { subject_id,grade_id,curriculum_id} = useParams<ParamsEnum>();
|
||||||
|
|
||||||
const { data: Subject } = useGetAllSubject({
|
const { data: Subject } = useGetAllSubject({
|
||||||
show: subject_id,
|
show: subject_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const SubjectName = Subject?.data?.name ?? "";
|
const { data: grade } = useGetAllGrade({
|
||||||
|
show: grade_id,
|
||||||
|
});
|
||||||
|
const { data: Curriculum } = useGetAllCurriculum({
|
||||||
|
show: curriculum_id,
|
||||||
|
});
|
||||||
|
const gradeName = grade?.data?.name ?? "";
|
||||||
|
|
||||||
|
const SubjectName = Subject?.data?.name ?? "";
|
||||||
|
const CurriculumName = Curriculum?.data?.name ?? "";
|
||||||
|
useSetPageTitle( t(`page_header.grade`)+ "/"+ gradeName +"/"+t(`PageTitle.subject`)+"/"+SubjectName+"/"+t("PageTitle.curriculum")+"/"+CurriculumName+"/"+t("PageTitle.unit"));
|
||||||
|
|
||||||
|
|
||||||
useSetPageTitle(t(`page_header.subject`) + "/" + t(`${SubjectName}`));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
<Suspense fallback={<Spin />}>
|
<Suspense fallback={<Spin />}>
|
||||||
<header>
|
<header>
|
||||||
<h6>
|
<h6>
|
||||||
{t("models.units")} {SubjectName}
|
{t("models.units")}
|
||||||
</h6>
|
</h6>
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
<Table />
|
<Table />
|
||||||
<AddModalForm />
|
<AddModalForm />
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,25 @@
|
||||||
import { useColumns } from "./useTableColumns";
|
import { useColumns } from "./useTableColumns";
|
||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import DataTable from "../../Layout/Dashboard/Table/DataTable";
|
import DataTable from "../../Layout/Dashboard/Table/DataTable";
|
||||||
import { useGetAllUnit } from "../../api/unit";
|
import { useGetAllUnit } from "../../api/unit";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../enums/params";
|
import { ParamsEnum } from "../../enums/params";
|
||||||
|
import { useObjectToEdit } from "../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const { subject_id } = useParams<ParamsEnum>();
|
const { subject_id } = useParams<ParamsEnum>();
|
||||||
const response = useGetAllUnit({ subject_id: subject_id, pagination: true });
|
const response = useGetAllUnit({ subject_id: subject_id, pagination: true });
|
||||||
|
const {setOldObjectToEdit} = useObjectToEdit()
|
||||||
console.log(response?.data?.data, "response?.data");
|
console.log(response?.data?.data, "response?.data");
|
||||||
|
const data = response?.data?.data;
|
||||||
|
const lastElement = response?.data?.data && response?.data?.data[data?.length - 1]
|
||||||
|
console.log(lastElement);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(lastElement){
|
||||||
|
setOldObjectToEdit(lastElement)
|
||||||
|
}
|
||||||
|
}, [lastElement])
|
||||||
|
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { Space, TableColumnsType, Tooltip } from "antd";
|
import { Space, TableColumnsType, Tooltip } from "antd";
|
||||||
import { Unit } from "../../types/Item";
|
|
||||||
import { FaPlus } from "react-icons/fa";
|
import { FaPlus } from "react-icons/fa";
|
||||||
import useModalHandler from "../../utils/useModalHandler";
|
import useModalHandler from "../../utils/useModalHandler";
|
||||||
import { ModalEnum } from "../../enums/Model";
|
import { ModalEnum } from "../../enums/Model";
|
||||||
|
|
@ -17,6 +16,7 @@ import {
|
||||||
canShowUnit,
|
canShowUnit,
|
||||||
} from "../../utils/hasAbilityFn";
|
} from "../../utils/hasAbilityFn";
|
||||||
import ActionButtons from "../../Components/Table/ActionButtons";
|
import ActionButtons from "../../Components/Table/ActionButtons";
|
||||||
|
import { Unit } from "../../types/Unit";
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
const { handel_open_model } = useModalHandler();
|
const { handel_open_model } = useModalHandler();
|
||||||
|
|
@ -24,16 +24,16 @@ export const useColumns = () => {
|
||||||
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handelShow = (record: any) => {
|
const handelShow = (record: Unit) => {
|
||||||
navigate(`${ABILITIES_ENUM?.UNIT}/${record?.id}`);
|
navigate(`${ABILITIES_ENUM?.UNIT}/${record?.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handelDelete = (data: any) => {
|
const handelDelete = (data: Unit) => {
|
||||||
setObjectToEdit(data);
|
setObjectToEdit(data);
|
||||||
handel_open_model(ModalEnum?.UNIT_DELETE);
|
handel_open_model(ModalEnum?.UNIT_DELETE);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEdit = (record: any) => {
|
const handleEdit = (record: Unit) => {
|
||||||
setObjectToEdit(record);
|
setObjectToEdit(record);
|
||||||
handel_open_model(ModalEnum?.UNIT_EDIT);
|
handel_open_model(ModalEnum?.UNIT_EDIT);
|
||||||
};
|
};
|
||||||
|
|
@ -56,11 +56,11 @@ export const useColumns = () => {
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t("columns.lesson_count"),
|
title: t("columns.term"),
|
||||||
dataIndex: "lesson_count",
|
dataIndex: "term",
|
||||||
key: "lesson_count",
|
key: "term",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) => record?.lessons_count,
|
render: (text, record) => record?.term,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,14 @@ import { useAddLesson } from "../../../api/lesson";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../../enums/params";
|
import { ParamsEnum } from "../../../enums/params";
|
||||||
import { useModalState } from "../../../zustand/Modal";
|
import { useModalState } from "../../../zustand/Modal";
|
||||||
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
const AddModel: React.FC = () => {
|
const AddModel: React.FC = () => {
|
||||||
|
|
||||||
const { isOpen, setIsOpen } = useModalState((state) => state);
|
const { isOpen, setIsOpen } = useModalState((state) => state);
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { mutate, isSuccess, status } = useAddLesson();
|
const { mutate, isSuccess, status } = useAddLesson();
|
||||||
|
const {OldObjectToEdit} = useObjectToEdit()
|
||||||
const { unit_id } = useParams<ParamsEnum>();
|
const { unit_id } = useParams<ParamsEnum>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
|
|
@ -25,6 +26,13 @@ const AddModel: React.FC = () => {
|
||||||
}, [setIsOpen, isSuccess, queryClient]);
|
}, [setIsOpen, isSuccess, queryClient]);
|
||||||
|
|
||||||
const handleSubmit = (values: any) => {
|
const handleSubmit = (values: any) => {
|
||||||
|
|
||||||
|
let order = 0 ;
|
||||||
|
if(OldObjectToEdit?.order || OldObjectToEdit?.order === 0){
|
||||||
|
order = Number(OldObjectToEdit.order) + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
mutate({ ...values, unit_id: unit_id });
|
mutate({ ...values, unit_id: unit_id });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ import { ParamsEnum } from "../../enums/params";
|
||||||
import { useGetAllUnit } from "../../api/unit";
|
import { useGetAllUnit } from "../../api/unit";
|
||||||
import { ModalEnum } from "../../enums/Model";
|
import { ModalEnum } from "../../enums/Model";
|
||||||
import { useDeleteLesson } from "../../api/lesson";
|
import { useDeleteLesson } from "../../api/lesson";
|
||||||
|
import { useGetAllGrade } from "../../api/grade";
|
||||||
|
import { useGetAllCurriculum } from "../../api/curriculum";
|
||||||
|
import { useGetAllSubject } from "../../api/subject";
|
||||||
|
|
||||||
const Table = lazy(() => import('./Table'));
|
const Table = lazy(() => import('./Table'));
|
||||||
const AddModalForm = lazy(() => import('./Model/AddModel'));
|
const AddModalForm = lazy(() => import('./Model/AddModel'));
|
||||||
|
|
@ -17,22 +20,29 @@ const TableHeader = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const deleteMutation = useDeleteLesson();
|
const deleteMutation = useDeleteLesson();
|
||||||
|
|
||||||
const { unit_id } = useParams<ParamsEnum>();
|
const { unit_id,curriculum_id,grade_id ,subject_id} = useParams<ParamsEnum>();
|
||||||
const { data: unit } = useGetAllUnit({ show: unit_id });
|
const { data: unit } = useGetAllUnit({ show: unit_id });
|
||||||
|
|
||||||
|
|
||||||
|
const { data: Subject } = useGetAllSubject({
|
||||||
|
show: subject_id,
|
||||||
|
});
|
||||||
|
const { data: grade } = useGetAllGrade({
|
||||||
|
show: grade_id,
|
||||||
|
});
|
||||||
|
const { data: Curriculum } = useGetAllCurriculum({
|
||||||
|
show: curriculum_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const gradeName = grade?.data?.name ?? "";
|
||||||
|
const SubjectName = Subject?.data?.name ?? "";
|
||||||
|
const CurriculumName = Curriculum?.data?.name ?? "";
|
||||||
const unitName = unit?.data?.name ?? "";
|
const unitName = unit?.data?.name ?? "";
|
||||||
const SubjectName = unit?.data?.subject?.name ?? "";
|
|
||||||
|
|
||||||
console.log(unit?.data);
|
|
||||||
|
|
||||||
useSetPageTitle(
|
useSetPageTitle( t(`page_header.grade`)+ "/"+ gradeName +"/"+t(`PageTitle.subject`)+"/"+SubjectName+"/"+t("PageTitle.curriculum")+"/"+CurriculumName+"/"+t("PageTitle.unit")+"/"+unitName+"/"+t("PageTitle.lesson"));
|
||||||
t(`page_header.subject`) +
|
|
||||||
"/" +
|
|
||||||
`${SubjectName}` +
|
|
||||||
"/" +
|
|
||||||
t(`PageTitle.unit`) +
|
|
||||||
"/" +
|
|
||||||
`${unitName}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,27 @@
|
||||||
import { useColumns } from "./useTableColumns";
|
import { useColumns } from "./useTableColumns";
|
||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import DataTable from "../../Layout/Dashboard/Table/DataTable";
|
import DataTable from "../../Layout/Dashboard/Table/DataTable";
|
||||||
import { useGetAllLesson } from "../../api/lesson";
|
import { useGetAllLesson } from "../../api/lesson";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../enums/params";
|
import { ParamsEnum } from "../../enums/params";
|
||||||
|
import { useObjectToEdit } from "../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const { unit_id } = useParams<ParamsEnum>();
|
const { unit_id } = useParams<ParamsEnum>();
|
||||||
const response = useGetAllLesson({ unit_id: unit_id, pagination: true });
|
const response = useGetAllLesson({ unit_id: unit_id, pagination: true });
|
||||||
|
|
||||||
|
const {setOldObjectToEdit} = useObjectToEdit()
|
||||||
|
console.log(response?.data?.data, "response?.data");
|
||||||
|
const data = response?.data?.data;
|
||||||
|
const lastElement = response?.data?.data && response?.data?.data[data?.length - 1]
|
||||||
|
console.log(lastElement);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(lastElement){
|
||||||
|
setOldObjectToEdit(lastElement)
|
||||||
|
}
|
||||||
|
}, [lastElement])
|
||||||
|
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ import { toast } from "react-toastify";
|
||||||
import useSetPageTitle from "../../Hooks/useSetPageTitle";
|
import useSetPageTitle from "../../Hooks/useSetPageTitle";
|
||||||
import { useGetAllUnit } from "../../api/unit";
|
import { useGetAllUnit } from "../../api/unit";
|
||||||
import { useGetAllLesson } from "../../api/lesson";
|
import { useGetAllLesson } from "../../api/lesson";
|
||||||
|
import { useGetAllSubject } from "../../api/subject";
|
||||||
|
import { useGetAllGrade } from "../../api/grade";
|
||||||
|
import { useGetAllCurriculum } from "../../api/curriculum";
|
||||||
|
|
||||||
const AddPage: React.FC = () => {
|
const AddPage: React.FC = () => {
|
||||||
const { isSuccess: isSuccessAsync, mutateAsync } = useAddQuestionAsync();
|
const { isSuccess: isSuccessAsync, mutateAsync } = useAddQuestionAsync();
|
||||||
|
|
@ -43,41 +46,42 @@ const AddPage: React.FC = () => {
|
||||||
SavedQuestionData,
|
SavedQuestionData,
|
||||||
} = useObjectToEdit();
|
} = useObjectToEdit();
|
||||||
|
|
||||||
const { subject_id, lesson_id, unit_id } = useParams<ParamsEnum>();
|
|
||||||
const { setIsOpen } = useModalState((state) => state);
|
const { setIsOpen } = useModalState((state) => state);
|
||||||
|
|
||||||
const { data: unit } = useGetAllUnit({ show: unit_id });
|
|
||||||
const { data: lesson } = useGetAllLesson({ show: lesson_id });
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const { unit_id,curriculum_id,grade_id ,subject_id,lesson_id} = useParams<ParamsEnum>();
|
||||||
|
const { data: unit } = useGetAllUnit({ show: unit_id });
|
||||||
|
|
||||||
|
|
||||||
|
const { data: Subject } = useGetAllSubject({
|
||||||
|
show: subject_id,
|
||||||
|
});
|
||||||
|
const { data: grade } = useGetAllGrade({
|
||||||
|
show: grade_id,
|
||||||
|
});
|
||||||
|
const { data: Curriculum } = useGetAllCurriculum({
|
||||||
|
show: curriculum_id,
|
||||||
|
});
|
||||||
|
const { data: Lesson } = useGetAllLesson({
|
||||||
|
show: lesson_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const gradeName = grade?.data?.name ?? "";
|
||||||
|
const SubjectName = Subject?.data?.name ?? "";
|
||||||
|
const CurriculumName = Curriculum?.data?.name ?? "";
|
||||||
const unitName = unit?.data?.name ?? "";
|
const unitName = unit?.data?.name ?? "";
|
||||||
const SubjectName = unit?.data?.subject?.name ?? "";
|
const LessonName = Lesson?.data?.name ?? "";
|
||||||
const lessonName = lesson?.data?.name ?? "";
|
|
||||||
|
|
||||||
useSetPageTitle(
|
|
||||||
t(`page_header.subject`) +
|
|
||||||
"/" +
|
|
||||||
`${SubjectName}` +
|
|
||||||
"/" +
|
|
||||||
t(`PageTitle.unit`) +
|
|
||||||
"/" +
|
|
||||||
`${unitName}` +
|
|
||||||
"/" +
|
|
||||||
t(`PageTitle.lesson`) +
|
|
||||||
"/" +
|
|
||||||
`${lessonName}` +
|
|
||||||
"/" +
|
|
||||||
t(`PageTitle.questions`),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
useSetPageTitle( t(`page_header.grade`)+ "/"+ gradeName +"/"+t(`PageTitle.subject`)+"/"+SubjectName+"/"+t("PageTitle.curriculum")+"/"+CurriculumName+"/"+t("PageTitle.unit")+"/"+unitName+"/"+t("PageTitle.lesson")+"/"+LessonName+"/"+t("PageTitle.question")+"/"+t("practical.add"));
|
||||||
const handleSubmit = (
|
const handleSubmit = (
|
||||||
values: any,
|
values: any,
|
||||||
{ resetForm }: { resetForm: () => void },
|
{ resetForm }: { resetForm: () => void },
|
||||||
) => {
|
) => {
|
||||||
const DataToSend = structuredClone(values);
|
const DataToSend = structuredClone(values);
|
||||||
setTagsSearch(null);
|
|
||||||
console.log(isBseQuestion);
|
|
||||||
|
|
||||||
|
setTagsSearch(null);
|
||||||
|
const canAnswersBeShuffled = DataToSend?.canAnswersBeShuffled ? 1 : 0 ;
|
||||||
if (isBseQuestion || DataToSend?.isBase === 1) {
|
if (isBseQuestion || DataToSend?.isBase === 1) {
|
||||||
const newBseQuestion = {
|
const newBseQuestion = {
|
||||||
subject_id: subject_id,
|
subject_id: subject_id,
|
||||||
|
|
@ -85,6 +89,9 @@ const AddPage: React.FC = () => {
|
||||||
image: DataToSend?.image ?? "",
|
image: DataToSend?.image ?? "",
|
||||||
isBase: 1,
|
isBase: 1,
|
||||||
lessons_ids: [lesson_id],
|
lessons_ids: [lesson_id],
|
||||||
|
canAnswersBeShuffled,
|
||||||
|
hint:DataToSend?.hint
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mutateAsync(newBseQuestion).then((data: any) => {
|
mutateAsync(newBseQuestion).then((data: any) => {
|
||||||
|
|
@ -113,6 +120,7 @@ const AddPage: React.FC = () => {
|
||||||
subject_id: subject_id,
|
subject_id: subject_id,
|
||||||
tags,
|
tags,
|
||||||
lessons_ids: [lesson_id],
|
lessons_ids: [lesson_id],
|
||||||
|
canAnswersBeShuffled
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -162,7 +170,7 @@ const AddPage: React.FC = () => {
|
||||||
>
|
>
|
||||||
<main className="w-100 exercise_add_main">
|
<main className="w-100 exercise_add_main">
|
||||||
<Header/>
|
<Header/>
|
||||||
<ModelForm/>
|
<BaseForm/>
|
||||||
|
|
||||||
<div className="exercise_add_buttons">
|
<div className="exercise_add_buttons">
|
||||||
<div onClick={handleCancel}>{t("practical.back")}</div>
|
<div onClick={handleCancel}>{t("practical.back")}</div>
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,12 @@ import { toast } from "react-toastify";
|
||||||
import useSetPageTitle from "../../Hooks/useSetPageTitle";
|
import useSetPageTitle from "../../Hooks/useSetPageTitle";
|
||||||
import { useGetAllUnit } from "../../api/unit";
|
import { useGetAllUnit } from "../../api/unit";
|
||||||
import { useGetAllLesson } from "../../api/lesson";
|
import { useGetAllLesson } from "../../api/lesson";
|
||||||
|
import { useGetAllSubject } from "../../api/subject";
|
||||||
|
import { useGetAllGrade } from "../../api/grade";
|
||||||
|
import { useGetAllCurriculum } from "../../api/curriculum";
|
||||||
|
|
||||||
const EditPage: React.FC = () => {
|
const EditPage: React.FC = () => {
|
||||||
const { question_id, subject_id, unit_id } = useParams<ParamsEnum>();
|
const { unit_id,curriculum_id,grade_id ,subject_id,lesson_id,question_id } = useParams<ParamsEnum>();
|
||||||
const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions } =
|
const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions } =
|
||||||
useObjectToEdit();
|
useObjectToEdit();
|
||||||
|
|
||||||
|
|
@ -50,36 +53,38 @@ const EditPage: React.FC = () => {
|
||||||
|
|
||||||
const objectToEdit = { ...data?.data, Questions: Questions?.data };
|
const objectToEdit = { ...data?.data, Questions: Questions?.data };
|
||||||
|
|
||||||
const { lesson_id } = useParams();
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (objectToEdit?.isBase && isBseQuestion !== true) {
|
if (objectToEdit?.isBase && isBseQuestion !== true) {
|
||||||
setIsBseQuestion(true);
|
setIsBseQuestion(true);
|
||||||
}
|
}
|
||||||
}, [objectToEdit?.isBase]);
|
}, [objectToEdit?.isBase]);
|
||||||
|
|
||||||
const { data: unit } = useGetAllUnit({ show: unit_id });
|
|
||||||
const { data: lesson } = useGetAllLesson({ show: lesson_id });
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const unitName = unit?.data?.name ?? "";
|
const { data: unit } = useGetAllUnit({ show: unit_id });
|
||||||
const SubjectName = unit?.data?.subject?.name ?? "";
|
|
||||||
const lessonName = lesson?.data?.name ?? "";
|
|
||||||
|
|
||||||
useSetPageTitle(
|
|
||||||
t(`page_header.subject`) +
|
const { data: Subject } = useGetAllSubject({
|
||||||
"/" +
|
show: subject_id,
|
||||||
`${SubjectName}` +
|
});
|
||||||
"/" +
|
const { data: grade } = useGetAllGrade({
|
||||||
t(`PageTitle.unit`) +
|
show: grade_id,
|
||||||
"/" +
|
});
|
||||||
`${unitName}` +
|
const { data: Curriculum } = useGetAllCurriculum({
|
||||||
"/" +
|
show: curriculum_id,
|
||||||
t(`PageTitle.lesson`) +
|
});
|
||||||
"/" +
|
const { data: Lesson } = useGetAllLesson({
|
||||||
`${lessonName}` +
|
show: lesson_id,
|
||||||
"/" +
|
});
|
||||||
t(`PageTitle.questions`),
|
|
||||||
);
|
const gradeName = grade?.data?.name ?? "";
|
||||||
|
const SubjectName = Subject?.data?.name ?? "";
|
||||||
|
const CurriculumName = Curriculum?.data?.name ?? "";
|
||||||
|
const unitName = unit?.data?.name ?? "";
|
||||||
|
const LessonName = Lesson?.data?.name ?? "";
|
||||||
|
|
||||||
|
useSetPageTitle( t(`page_header.grade`)+ "/"+ gradeName +"/"+t(`PageTitle.subject`)+"/"+SubjectName+"/"+t("PageTitle.curriculum")+"/"+CurriculumName+"/"+t("PageTitle.unit")+"/"+unitName+"/"+t("PageTitle.lesson")+"/"+LessonName+"/"+t("PageTitle.question")+"/"+t("practical.edit"));
|
||||||
|
|
||||||
const handleSubmit = (values: any) => {
|
const handleSubmit = (values: any) => {
|
||||||
const DataToSend = structuredClone(values);
|
const DataToSend = structuredClone(values);
|
||||||
|
|
@ -91,6 +96,8 @@ const EditPage: React.FC = () => {
|
||||||
id: DataToSend?.id,
|
id: DataToSend?.id,
|
||||||
content: DataToSend?.content,
|
content: DataToSend?.content,
|
||||||
image: DataToSend?.image ?? "",
|
image: DataToSend?.image ?? "",
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
if (
|
if (
|
||||||
typeof UpdateBseQuestion?.image === "string" &&
|
typeof UpdateBseQuestion?.image === "string" &&
|
||||||
|
|
@ -150,6 +157,8 @@ const EditPage: React.FC = () => {
|
||||||
tags,
|
tags,
|
||||||
lessons_ids: [lesson_id],
|
lessons_ids: [lesson_id],
|
||||||
parent_id: values?.id,
|
parent_id: values?.id,
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -169,9 +178,6 @@ const EditPage: React.FC = () => {
|
||||||
|
|
||||||
updatedObject?.QuestionOptions?.forEach((item: any) => {
|
updatedObject?.QuestionOptions?.forEach((item: any) => {
|
||||||
if (item?.id) {
|
if (item?.id) {
|
||||||
// if(!item?.answer_image){
|
|
||||||
// item["answer_image"] = ""
|
|
||||||
// }
|
|
||||||
console.log(item);
|
console.log(item);
|
||||||
|
|
||||||
oldQuestionOptions.push(item);
|
oldQuestionOptions.push(item);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import TextField from "./TextField";
|
||||||
import File from "./File";
|
import File from "./File";
|
||||||
import { FaCirclePlus, FaDeleteLeft } from "react-icons/fa6";
|
import { FaCirclePlus, FaDeleteLeft } from "react-icons/fa6";
|
||||||
import { FaTrash } from "react-icons/fa";
|
import { FaTrash } from "react-icons/fa";
|
||||||
|
import HintField from "./HintField";
|
||||||
|
|
||||||
const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
|
|
@ -25,9 +26,9 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
|
|
||||||
formik.setFieldValue("QuestionOptions", updatedQuestionOptions);
|
formik.setFieldValue("QuestionOptions", updatedQuestionOptions);
|
||||||
};
|
};
|
||||||
console.log(formik.values);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div className="ChoiceFields">
|
<div className="ChoiceFields">
|
||||||
<TextField
|
<TextField
|
||||||
className="textarea_exercise"
|
className="textarea_exercise"
|
||||||
|
|
@ -50,10 +51,21 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
name={index}
|
name={index}
|
||||||
type="Checkbox"
|
type="Checkbox"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<p className="delete_question_options">
|
<p className="delete_question_options">
|
||||||
<FaTrash onClick={handleDeleteChoice} size={17} />
|
<FaTrash onClick={handleDeleteChoice} size={17} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<HintField
|
||||||
|
placeholder={"hint"}
|
||||||
|
name={index}
|
||||||
|
label="hint"
|
||||||
|
id={`hint`}
|
||||||
|
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
70
src/Pages/question/Model/Field/Choices.tsx
Normal file
70
src/Pages/question/Model/Field/Choices.tsx
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Choice } from '../../../../types/Item';
|
||||||
|
import ChoiceFields from './ChoiceFields';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
|
const Choices = () => {
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
|
|
||||||
|
const handleDragEnd = (result: any) => {
|
||||||
|
// Check if the item was dropped outside the list
|
||||||
|
if (!result.destination) return;
|
||||||
|
|
||||||
|
// Create a new array from the current QuestionOptions
|
||||||
|
const items = Array.from(formik?.values?.QuestionOptions);
|
||||||
|
|
||||||
|
// Remove the item from the original position
|
||||||
|
const [reorderedItem] = items.splice(result.source.index, 1);
|
||||||
|
|
||||||
|
// Insert the item at the new position
|
||||||
|
items.splice(result.destination.index, 0, reorderedItem);
|
||||||
|
|
||||||
|
// Update the order keys based on the new indices
|
||||||
|
const updatedItems = items.map((item, index) => ({
|
||||||
|
...item ?? {},
|
||||||
|
order: index + 1, // Update order to be 1-based index
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Update the formik state with the new order
|
||||||
|
console.log(updatedItems,"updatedItems");
|
||||||
|
|
||||||
|
formik.setFieldValue('QuestionOptions', updatedItems);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DragDropContext onDragEnd={handleDragEnd}>
|
||||||
|
<Droppable droppableId="choices">
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
{...provided.droppableProps}
|
||||||
|
ref={provided.innerRef}
|
||||||
|
|
||||||
|
>
|
||||||
|
{formik?.values?.QuestionOptions?.map((item: Choice, index: number) => {
|
||||||
|
// Use a unique identifier for draggableId
|
||||||
|
const draggableId = item.name ? item.name.toString() : `item-${index}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Draggable key={draggableId} draggableId={draggableId} index={index}>
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
>
|
||||||
|
<ChoiceFields index={index} data={item} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{provided.placeholder} {/* Placeholder for spacing */}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</DragDropContext>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Choices;
|
||||||
|
|
@ -17,7 +17,6 @@ const File = ({
|
||||||
const { formik, t, isError, errorMsg } = useFormField(newName, props);
|
const { formik, t, isError, errorMsg } = useFormField(newName, props);
|
||||||
let imageUrl = formik?.values?.QuestionOptions[name]?.answer_image ?? null;
|
let imageUrl = formik?.values?.QuestionOptions[name]?.answer_image ?? null;
|
||||||
// console.log(imageUrl);
|
// console.log(imageUrl);
|
||||||
console.log(imageUrl);
|
|
||||||
|
|
||||||
const fileList: UploadFile[] = useMemo(() => {
|
const fileList: UploadFile[] = useMemo(() => {
|
||||||
if (!imageUrl) return [];
|
if (!imageUrl) return [];
|
||||||
|
|
|
||||||
69
src/Pages/question/Model/Field/HintField.tsx
Normal file
69
src/Pages/question/Model/Field/HintField.tsx
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { Form, Input } from "antd";
|
||||||
|
import React from "react";
|
||||||
|
import useFormField from "../../../../Hooks/useFormField";
|
||||||
|
import { MdOutlineEdit } from "react-icons/md";
|
||||||
|
import { Field } from "formik";
|
||||||
|
const { TextArea } = Input;
|
||||||
|
|
||||||
|
const HintField = ({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
label2,
|
||||||
|
placeholder,
|
||||||
|
isDisabled,
|
||||||
|
onChange,
|
||||||
|
props,
|
||||||
|
no_label,
|
||||||
|
label_icon,
|
||||||
|
id,
|
||||||
|
className,
|
||||||
|
}: any) => {
|
||||||
|
const newName = `QuestionOptions[${name}].hint`;
|
||||||
|
const { formik, isError, errorMsg, t } = useFormField(newName, props);
|
||||||
|
const TextFilehandleChange = (
|
||||||
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||||
|
) => {
|
||||||
|
// console.log('Change:', e.target.value);
|
||||||
|
formik.setFieldValue(newName, e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`ValidationField w-100 ${className ?? ""} `}>
|
||||||
|
{no_label ? (
|
||||||
|
<label htmlFor={name} className="text">
|
||||||
|
<span>empty</span>
|
||||||
|
</label>
|
||||||
|
) : label_icon ? (
|
||||||
|
<div className="LabelWithIcon">
|
||||||
|
<label htmlFor={name} className="text">
|
||||||
|
{label2 ? label2 : t(`input.${label ? label : name}`)}
|
||||||
|
</label>
|
||||||
|
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<label htmlFor={name} className="text">
|
||||||
|
{label2 ? label2 : t(`input.${label ? label : name}`)}
|
||||||
|
</label>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
hasFeedback
|
||||||
|
validateStatus={isError ? "error" : ""}
|
||||||
|
help={isError ? errorMsg : ""}
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
as={Input}
|
||||||
|
placeholder={t(`input.${placeholder ? placeholder : name}`)}
|
||||||
|
name={newName}
|
||||||
|
disabled={isDisabled}
|
||||||
|
size="large"
|
||||||
|
onChange={onChange || TextFilehandleChange}
|
||||||
|
style={{width:200}}
|
||||||
|
id={id}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(HintField);
|
||||||
|
|
@ -10,17 +10,14 @@ import { useTranslation } from "react-i18next";
|
||||||
import DynamicTags from "./Tags/DynamicTags";
|
import DynamicTags from "./Tags/DynamicTags";
|
||||||
import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
|
import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
|
||||||
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
|
||||||
|
import Choices from "./ChoiceField/Choices";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const { isOpen } = useModalState((state) => state);
|
|
||||||
// const {data} = useGetAllQuestion();
|
|
||||||
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
|
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Success) {
|
if (Success) {
|
||||||
console.log(1);
|
|
||||||
|
|
||||||
formik.setErrors({});
|
formik.setErrors({});
|
||||||
formik.resetForm({ values: {} });
|
formik.resetForm({ values: {} });
|
||||||
setSuccess(false);
|
setSuccess(false);
|
||||||
|
|
@ -32,7 +29,6 @@ const Form = () => {
|
||||||
}, [formik?.values]);
|
}, [formik?.values]);
|
||||||
|
|
||||||
// console.log(formik?.errors);
|
// console.log(formik?.errors);
|
||||||
console.log(formik?.values?.Questions, "formik?.values?.Questions");
|
|
||||||
|
|
||||||
const handleAddChoice = (parent_index: number) => {
|
const handleAddChoice = (parent_index: number) => {
|
||||||
console.log(parent_index);
|
console.log(parent_index);
|
||||||
|
|
@ -70,7 +66,6 @@ const Form = () => {
|
||||||
formik.setFieldValue("max_mark", max_mark);
|
formik.setFieldValue("max_mark", max_mark);
|
||||||
};
|
};
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
console.log(formik.errors);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="w-100">
|
<Row className="w-100">
|
||||||
|
|
@ -109,19 +104,7 @@ const Form = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(
|
<Choices parent_index={parent_index} />
|
||||||
(formik?.values as any)?.Questions?.[parent_index]
|
|
||||||
?.QuestionOptions || []
|
|
||||||
).map((item: Choice, index: number) => {
|
|
||||||
return (
|
|
||||||
<ChoiceFields
|
|
||||||
key={index}
|
|
||||||
parent_index={parent_index}
|
|
||||||
index={index}
|
|
||||||
data={item}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{formik?.values?.Questions?.[parent_index]?.QuestionOptions
|
{formik?.values?.Questions?.[parent_index]?.QuestionOptions
|
||||||
?.length < 5 && (
|
?.length < 5 && (
|
||||||
|
|
|
||||||
87
src/Pages/question/Model/Malty/ChoiceField/Choices.tsx
Normal file
87
src/Pages/question/Model/Malty/ChoiceField/Choices.tsx
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ChoiceFields from './ChoiceFields';
|
||||||
|
import { Choice } from '../../../../../types/Item';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
|
const Choices = ({parent_index}:{parent_index:number}) => {
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
|
|
||||||
|
|
||||||
|
const handleDragEnd = (result: any) => {
|
||||||
|
// Check if the item was dropped outside the list
|
||||||
|
if (!result.destination) return;
|
||||||
|
|
||||||
|
// Create a new array from the current QuestionOptions
|
||||||
|
const items = Array.from(formik?.values?.QuestionOptions);
|
||||||
|
|
||||||
|
// Remove the item from the original position
|
||||||
|
const [reorderedItem] = items.splice(result.source.index, 1);
|
||||||
|
|
||||||
|
// Insert the item at the new position
|
||||||
|
items.splice(result.destination.index, 0, reorderedItem);
|
||||||
|
|
||||||
|
// Update the order keys based on the new indices
|
||||||
|
const updatedItems = items.map((item, index) => ({
|
||||||
|
...item ?? {},
|
||||||
|
order: index + 1, // Update order to be 1-based index
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Update the formik state with the new order
|
||||||
|
console.log(updatedItems,"updatedItems");
|
||||||
|
|
||||||
|
formik.setFieldValue('QuestionOptions', updatedItems);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DragDropContext onDragEnd={handleDragEnd}>
|
||||||
|
<Droppable droppableId="choices">
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
{...provided.droppableProps}
|
||||||
|
ref={provided.innerRef}
|
||||||
|
|
||||||
|
>
|
||||||
|
{(
|
||||||
|
(formik?.values as any)?.Questions?.[parent_index]
|
||||||
|
?.QuestionOptions || []
|
||||||
|
).map((item: Choice, index: number) => {
|
||||||
|
const draggableId = item.name ? item.name.toString() : `item-${index}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Draggable key={draggableId} draggableId={draggableId} index={index}>
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
>
|
||||||
|
|
||||||
|
<ChoiceFields
|
||||||
|
key={index}
|
||||||
|
parent_index={parent_index}
|
||||||
|
index={index}
|
||||||
|
data={item}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</DragDropContext>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Choices
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Checkbox, Form } from "antd";
|
||||||
|
import { useFormik, useFormikContext } from "formik";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
const CheckboxField = ({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
isDisabled,
|
||||||
|
onChange,
|
||||||
|
Group,
|
||||||
|
className,
|
||||||
|
props,
|
||||||
|
}: any) => {
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const newName = `Questions[${name}].canAnswersBeShuffled`;
|
||||||
|
console.log(formik.values?.Questions?.[name]);
|
||||||
|
|
||||||
|
const CheckboxhandleChange = (value: any, index: number) => {
|
||||||
|
formik.setFieldValue(newName, value?.target?.checked ? 1 : 0);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className={Group ? "d-inline mt-5 Checkbox" : ``}>
|
||||||
|
<Checkbox
|
||||||
|
onChange={onChange || CheckboxhandleChange}
|
||||||
|
disabled={isDisabled}
|
||||||
|
checked={formik.values?.Questions?.[name]?.canAnswersBeShuffled === 1}
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
{t(`input.${label ? label : name}`)}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CheckboxField;
|
||||||
|
|
@ -9,6 +9,7 @@ import File from "./File";
|
||||||
import { FaTrash } from "react-icons/fa";
|
import { FaTrash } from "react-icons/fa";
|
||||||
import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
|
import CheckboxField from "./CheckboxField";
|
||||||
|
|
||||||
const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
|
|
@ -46,6 +47,13 @@ const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
name={index}
|
name={index}
|
||||||
type="File"
|
type="File"
|
||||||
/>
|
/>
|
||||||
|
<CheckboxField
|
||||||
|
className="canAnswersBeShuffled"
|
||||||
|
label={"canAnswersBeShuffled"}
|
||||||
|
name={index}
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
<p className="delete_question_options">
|
<p className="delete_question_options">
|
||||||
<FaTrash onClick={handleDeleteQuestion} size={17} />
|
<FaTrash onClick={handleDeleteQuestion} size={17} />
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { useTranslation } from "react-i18next";
|
||||||
import DynamicTags from "./Tags/DynamicTags";
|
import DynamicTags from "./Tags/DynamicTags";
|
||||||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import Choices from "./Field/Choices";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const [t] = useTranslation()
|
const [t] = useTranslation()
|
||||||
|
|
@ -42,11 +43,12 @@ const Form = () => {
|
||||||
<div className="exercise_form">
|
<div className="exercise_form">
|
||||||
<ValidationField className="textarea_exercise" name="content" label="details" type="TextArea" />
|
<ValidationField className="textarea_exercise" name="content" label="details" type="TextArea" />
|
||||||
<ValidationField className="file_exercise" name="image" label="attachment" type="File" />
|
<ValidationField className="file_exercise" name="image" label="attachment" type="File" />
|
||||||
|
<ValidationField name="canAnswersBeShuffled" label="canAnswersBeShuffled" type="Checkbox" />
|
||||||
</div>
|
</div>
|
||||||
{
|
<div>
|
||||||
(((formik?.values as any)?.QuestionOptions as Choice[])||[]) .map((item:Choice,index:number)=>{
|
<ValidationField className="hint" name="hint" label="hint" type="text" style={{width:200}} />
|
||||||
return <ChoiceFields key={index} index={index} data={item}/>
|
</div>
|
||||||
})}
|
<Choices />
|
||||||
{formik?.values?.QuestionOptions?.length < 5 && (
|
{formik?.values?.QuestionOptions?.length < 5 && (
|
||||||
<p className="add_new_button" >
|
<p className="add_new_button" >
|
||||||
<FaCirclePlus onClick={handleAddChoice} size={23} /> {t("header.add_new_choice")}
|
<FaCirclePlus onClick={handleAddChoice} size={23} /> {t("header.add_new_choice")}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ export const getInitialValues = (objectToEdit: Question): any => {
|
||||||
content: objectToEdit?.content ?? "",
|
content: objectToEdit?.content ?? "",
|
||||||
image: objectToEdit?.image ?? "",
|
image: objectToEdit?.image ?? "",
|
||||||
subject_id: objectToEdit?.subject_id ?? "",
|
subject_id: objectToEdit?.subject_id ?? "",
|
||||||
|
canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ?? 0,
|
||||||
isBase: 0,
|
isBase: 0,
|
||||||
parent_id: objectToEdit?.parent_id ?? "",
|
parent_id: objectToEdit?.parent_id ?? "",
|
||||||
QuestionOptions: objectToEdit?.QuestionOptions ?? [],
|
QuestionOptions: objectToEdit?.QuestionOptions ?? [],
|
||||||
|
|
@ -38,10 +39,6 @@ export const getValidationSchema = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getInitialValuesBase = (objectToEdit: Question): any => {
|
export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
const tags = objectToEdit?.tags?.map((item: any, index: number) => {
|
|
||||||
return { ...item, key: index };
|
|
||||||
});
|
|
||||||
console.log(objectToEdit);
|
|
||||||
|
|
||||||
const newQuestions = objectToEdit?.Questions?.map((item: any) => {
|
const newQuestions = objectToEdit?.Questions?.map((item: any) => {
|
||||||
const tags = item?.tags?.map((tag: any) => ({
|
const tags = item?.tags?.map((tag: any) => ({
|
||||||
|
|
@ -52,6 +49,7 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
|
canAnswersBeShuffled: item?.canAnswersBeShuffled ?? 0,
|
||||||
tags,
|
tags,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
@ -65,10 +63,13 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
subject_id: objectToEdit?.subject_id ?? "",
|
subject_id: objectToEdit?.subject_id ?? "",
|
||||||
isBase: 1,
|
isBase: 1,
|
||||||
parent_id: objectToEdit?.parent_id ?? "",
|
parent_id: objectToEdit?.parent_id ?? "",
|
||||||
|
canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ?? 0,
|
||||||
|
|
||||||
Questions: questions,
|
Questions: questions,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const getValidationSchemaBase = () => {
|
export const getValidationSchemaBase = () => {
|
||||||
// validate input
|
// validate input
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ import { useGetAllLesson } from "../../api/lesson";
|
||||||
import { useDeleteQuestion } from "../../api/Question";
|
import { useDeleteQuestion } from "../../api/Question";
|
||||||
import DeleteModels from "../../Layout/Dashboard/DeleteModels";
|
import DeleteModels from "../../Layout/Dashboard/DeleteModels";
|
||||||
import { ModalEnum } from "../../enums/Model";
|
import { ModalEnum } from "../../enums/Model";
|
||||||
|
import { useGetAllSubject } from "../../api/subject";
|
||||||
|
import { useGetAllGrade } from "../../api/grade";
|
||||||
|
import { useGetAllCurriculum } from "../../api/curriculum";
|
||||||
const Table = lazy(() => import("./Table"));
|
const Table = lazy(() => import("./Table"));
|
||||||
|
|
||||||
const TableHeader = () => {
|
const TableHeader = () => {
|
||||||
|
|
@ -16,35 +19,37 @@ const TableHeader = () => {
|
||||||
|
|
||||||
const deleteMutation = useDeleteQuestion();
|
const deleteMutation = useDeleteQuestion();
|
||||||
|
|
||||||
const { unit_id,lesson_id } = useParams<ParamsEnum>();
|
const { unit_id,curriculum_id,grade_id ,subject_id,lesson_id} = useParams<ParamsEnum>();
|
||||||
const { data: unit } = useGetAllUnit({ show: unit_id });
|
const { data: unit } = useGetAllUnit({ show: unit_id });
|
||||||
const { data: lesson } = useGetAllLesson({ show: lesson_id });
|
|
||||||
const unitName = unit?.data?.name ?? "";
|
|
||||||
const SubjectName = unit?.data?.subject?.name ?? "";
|
|
||||||
const lessonName = lesson?.data?.name ?? "";
|
|
||||||
|
|
||||||
useSetPageTitle(
|
|
||||||
t(`page_header.subject`) +
|
const { data: Subject } = useGetAllSubject({
|
||||||
"/" +
|
show: subject_id,
|
||||||
`${SubjectName}` +
|
});
|
||||||
"/" +
|
const { data: grade } = useGetAllGrade({
|
||||||
t(`PageTitle.unit`) +
|
show: grade_id,
|
||||||
"/" +
|
});
|
||||||
`${unitName}` +
|
const { data: Curriculum } = useGetAllCurriculum({
|
||||||
"/" +
|
show: curriculum_id,
|
||||||
t(`PageTitle.lesson`) +
|
});
|
||||||
"/" +
|
const { data: Lesson } = useGetAllLesson({
|
||||||
`${lessonName}` +
|
show: lesson_id,
|
||||||
"/" +
|
});
|
||||||
t(`PageTitle.questions`),
|
|
||||||
);
|
const gradeName = grade?.data?.name ?? "";
|
||||||
|
const SubjectName = Subject?.data?.name ?? "";
|
||||||
|
const CurriculumName = Curriculum?.data?.name ?? "";
|
||||||
|
const unitName = unit?.data?.name ?? "";
|
||||||
|
const LessonName = Lesson?.data?.name ?? "";
|
||||||
|
|
||||||
|
useSetPageTitle( t(`page_header.grade`)+ "/"+ gradeName +"/"+t(`PageTitle.subject`)+"/"+SubjectName+"/"+t("PageTitle.curriculum")+"/"+CurriculumName+"/"+t("PageTitle.unit")+"/"+unitName+"/"+t("PageTitle.lesson")+"/"+LessonName+"/"+t("PageTitle.question"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
<Suspense fallback={<Spin />}>
|
<Suspense fallback={<Spin />}>
|
||||||
<header>
|
<header>
|
||||||
<h6>
|
<h6>
|
||||||
{t("models.Question")} {SubjectName} {unitName} {lessonName}
|
{t("models.Question")}
|
||||||
</h6>
|
</h6>
|
||||||
</header>
|
</header>
|
||||||
<Table />
|
<Table />
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@ import useSetPageTitle from "../../../Hooks/useSetPageTitle";
|
||||||
import { canAddSubject } from "../../../utils/hasAbilityFn";
|
import { canAddSubject } from "../../../utils/hasAbilityFn";
|
||||||
import { useDeleteSubject } from "../../../api/subject";
|
import { useDeleteSubject } from "../../../api/subject";
|
||||||
import { lazy } from "react";
|
import { lazy } from "react";
|
||||||
|
import { useGetAllCurriculum } from "../../../api/curriculum";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { ParamsEnum } from "../../../enums/params";
|
||||||
|
import { useGetAllGrade } from "../../../api/grade";
|
||||||
const Table = lazy(() => import("./TablePage"));
|
const Table = lazy(() => import("./TablePage"));
|
||||||
const AddModalForm = lazy(() => import("../Model/AddModel"));
|
const AddModalForm = lazy(() => import("../Model/AddModel"));
|
||||||
const EditModalForm = lazy(() => import("../Model/EditModel"));
|
const EditModalForm = lazy(() => import("../Model/EditModel"));
|
||||||
|
|
@ -16,7 +20,15 @@ const TableWithHeader = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const deleteMutation = useDeleteSubject();
|
const deleteMutation = useDeleteSubject();
|
||||||
|
|
||||||
useSetPageTitle(t(`page_header.subject`));
|
const { grade_id} = useParams<ParamsEnum>();
|
||||||
|
|
||||||
|
const { data: grade } = useGetAllGrade({
|
||||||
|
show: grade_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const gradeName = grade?.data?.name ?? "";
|
||||||
|
useSetPageTitle( t(`page_header.grade`)+ "/"+ `${gradeName}` +"/"+t(`PageTitle.subject`));
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,8 @@
|
||||||
@import "./Model.scss";
|
@import "./Model.scss";
|
||||||
@import "./Segmented.scss";
|
@import "./Segmented.scss";
|
||||||
@import "./Mix.scss";
|
@import "./Mix.scss";
|
||||||
|
|
||||||
|
|
||||||
|
.draggable-row {
|
||||||
|
cursor: move; /* Change cursor to indicate draggable rows */
|
||||||
|
}
|
||||||
|
|
@ -120,3 +120,10 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 100px;
|
left: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.hint_canAnswersBeShuffled{
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// export const BaseURL = "http://192.168.1.6:8000/api/";
|
export const BaseURL = "http://192.168.1.111:8000/api/";
|
||||||
// export const BaseURL = "http://127.0.0.1:8000/api/";
|
// export const BaseURL = "http://127.0.0.1:8000/api/";
|
||||||
|
|
||||||
export const BaseURL = "http://192.168.1.111:8000/api/";
|
// export const BaseURL = "http://192.168.1.120:8000/api/";
|
||||||
|
|
||||||
// export const ImageBaseURL = "http://192.168.1.9:8000/";
|
// export const ImageBaseURL = "http://192.168.1.9:8000/";
|
||||||
|
|
||||||
|
|
|
||||||
5
src/enums/Term.ts
Normal file
5
src/enums/Term.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
export enum TermEnum {
|
||||||
|
FIRST_TERM = "first_term",
|
||||||
|
SECOND_TERM = "second_term",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@ function QueryProvider({ children }: any) {
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
cacheTime:0
|
// staleTime:Infinity
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,9 @@
|
||||||
"add_Question": "إضافة اسئلة",
|
"add_Question": "إضافة اسئلة",
|
||||||
"malty_exercise": "تمرين متعدد",
|
"malty_exercise": "تمرين متعدد",
|
||||||
"add_new_question": "اضافة سؤال جديد",
|
"add_new_question": "اضافة سؤال جديد",
|
||||||
"exercise": "تمارين"
|
"exercise": "تمارين",
|
||||||
|
"icon" :"الايقونة"
|
||||||
|
|
||||||
},
|
},
|
||||||
"columns": {
|
"columns": {
|
||||||
"id": "الرقم التعريفي",
|
"id": "الرقم التعريفي",
|
||||||
|
|
@ -119,6 +121,7 @@
|
||||||
"payment_type": "نوع الدفع",
|
"payment_type": "نوع الدفع",
|
||||||
"value": "القيمة",
|
"value": "القيمة",
|
||||||
"subject_name": "اسم المادة",
|
"subject_name": "اسم المادة",
|
||||||
|
"icon" :"الايقونة",
|
||||||
"image": "الصورة",
|
"image": "الصورة",
|
||||||
"card": "البطاقة",
|
"card": "البطاقة",
|
||||||
"birthday": "تاريخ الميلاد",
|
"birthday": "تاريخ الميلاد",
|
||||||
|
|
@ -317,6 +320,7 @@
|
||||||
"due_date": "تاريخ الاستحقاق",
|
"due_date": "تاريخ الاستحقاق",
|
||||||
"assigning_date": "تاريخ التعيين",
|
"assigning_date": "تاريخ التعيين",
|
||||||
"subject_name": "اسم المادة",
|
"subject_name": "اسم المادة",
|
||||||
|
"icon" :"الايقونة",
|
||||||
"exam_type": "نوع الامتحان",
|
"exam_type": "نوع الامتحان",
|
||||||
"grade_to_pass": "الدرجة اللازمة للنجاح",
|
"grade_to_pass": "الدرجة اللازمة للنجاح",
|
||||||
"max_grade": "الدرجة القصوى",
|
"max_grade": "الدرجة القصوى",
|
||||||
|
|
@ -354,7 +358,9 @@
|
||||||
"isBase": "سؤال رئيسي",
|
"isBase": "سؤال رئيسي",
|
||||||
"main_question": "النص الأساسي ",
|
"main_question": "النص الأساسي ",
|
||||||
"question": "السؤال",
|
"question": "السؤال",
|
||||||
"id": "الرقم التعريفي"
|
"id": "الرقم التعريفي",
|
||||||
|
"canAnswersBeShuffled":"يمكن خلط الإجابات",
|
||||||
|
"hint":"لحليح"
|
||||||
},
|
},
|
||||||
|
|
||||||
"select": {
|
"select": {
|
||||||
|
|
@ -679,7 +685,9 @@
|
||||||
"edit": "تعديل",
|
"edit": "تعديل",
|
||||||
"questions": "اسئلة",
|
"questions": "اسئلة",
|
||||||
"lesson": "الدرس",
|
"lesson": "الدرس",
|
||||||
"curriculum": "مقرر"
|
"curriculum": "مقرر",
|
||||||
|
"subject":"المادة",
|
||||||
|
"question":"السؤال"
|
||||||
},
|
},
|
||||||
"page_header": {
|
"page_header": {
|
||||||
"dashboard": "لوحة القيادة / الصفحة الرئيسية",
|
"dashboard": "لوحة القيادة / الصفحة الرئيسية",
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@ export interface Question {
|
||||||
parent_id: number;
|
parent_id: number;
|
||||||
isBase: number;
|
isBase: number;
|
||||||
content: string;
|
content: string;
|
||||||
|
canAnswersBeShuffled:number ;
|
||||||
max_mark: number;
|
max_mark: number;
|
||||||
min_mark_to_pass: number;
|
min_mark_to_pass: number;
|
||||||
image: string | null;
|
image: string | null;
|
||||||
|
|
|
||||||
21
src/types/Unit.ts
Normal file
21
src/types/Unit.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { TermEnum } from "../enums/Term";
|
||||||
|
import { Nullable } from "./App";
|
||||||
|
|
||||||
|
// Define the type for the object
|
||||||
|
export interface Unit {
|
||||||
|
curriculum_id: number;
|
||||||
|
id: number; // Represents the student ID
|
||||||
|
name: string; // Represents the student's name
|
||||||
|
order: number; // Represents the order (could be for sorting)
|
||||||
|
term: TermEnum; // Represents the term using the Term enum
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InitialValues {
|
||||||
|
curriculum_id: number;
|
||||||
|
id: number; // Represents the student ID
|
||||||
|
name: string; // Represents the student's name
|
||||||
|
order: number; // Represents the order (could be for sorting)
|
||||||
|
term: TermEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UnitInitialValues = Partial<Nullable<InitialValues>>;
|
||||||
6
src/utils/enumToArray.ts
Normal file
6
src/utils/enumToArray.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
export const enumToArray = (enumObj: any) => {
|
||||||
|
return Object.keys(enumObj).map(key => ({
|
||||||
|
value: enumObj[key],
|
||||||
|
label: enumObj[key],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
@ -3,6 +3,8 @@ import { create } from "zustand";
|
||||||
interface ModelState {
|
interface ModelState {
|
||||||
objectToEdit: any;
|
objectToEdit: any;
|
||||||
setObjectToEdit: (data: any) => void;
|
setObjectToEdit: (data: any) => void;
|
||||||
|
OldObjectToEdit: any;
|
||||||
|
setOldObjectToEdit: (data: any) => void;
|
||||||
paramToSend: any;
|
paramToSend: any;
|
||||||
setParamToSend: (data: any) => void;
|
setParamToSend: (data: any) => void;
|
||||||
TagsSearch: any;
|
TagsSearch: any;
|
||||||
|
|
@ -27,6 +29,8 @@ interface ModelState {
|
||||||
export const useObjectToEdit = create<ModelState>((set) => ({
|
export const useObjectToEdit = create<ModelState>((set) => ({
|
||||||
objectToEdit: null,
|
objectToEdit: null,
|
||||||
setObjectToEdit: (data) => set(() => ({ objectToEdit: data })),
|
setObjectToEdit: (data) => set(() => ({ objectToEdit: data })),
|
||||||
|
OldObjectToEdit: null,
|
||||||
|
setOldObjectToEdit: (data) => set(() => ({ OldObjectToEdit: data })),
|
||||||
paramToSend: {},
|
paramToSend: {},
|
||||||
setParamToSend: (data) => set(() => ({ paramToSend: data })),
|
setParamToSend: (data) => set(() => ({ paramToSend: data })),
|
||||||
TagsSearch: null,
|
TagsSearch: null,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user