diff --git a/src/Components/student/AddressCard.tsx b/src/Components/student/AddressCard.tsx new file mode 100644 index 0000000..558a9aa --- /dev/null +++ b/src/Components/student/AddressCard.tsx @@ -0,0 +1,24 @@ +import { Divider } from 'antd' +import { useTranslation } from 'react-i18next' +import { RxHome } from "react-icons/rx"; + +const StudentAddressCard = ({address}:{address:string}) => { + const {t} = useTranslation(); + return ( +
+
{t("practical.address")}
+ +
+ + +
{t("practical.address")}
+

{address}

+
+
+
+ ) +} + +export default StudentAddressCard + + diff --git a/src/Components/student/StudentInfoCard.tsx b/src/Components/student/StudentInfoCard.tsx new file mode 100644 index 0000000..238d48c --- /dev/null +++ b/src/Components/student/StudentInfoCard.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import { studentParamInfo } from './StudentParam' +import { Divider } from 'antd' + +const StudentInfoCard = ({data,name,status}:any) => { + return ( +
+
+ +
+ {status} +

{name}

+
+
+ +
+ {data?.map((student:any)=>( + +

{student?.key}

+

{student?.value}

+
+ ))} +
+
+ ) +} + +export default StudentInfoCard + + diff --git a/src/Components/student/StudentParam.ts b/src/Components/student/StudentParam.ts new file mode 100644 index 0000000..556fff7 --- /dev/null +++ b/src/Components/student/StudentParam.ts @@ -0,0 +1,8 @@ +export const studentParamInfo = [ + {key:"الحنس" , value:"male"}, + {key:"sex" , value:"male"}, + {key:"sex" , value:"male"}, + {key:"sex" , value:"male"}, + {key:"sex" , value:"male"}, + {key:"sex" , value:"male"} +] \ No newline at end of file diff --git a/src/Layout/Dashboard/PageHeader.tsx b/src/Layout/Dashboard/PageHeader.tsx index ce95f02..8f6d921 100644 --- a/src/Layout/Dashboard/PageHeader.tsx +++ b/src/Layout/Dashboard/PageHeader.tsx @@ -17,12 +17,14 @@ const PageHeader = ({ pageTitle, openModel = true, locationToNavigate, + addModal = true }: { - canAdd: any; - ModelAbility: any; + canAdd?: any; + ModelAbility?: any; pageTitle: string; openModel?: boolean; locationToNavigate?: string | any; + addModal?:boolean; }) => { const navigate = useNavigate(); const { handel_open_model } = useModalHandler(); @@ -49,7 +51,7 @@ const PageHeader = ({ {PageTitle} - {canAdd && ( + { addModal ? canAdd && (
- )} + ) :""} ); diff --git a/src/Pages/Admin/Student/show/Model/FilterForm.tsx b/src/Pages/Admin/Student/show/Model/FilterForm.tsx new file mode 100644 index 0000000..e1925e4 --- /dev/null +++ b/src/Pages/Admin/Student/show/Model/FilterForm.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import ValidationField from "../../../../../Components/ValidationField/ValidationField"; +import { Col, Row } from "reactstrap"; +import { userTypeOptions } from "../../../../../config/userTypeOptions"; + +const FilterForm = () => { + return ( +
+ + + + + + + + + +
+ ); +}; + +export default FilterForm; diff --git a/src/Pages/Admin/Student/show/Page.tsx b/src/Pages/Admin/Student/show/Page.tsx new file mode 100644 index 0000000..d5ad396 --- /dev/null +++ b/src/Pages/Admin/Student/show/Page.tsx @@ -0,0 +1,44 @@ +import { useTranslation } from "react-i18next"; +import { Suspense } from "react"; +import { Spin } from "antd"; +import useSetPageTitle from "../../../../Hooks/useSetPageTitle"; +import PageHeader from "../../../../Layout/Dashboard/PageHeader"; +import FilterLayout from "../../../../Layout/Dashboard/FilterLayout"; +import FilterForm from "./Model/FilterForm"; +import StudentInfoCard from "../../../../Components/student/StudentInfoCard"; +import StudentAddressCard from "../../../../Components/student/AddressCard"; +import { studentParamInfo } from "../../../../Components/student/StudentParam"; +import StudentTabs from "./StudentTabs"; + +const TableHeader = () => { + const [t] = useTranslation(); + useSetPageTitle( + t(`page_header.users`) + + "/ " + + t(`PageTitle.students`) + + + " / " + + t(`PageTitle.students_details`), + ); + return ( +
+ }> + +
+
+ + +
+
+ +
+ +
+
+
+ ); +}; + +export default TableHeader; diff --git a/src/Pages/Admin/Student/show/StudentTabs.tsx b/src/Pages/Admin/Student/show/StudentTabs.tsx new file mode 100644 index 0000000..3ff820c --- /dev/null +++ b/src/Pages/Admin/Student/show/StudentTabs.tsx @@ -0,0 +1,61 @@ +import { useTranslation } from 'react-i18next'; +import { Tabs } from 'antd'; +import type { TabsProps } from 'antd'; +import FilterLayout from '../../../../Layout/Dashboard/FilterLayout'; +import FilterForm from './Model/FilterForm'; +import { lazy } from 'react'; +import { BsQuestionSquare } from "react-icons/bs"; +import { IoStatsChartOutline } from "react-icons/io5"; +import { useGetAllUser } from '../../../../api/user'; +import useSearchQuery from '../../../../api/utils/useSearchQuery'; +import { useFilterState } from '../../../../Components/Utils/Filter/FilterState'; + +const Table = lazy(() => import("./Table")); + +const StudentTabs = () => { + const {t} = useTranslation(); + + const [searchQuery] = useSearchQuery("name"); + const { filterState } = useFilterState(); + const response = useGetAllUser({ + name: searchQuery, + pagination: true, + ...filterState, + }); + + const items: TabsProps['items'] = [ + { + key: '1', + label: {t("practical.quiz")} , + icon:, + children: + <> + } + filterTitle="sidebar.quiz" + /> + + , + }, + { + key: '2', + label: {t("practical.hightes_quiz")} , + icon:, + children: + <> + } + filterTitle="practical.hightes_quiz" + /> +
+ , + }, + ]; + return ( + <> + + +) +} + +export default StudentTabs \ No newline at end of file diff --git a/src/Pages/Admin/Student/show/Table.tsx b/src/Pages/Admin/Student/show/Table.tsx new file mode 100644 index 0000000..f416400 --- /dev/null +++ b/src/Pages/Admin/Student/show/Table.tsx @@ -0,0 +1,8 @@ +import DataTable from "../../../../Layout/Dashboard/Table/DataTable"; +import { useColumns } from "./useTableColumns"; +const App = ({response}:{response:any}) => { + + return ; +}; + +export default App; diff --git a/src/Pages/Admin/Student/show/index.tsx b/src/Pages/Admin/Student/show/index.tsx new file mode 100644 index 0000000..7f045ab --- /dev/null +++ b/src/Pages/Admin/Student/show/index.tsx @@ -0,0 +1,9 @@ +import { useColumns } from "./useTableColumns"; +import Table from "./Table"; +import { FaPlus } from "react-icons/fa"; + +export { + Table, + useColumns, + FaPlus, +}; diff --git a/src/Pages/Admin/Student/show/useTableColumns.tsx b/src/Pages/Admin/Student/show/useTableColumns.tsx new file mode 100644 index 0000000..3c6b583 --- /dev/null +++ b/src/Pages/Admin/Student/show/useTableColumns.tsx @@ -0,0 +1,48 @@ +import { TableColumnsType } from "antd"; +import { user } from "../../../../types/Item"; +import { useTranslation } from "react-i18next"; + +export const useColumns = () => { + const [t] = useTranslation(); + + const columns: TableColumnsType = [ + { + title: t("columns.quiz_date"), + dataIndex: "id", + key: "id", + align: "center", + }, + { + title: t("columns.subject"), + dataIndex: "username", + key: "username", + align: "center", + }, + { + title: t("columns.quiz_address"), + dataIndex: "phone_number", + key: "phone_number", + align: "center", + }, + { + title: t("columns.created_by"), + dataIndex: "type", + key: "type", + align: "center", + }, + { + title: t("columns.creator_name"), + dataIndex: "type", + key: "type", + align: "center", + }, + { + title: t("columns.quiz_status"), + dataIndex: "type", + key: "type", + align: "center", + }, + ]; + + return columns; +}; diff --git a/src/Pages/Admin/User/useTableColumns.tsx b/src/Pages/Admin/User/useTableColumns.tsx index 0ce516b..5140bb6 100644 --- a/src/Pages/Admin/User/useTableColumns.tsx +++ b/src/Pages/Admin/User/useTableColumns.tsx @@ -1,11 +1,12 @@ import { TableColumnsType } from "antd"; -import { user } from "../../../types/Item"; +import { single_user, user } from "../../../types/Item"; import { ModalEnum } from "../../../enums/Model"; import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; import { useModalState } from "../../../zustand/Modal"; import { useTranslation } from "react-i18next"; import { canDeleteUser, canEditUser } from "../../../utils/hasAbilityFn"; import ActionButtons from "../../../Components/Table/ActionButtons"; +import { useNavigate } from "react-router-dom"; export const useColumns = () => { const [t] = useTranslation(); @@ -13,6 +14,7 @@ export const useColumns = () => { const { setIsOpen } = useModalState((state) => state); const { setObjectToEdit } = useObjectToEdit((state) => state); + const handelDelete = (record: any) => { setObjectToEdit(record); setIsOpen(ModalEnum?.USER_DELETE); diff --git a/src/Routes.tsx b/src/Routes.tsx index 78b4384..77f3015 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -21,11 +21,14 @@ const EditQuestionPage = React.lazy( const Report = React.lazy(() => import("./Pages/Admin/Report/Page")); const Student = React.lazy(() => import("./Pages/Admin/Student/Page")); +const ShowStudent = React.lazy(() => import("./Pages/Admin/Student/show/Page")); + const ReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Page")); const AddReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Add/Page")); const EditReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Edit/Page")); const User = React.lazy(() => import("./Pages/Admin/User/Page")); + const Param = React.lazy(() => import("./Pages/Admin/Param/Page")); /// RESELLER /// @@ -137,60 +140,6 @@ export const menuItems: TMenuItem[] = [ type:UserTypeEnum.RE_SELLER }, - - - - // { - // header: "page_header.tags", - // element: , - // icon: , - // text: "sidebar.tags", - // path: `/${ABILITIES_ENUM?.TAG}`, - // abilities: ABILITIES_ENUM?.TAG, - // abilities_value: ABILITIES_VALUES_ENUM.INDEX, - // prevPath: 0, - // }, - // { - // header: "page_header.subject", - // element: , - // icon: , - // text: "sidebar.subject", - // path: `/${ABILITIES_ENUM?.SUBJECT}`, - // abilities: ABILITIES_ENUM?.SUBJECT, - // abilities_value: ABILITIES_VALUES_ENUM.INDEX, - // prevPath: 0, - // }, - - // { - // header: "page_header.package", - // element: , - // icon: , - // text: "sidebar.package", - // path: `/${ABILITIES_ENUM?.Package}`, - // abilities: ABILITIES_ENUM?.Package, - // abilities_value: ABILITIES_VALUES_ENUM.INDEX, - // prevPath: 0, - // }, - // { - // header: "page_header.subject", - // element: , - // icon: , - // text: "sidebar.subject", - // path: `/${ABILITIES_ENUM?.SUBJECT}`, - // abilities: ABILITIES_ENUM?.SUBJECT, - // abilities_value: ABILITIES_VALUES_ENUM.INDEX, - // prevPath: 0, - // }, - // { - // header: "page_header.tags", - // element: , - // icon: , - // text: "sidebar.tags", - // path: `/${ABILITIES_ENUM?.TAG}`, - // abilities: ABILITIES_ENUM?.TAG, - // abilities_value: ABILITIES_VALUES_ENUM.INDEX, - // prevPath: 0, - // }, ]; export const CrudRoute: TCrudRoute[] = [ @@ -261,6 +210,14 @@ export const CrudRoute: TCrudRoute[] = [ abilities_value: ABILITIES_VALUES_ENUM.INDEX, prevPath: 0, }, + { + header: "page_header.student", + element: , + path: `/${ABILITIES_ENUM?.STUDENT}/:id`, + abilities: ABILITIES_ENUM?.STUDENT, + abilities_value: ABILITIES_VALUES_ENUM.INDEX, + prevPath: 0, + } ]; export const AppRoutes: Record = Object.fromEntries( diff --git a/src/Styles/Pages/StudentInfoCard.scss b/src/Styles/Pages/StudentInfoCard.scss new file mode 100644 index 0000000..efe2635 --- /dev/null +++ b/src/Styles/Pages/StudentInfoCard.scss @@ -0,0 +1,101 @@ +.single_student{ + display: flex; + .single_student_body{ + display: flex; + width: 100%; + .student_info{ + width: 32%; + } + .student_table{ + width: 68%; + } + } +} + + +.student_info_card{ + width: 24vw; + box-shadow: 2px 2px 8px 3px rgba(0, 0, 0, 0.1); + border-radius: 10px; + padding: 20px 15px ; + .student_info_card_header{ + display: flex; + gap: 10px; + img{ + width: 24%; + } + .student_name_and_sub{ + display: flex; flex-direction: column;justify-content: center; + span{ + color: greenyellow; + } + h2{ + font-size: 22px; + } + } + } + .student_info_card_body{ + display: flex; flex-direction: column; + gap: 30px; + span{ + display: flex;justify-content: space-between; + h4{ + color: #202C4B; + font-size: 20px; + } + p{ + color: #6A7287; + } + } + } +} + +.student_address_card{ + width: 24vw; + box-shadow: 2px 2px 8px 3px rgba(0, 0, 0, 0.1); + border-radius: 10px; + padding: 20px 15px ; + margin-top: 30px; + .student_address_card_body{ + display: flex;align-items: center; + gap: 15px; + svg{ + @include Flex; + border-radius: 5px; + background: #F2F4F8; + width: 40px;height: 40px; + padding: 7px; + } + p{ + color: #6A7287; + } + } +} + + + +@media screen and (max-width:1250px) { + .single_student{ + display: flex; + .single_student_body{ + display: flex;flex-direction: column !important; + width: 100%; + .student_info{ + display: flex; + width: 100%; + gap: 20px; + .student_address_card{ + width: 50%; + margin-top: 0 !important; + max-height: 17vw ; + } + .student_info_card{ + width: 50%; + } + } + .student_table{ + width: 100%; + } + } + } +} diff --git a/src/Styles/Pages/index.scss b/src/Styles/Pages/index.scss index 7c8444d..ddd784b 100644 --- a/src/Styles/Pages/index.scss +++ b/src/Styles/Pages/index.scss @@ -9,4 +9,5 @@ @import "./subject.scss"; @import "./Marks.scss"; @import "./exercise.scss"; -@import './reSeller.scss'; \ No newline at end of file +@import './reSeller.scss'; +@import './StudentInfoCard.scss'; \ No newline at end of file diff --git a/src/translate/ar.json b/src/translate/ar.json index b9c32df..ba40102 100644 --- a/src/translate/ar.json +++ b/src/translate/ar.json @@ -177,7 +177,13 @@ "key": "المفتاح", "expiration_date": "تاريخ الالغاء", "activation_date": "تاريخ التنشيط", - "first_name": "الاسم الأول" + "first_name": "الاسم الأول", + "quiz_date":"تاريخ الاختبار", + "quiz_address":"عنوان الاختبار", + "subject":"المادة", + "quiz_status":"حالة الاختبار", + "creator_name":"اسم المنشئ", + "created_by":"أنشئ بواسطة" }, "practical": { "to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال", @@ -224,7 +230,10 @@ "reset": "اعادة تعيين", "next": "التالي", "prev": "السابق", - "Abbreviations": "الاختصارات" + "Abbreviations": "الاختصارات", + "address":"العنوان", + "quiz":"الاختبارات", + "hightes_quiz":"اعلى اختبار" }, "Table": { "header": "", @@ -739,7 +748,8 @@ "student": "الطلاب", "reseller": "البائعين", "param": "معامل", - "student_package": "حزمة الطالب" + "student_package": "حزمة الطالب", + "quiz":"الاختبارات" }, "message": { "some_thing_went_wrong": "حدث خطأ ما", @@ -770,7 +780,11 @@ "add_reseller":"إضافة بائع", "grade":"الصفوف" , "report":"تقرير", - "tags":"كلمات مفتاحية" + "tags":"كلمات مفتاحية", + "users":"المستخدمون", + "reseller":"البائعين", + "students":"الطلاب", + "students_details":"تفاصيل الطلاب" }, "page_header": { "dashboard": "لوحة القيادة / الصفحة الرئيسية", @@ -803,7 +817,7 @@ "edit_Question": "لوحة القيادة /تعديل اسئلة ", "grade": "لوحة القيادة / الصفوف", "report": "تقرير", - "user": "مستخدم", + "users": "لوحة القيادة / المستخدمون", "reseller": " لوحة القيادة / البائعين", "add_reseller": " لوحة القيادة / البائعين / إضافة بائع ", "param": "معامل", diff --git a/src/types/Item.ts b/src/types/Item.ts index 1b799de..ce545df 100644 --- a/src/types/Item.ts +++ b/src/types/Item.ts @@ -354,4 +354,11 @@ type student = { first_name:string; last_name:string; sex:string -} \ No newline at end of file +} + +export type single_user = { + id: number; + type: student; + expiration_date: string; + activation_date: string; +}; \ No newline at end of file diff --git a/src/utils/hasAbilityFn.ts b/src/utils/hasAbilityFn.ts index 1d1c1e0..a5e6043 100644 --- a/src/utils/hasAbilityFn.ts +++ b/src/utils/hasAbilityFn.ts @@ -620,7 +620,6 @@ export const canDeleteUser = hasAbility( ABILITIES_VALUES_ENUM.DELETE, ); - /// ReSeller export const canAddReSeller = hasAbility( @@ -678,3 +677,5 @@ export const canDeleteStudent_Package = hasAbility( ABILITIES_ENUM.Student_Package, ABILITIES_VALUES_ENUM.DELETE, ); + +