diff --git a/src/Pages/Admin/Manager/Edit/Page.tsx b/src/Pages/Admin/Manager/Edit/Page.tsx
new file mode 100644
index 0000000..71a2fa3
--- /dev/null
+++ b/src/Pages/Admin/Manager/Edit/Page.tsx
@@ -0,0 +1,54 @@
+import { useTranslation } from "react-i18next";
+import useSetPageTitle from "../../../../Hooks/useSetPageTitle";
+import PageHeader from "../../../../Layout/Dashboard/PageHeader";
+import { Suspense } from "react";
+import { Spin } from "antd";
+import { ModalEnum } from "../../../../enums/Model";
+import { canAddReSeller } from "../../../../utils/hasAbilityFn";
+import PersonalDetailsForm from "../Form/PersonalDetailsForm";
+import { Formik, Form } from "formik";
+import { getInitialValues, getValidationSchema } from "../Form/formUtils";
+import TitleDetailsForm from "../Form/TitleDetailsForm";
+import AttachmentForm from "../Form/AttachmentForm";
+import PasswordDetailsForm from "../Form/PasswordDetailsForm";
+
+const TableHeader = () => {
+ const [t] = useTranslation();
+ useSetPageTitle(t(`page_header.add_reseller`));
+ const handelSubmit = (values: any) => {
+ console.log(values, "values");
+ };
+ return (
+
+ );
+};
+
+export default TableHeader;
diff --git a/src/Pages/Admin/Manager/Form/PasswordDetailsForm.tsx b/src/Pages/Admin/Manager/Form/PasswordDetailsForm.tsx
new file mode 100644
index 0000000..3f19706
--- /dev/null
+++ b/src/Pages/Admin/Manager/Form/PasswordDetailsForm.tsx
@@ -0,0 +1,23 @@
+import { useTranslation } from "react-i18next";
+import { FaStore } from "react-icons/fa";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+
+const PasswordDetailsForm = () => {
+ const [t] = useTranslation();
+
+ return (
+
+
+
+ {t("header.password")}
+
+
+
+
+
+
+
+ );
+};
+
+export default PasswordDetailsForm;
diff --git a/src/Pages/Admin/Manager/Form/PersonalDetailsForm.tsx b/src/Pages/Admin/Manager/Form/PersonalDetailsForm.tsx
index 5815b15..2cdf203 100644
--- a/src/Pages/Admin/Manager/Form/PersonalDetailsForm.tsx
+++ b/src/Pages/Admin/Manager/Form/PersonalDetailsForm.tsx
@@ -16,15 +16,15 @@ const PersonalDetailsForm = () => {
{
/>
{
type="text"
/>
{
+
+ const {t} = useTranslation();
+ return (
+
+
{t(label)}
+
{t(value)}
+
+ )
+}
+
+export default CollectionInfoCard
diff --git a/src/Pages/ReSeller/Collections/Model/FilterForm.tsx b/src/Pages/ReSeller/Collections/Model/FilterForm.tsx
new file mode 100644
index 0000000..d601efb
--- /dev/null
+++ b/src/Pages/ReSeller/Collections/Model/FilterForm.tsx
@@ -0,0 +1,22 @@
+import React from "react";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { Col, Row } from "reactstrap";
+
+const FilterForm = () => {
+ return (
+
+
+
+
+ {/* */}
+
+
+
+ );
+};
+
+export default FilterForm;
diff --git a/src/Pages/ReSeller/Collections/Page.tsx b/src/Pages/ReSeller/Collections/Page.tsx
new file mode 100644
index 0000000..37b68ad
--- /dev/null
+++ b/src/Pages/ReSeller/Collections/Page.tsx
@@ -0,0 +1,40 @@
+import { useTranslation } from "react-i18next";
+import { lazy, 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 CollectionInfoCard from "./Model/CollectionInfoCard";
+import { CollectionData } from "../../../faker/item";
+const Table = lazy(() => import("./Table"));
+
+const TableHeader = () => {
+ const [t] = useTranslation();
+ useSetPageTitle([
+ {name:`${t(`page_header.home`)}`, path:"/"},
+ {name:`${t(`page_header.collections`)}`, path:"collections"}
+ ]);
+
+ return (
+
+
}>
+
+
+ {CollectionData?.map((collection:any)=>(
+
+ ))}
+
+
}
+ filterTitle="table.collections"
+ />
+
+
+
+ );
+};
+
+export default TableHeader;
diff --git a/src/Pages/ReSeller/Collections/Table.tsx b/src/Pages/ReSeller/Collections/Table.tsx
new file mode 100644
index 0000000..3c2f8c8
--- /dev/null
+++ b/src/Pages/ReSeller/Collections/Table.tsx
@@ -0,0 +1,21 @@
+import React from "react";
+import DataTable from "../../../Layout/Dashboard/Table/DataTable";
+import { useColumns } from "./useTableColumns";
+import useSearchQuery from "../../../api/utils/useSearchQuery";
+import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
+import { useGetAllSales } from "../../../api/sales";
+
+const App: React.FC = () => {
+ const [searchQuery] = useSearchQuery("name");
+ const { filterState } = useFilterState();
+
+ const response = useGetAllSales({
+ name: searchQuery,
+ pagination: true,
+ ...filterState,
+ });
+
+ return ;
+};
+
+export default App;
diff --git a/src/Pages/ReSeller/Collections/index.tsx b/src/Pages/ReSeller/Collections/index.tsx
new file mode 100644
index 0000000..447f22d
--- /dev/null
+++ b/src/Pages/ReSeller/Collections/index.tsx
@@ -0,0 +1,17 @@
+import { useColumns } from "./useTableColumns";
+import Table from "./Table";
+
+import { FaPlus } from "react-icons/fa";
+
+import AddModalForm from "./Model/AddModel";
+import EditModalForm from "./Model/EditModel";
+// import DeleteModalForm from "../../";
+
+export {
+ Table,
+ useColumns,
+ AddModalForm,
+ EditModalForm,
+ // DeleteModalForm,
+ FaPlus,
+};
diff --git a/src/Pages/ReSeller/Collections/useTableColumns.tsx b/src/Pages/ReSeller/Collections/useTableColumns.tsx
new file mode 100644
index 0000000..b5057b1
--- /dev/null
+++ b/src/Pages/ReSeller/Collections/useTableColumns.tsx
@@ -0,0 +1,43 @@
+import { TableColumnsType } from "antd";
+import { Collection } from "../../../types/Item";
+import { useTranslation } from "react-i18next";
+
+export const useColumns = () => {
+ const [t] = useTranslation();
+
+
+ const columns: TableColumnsType = [
+ {
+ title: t("columns.ID"),
+ dataIndex: "id",
+ key: "id",
+ align: "center",
+ },
+ {
+ title: t("columns.amount"),
+ dataIndex: "amount",
+ key: "amount",
+ align: "center",
+ },
+ {
+ title: t("columns.date_of_receipt"),
+ dataIndex: "date_of_receipt",
+ key: "date_of_receipt",
+ align: "center",
+ },
+ {
+ title: t("columns.description"),
+ dataIndex: "description",
+ key: "description",
+ align: "center",
+ },
+ {
+ title: t("columns.residual"),
+ dataIndex: "residual",
+ key: "residual",
+ align: "center",
+ },
+ ];
+
+ return columns;
+};
diff --git a/src/Pages/ReSeller/Notifications/Card.tsx b/src/Pages/ReSeller/Notifications/Card.tsx
new file mode 100644
index 0000000..e936b14
--- /dev/null
+++ b/src/Pages/ReSeller/Notifications/Card.tsx
@@ -0,0 +1,29 @@
+import TrashButton from "../../../Components/Ui/TrashButton"
+import { notifications } from "../../../types/Notifications"
+
+
+const Card = ({name,date,image,id,pop,setPop}:notifications) => {
+ const handleDeleteOne = () => {
+ setPop(pop?.filter((item:any)=> item?.id !== id))
+ }
+
+ return (
+
+
+

+
+
+
+
+
+
+ )
+}
+
+export default Card
\ No newline at end of file
diff --git a/src/Pages/ReSeller/Notifications/NotificationArray.ts b/src/Pages/ReSeller/Notifications/NotificationArray.ts
new file mode 100644
index 0000000..b5b00ed
--- /dev/null
+++ b/src/Pages/ReSeller/Notifications/NotificationArray.ts
@@ -0,0 +1,16 @@
+import { notifications } from "../../../types/Notifications";
+
+export const NotificationArray:notifications[] = [
+ {id:1,name:"تم إضافة تحصيل جديد بواسطة شاون",date:"1/10/2010",image:"/Image/faker_user.png"},
+ {id:2,name:"moa",date:"منذ ساعة",image:"/Image/faker_user.png"},
+ {id:3,name:"moaz",date:"1/10/2010",image:"/Image/faker_user.png"},
+ {id:4,name:"hello",date:"1/10/2010",image:"/Image/faker_user.png"},
+ {id:5,name:"nop",date:"1/10/2010",image:"/Image/faker_user.png"},
+ {id:6,name:"hey",date:"1/10/2010",image:"/Image/faker_user.png"},
+ // {id:2,name:"moaz",date:"1/10/2010",image:"/Image/faker_user.png"},
+ // {id:2,name:"moaz",date:"1/10/2010",image:"/Image/faker_user.png"},
+ // {id:2,name:"moaz",date:"1/10/2010",image:"/Image/faker_user.png"},
+ // {id:2,name:"moaz",date:"1/10/2010",image:"/Image/faker_user.png"},
+ // {id:2,name:"moaz",date:"1/10/2010",image:"/Image/faker_user.png"},
+
+]
\ No newline at end of file
diff --git a/src/Pages/ReSeller/Notifications/Page.tsx b/src/Pages/ReSeller/Notifications/Page.tsx
new file mode 100644
index 0000000..4ad956c
--- /dev/null
+++ b/src/Pages/ReSeller/Notifications/Page.tsx
@@ -0,0 +1,41 @@
+import { Divider } from 'antd';
+import { useTranslation } from 'react-i18next'
+import { NotificationArray } from './NotificationArray';
+import { notifications } from '../../../types/Notifications';
+import Card from './Card';
+import TrashButton from '../../../Components/Ui/TrashButton';
+import { useState } from 'react';
+
+const Page = () => {
+ const {t} = useTranslation();
+ const [pop, setPop] = useState(NotificationArray)
+
+ const handleDeleteAll = () => {
+ setPop([])
+ }
+
+ return (
+
+
+
{t("header.notifications")}
+
+
+
+
+ {pop?.map((not:notifications)=>(
+
+ ))}
+
+
+ )
+}
+
+export default Page
\ No newline at end of file
diff --git a/src/Pages/ReSeller/Profile/Form/AttachmentForm.tsx b/src/Pages/ReSeller/Profile/Form/AttachmentForm.tsx
new file mode 100644
index 0000000..da3397c
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/AttachmentForm.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+import { useTranslation } from "react-i18next";
+import { FaImage } from "react-icons/fa";
+import ImageBoxField from "./ImageBoxField/ImageBoxField";
+
+const AttachmentForm = () => {
+ const [t] = useTranslation();
+
+ return (
+
+ );
+};
+
+export default AttachmentForm;
diff --git a/src/Pages/ReSeller/Profile/Form/HeaderForm.tsx b/src/Pages/ReSeller/Profile/Form/HeaderForm.tsx
new file mode 100644
index 0000000..eb9a94e
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/HeaderForm.tsx
@@ -0,0 +1,24 @@
+import { Button } from 'antd';
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+
+const HeaderForm = ({name,Icon,ButtonIcon, isHaveButtonIcon= true,buttonName = "edit"}:{name:string,Icon:any,ButtonIcon?:any,isHaveButtonIcon?:boolean,buttonName?:string}) => {
+ const {t} = useTranslation();
+ return (
+ <>
+
+
+
{t(`header.${name}`)}
+
+
+
+
+ >
+ )
+}
+
+export default HeaderForm
\ No newline at end of file
diff --git a/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageBoxField.scss b/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageBoxField.scss
new file mode 100644
index 0000000..66e2f2f
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageBoxField.scss
@@ -0,0 +1,38 @@
+.ImageBoxField {
+ .ImageBox {
+ width: 120px;
+ height: 120px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: max(1.5px, 0.1vw) dashed #a9c3f1;
+ margin-block: 10px;
+ border-radius: 5px;
+ z-index: 9999999 !important;
+ .ImageBoxIcon {
+ cursor: pointer;
+ }
+ .imagePreview {
+ max-width: 99%;
+ height: auto;
+ max-height: 99%;
+ object-fit: contain;
+ border-radius: 5px;
+ }
+ }
+ .ImageHeader {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 10px;
+ }
+
+ .ImageCancelIcon {
+ width: 16px !important;
+ height: 16px !important;
+ }
+ .ImageBoxIcon {
+ width: 20px !important;
+ height: 20px !important;
+ }
+}
diff --git a/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageBoxField.tsx b/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageBoxField.tsx
new file mode 100644
index 0000000..d163048
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageBoxField.tsx
@@ -0,0 +1,87 @@
+import { useFormikContext } from "formik";
+import { useState, useRef, useEffect } from "react";
+import "./ImageBoxField.scss";
+import ImageIcon from "./ImageIcon";
+import ImageCancelIcon from "./ImageCancelIcon";
+import { generateImagePreview } from "./generateImagePreview";
+import { getNestedValue } from "../../../../../utils/getNestedValue";
+import { useTranslation } from "react-i18next";
+
+// Helper function to generate image preview from a File
+
+const ImageBoxField = ({ name }: any) => {
+ const formik = useFormikContext();
+ const value = getNestedValue(formik.values, name);
+ const [imagePreview, setImagePreview] = useState(null);
+ const fileInputRef = useRef(null);
+
+ useEffect(() => {
+ if (value instanceof File) {
+ generateImagePreview(value, setImagePreview);
+ } else if (typeof value === "string") {
+ setImagePreview(value);
+ } else {
+ setImagePreview(null);
+ }
+ }, [value]);
+
+ const handleFileChange = (event: any) => {
+ const file = event.target.files[0];
+ if (file) {
+ generateImagePreview(file, setImagePreview);
+ formik.setFieldValue(name, file);
+ }
+ };
+
+ const handleButtonClick = () => {
+ const fileInput = fileInputRef.current;
+ if (fileInput) {
+ fileInput.click();
+ }
+ };
+
+ const handleCancel = () => {
+ setImagePreview("");
+ formik.setFieldValue(name, "");
+
+ if (fileInputRef.current) {
+ fileInputRef.current.value = "";
+ }
+ };
+ const [t] = useTranslation();
+ return (
+
+
+
+ {imagePreview ? (
+ <>
+
+
+ >
+ ) : (
+
hidden
+ )}
+
+
+ {imagePreview ? (
+

+ ) : (
+
+ )}
+
+
+
+ );
+};
+
+export default ImageBoxField;
diff --git a/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageCancelIcon.tsx b/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageCancelIcon.tsx
new file mode 100644
index 0000000..d42ba53
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageCancelIcon.tsx
@@ -0,0 +1,18 @@
+import React from "react";
+
+interface ImageCancelIconProps extends React.HTMLAttributes {}
+
+const ImageCancelIcon: React.FC = (props) => {
+ return (
+
+ );
+};
+
+export default ImageCancelIcon;
diff --git a/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageIcon.tsx b/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageIcon.tsx
new file mode 100644
index 0000000..4ca597a
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/ImageBoxField/ImageIcon.tsx
@@ -0,0 +1,18 @@
+import React from "react";
+
+interface ImageIconProps extends React.HTMLAttributes {}
+
+const ImageIcon: React.FC = (props) => {
+ return (
+
+ );
+};
+
+export default ImageIcon;
diff --git a/src/Pages/ReSeller/Profile/Form/ImageBoxField/generateImagePreview.ts b/src/Pages/ReSeller/Profile/Form/ImageBoxField/generateImagePreview.ts
new file mode 100644
index 0000000..3f754d3
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/ImageBoxField/generateImagePreview.ts
@@ -0,0 +1,10 @@
+export const generateImagePreview = (
+ file: File,
+ setImagePreview: (result: string) => void,
+) => {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ setImagePreview(reader.result as string);
+ };
+ reader.readAsDataURL(file);
+};
diff --git a/src/Pages/ReSeller/Profile/Form/PasswordDetailsForm.tsx b/src/Pages/ReSeller/Profile/Form/PasswordDetailsForm.tsx
new file mode 100644
index 0000000..c6e9edb
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/PasswordDetailsForm.tsx
@@ -0,0 +1,25 @@
+import { useTranslation } from "react-i18next";
+import { FaStore } from "react-icons/fa";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import HeaderForm from "./HeaderForm";
+
+const PasswordDetailsForm = () => {
+ const [t] = useTranslation();
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default PasswordDetailsForm;
diff --git a/src/Pages/ReSeller/Profile/Form/PersonalDetailsForm.tsx b/src/Pages/ReSeller/Profile/Form/PersonalDetailsForm.tsx
new file mode 100644
index 0000000..96d9ed5
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/PersonalDetailsForm.tsx
@@ -0,0 +1,56 @@
+import { useTranslation } from "react-i18next";
+import { FaStore } from "react-icons/fa";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { statusType } from "../../../../config/statusType";
+import { Button } from "antd";
+import { CiEdit } from "react-icons/ci";
+import HeaderForm from "./HeaderForm";
+
+const PersonalDetailsForm = () => {
+ const [t] = useTranslation();
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default PersonalDetailsForm;
diff --git a/src/Pages/ReSeller/Profile/Form/TitleDetailsForm.tsx b/src/Pages/ReSeller/Profile/Form/TitleDetailsForm.tsx
new file mode 100644
index 0000000..1e62655
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/TitleDetailsForm.tsx
@@ -0,0 +1,33 @@
+import { useTranslation } from "react-i18next";
+import { FaStore } from "react-icons/fa";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { nationalities } from "../../../../types/App";
+import { CiEdit } from "react-icons/ci";
+import HeaderForm from "./HeaderForm";
+
+const TitleDetailsForm = () => {
+ const [t] = useTranslation();
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+export default TitleDetailsForm;
diff --git a/src/Pages/ReSeller/Profile/Form/formUtils.ts b/src/Pages/ReSeller/Profile/Form/formUtils.ts
new file mode 100644
index 0000000..b14915a
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Form/formUtils.ts
@@ -0,0 +1,13 @@
+import * as Yup from "yup";
+
+export const getInitialValues = (objectToEdit: Partial) => {
+ return {
+ id: objectToEdit?.id ?? null,
+ name: objectToEdit?.name ?? null,
+ };
+};
+
+export const getValidationSchema = () => {
+ // validate input
+ return Yup.object().shape({});
+};
diff --git a/src/Pages/ReSeller/Profile/Page.tsx b/src/Pages/ReSeller/Profile/Page.tsx
new file mode 100644
index 0000000..def9cc2
--- /dev/null
+++ b/src/Pages/ReSeller/Profile/Page.tsx
@@ -0,0 +1,58 @@
+import { useTranslation } from "react-i18next";
+import useSetPageTitle from "../../../Hooks/useSetPageTitle";
+import PageHeader from "../../../Layout/Dashboard/PageHeader";
+import { Suspense } from "react";
+import { Spin } from "antd";
+import { ModalEnum } from "../../../enums/Model";
+import { canAddReSeller } from "../../../utils/hasAbilityFn";
+import { Formik, Form } from "formik";
+import { getInitialValues, getValidationSchema } from "./Form/formUtils";
+import PersonalDetailsForm from "./Form/PersonalDetailsForm";
+import TitleDetailsForm from "./Form/TitleDetailsForm";
+import AttachmentForm from "./Form/AttachmentForm";
+import PasswordDetailsForm from "./Form/PasswordDetailsForm";
+
+const Page = () => {
+ const [t] = useTranslation();
+ useSetPageTitle(t(`page_header.add_reseller`));
+ const handelSubmit = (values: any) => {
+ console.log(values, "values");
+ };
+ useSetPageTitle([
+ {name:`${t(`page_header.home`)}`, path:"/"},
+ {name:`${t(`page_header.profile`)}`, path:"tag"}
+ ]);
+ return (
+
+ );
+};
+
+export default Page;
diff --git a/src/Pages/ReSeller/Sales/Model/AddModel.tsx b/src/Pages/ReSeller/Sales/Model/AddModel.tsx
new file mode 100644
index 0000000..dd0547e
--- /dev/null
+++ b/src/Pages/ReSeller/Sales/Model/AddModel.tsx
@@ -0,0 +1,34 @@
+import React from "react";
+import { getInitialValues, getValidationSchema } from "./formUtil";
+import { ModalEnum } from "../../../../enums/Model";
+import LayoutModel from "../../../../Layout/Dashboard/LayoutModel";
+import { QueryStatusEnum } from "../../../../enums/QueryStatus";
+import ModelForm from "./ModelForm";
+import { useAddStudentPackage } from "../../../../api/studentPackage";
+import { useAddSales } from "../../../../api/sales";
+
+const AddModel: React.FC = () => {
+ const { mutate, status } = useAddSales();
+
+ const handleSubmit = (values: any) => {
+ mutate({
+ ...values,
+ });
+ };
+ return (
+ <>
+
+
+
+ >
+ );
+};
+
+export default AddModel;
diff --git a/src/Pages/ReSeller/Sales/Model/FilterForm.tsx b/src/Pages/ReSeller/Sales/Model/FilterForm.tsx
new file mode 100644
index 0000000..d601efb
--- /dev/null
+++ b/src/Pages/ReSeller/Sales/Model/FilterForm.tsx
@@ -0,0 +1,22 @@
+import React from "react";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { Col, Row } from "reactstrap";
+
+const FilterForm = () => {
+ return (
+
+
+
+
+ {/* */}
+
+
+
+ );
+};
+
+export default FilterForm;
diff --git a/src/Pages/ReSeller/Sales/Model/ModelForm.tsx b/src/Pages/ReSeller/Sales/Model/ModelForm.tsx
new file mode 100644
index 0000000..4cace32
--- /dev/null
+++ b/src/Pages/ReSeller/Sales/Model/ModelForm.tsx
@@ -0,0 +1,26 @@
+import { Col, Row } from "reactstrap";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import useFormatDataToSelect from "../../../../utils/useFormatDataToSelect";
+
+const Form = ({ isEdit }: { isEdit?: boolean }) => {
+ const typeOptions = [
+ { id: "student", name: "student" },
+ { id: "reseller", name: "reseller" },
+ { id: "admin", name: "admin" },
+ ];
+ const typeArray = useFormatDataToSelect(typeOptions);
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default Form;
diff --git a/src/Pages/ReSeller/Sales/Model/formUtil.ts b/src/Pages/ReSeller/Sales/Model/formUtil.ts
new file mode 100644
index 0000000..d2aa9da
--- /dev/null
+++ b/src/Pages/ReSeller/Sales/Model/formUtil.ts
@@ -0,0 +1,13 @@
+import * as Yup from "yup";
+
+export const getInitialValues = (objectToEdit: any): any => {
+ return {
+ id: objectToEdit?.id ?? null,
+ phone_number: objectToEdit?.phone_number ?? null,
+ };
+};
+export const getValidationSchema = () => {
+ return Yup.object().shape({
+ phone_number: Yup.number().required("validation.required"),
+ });
+};
diff --git a/src/Pages/ReSeller/Sales/Page.tsx b/src/Pages/ReSeller/Sales/Page.tsx
new file mode 100644
index 0000000..f0856a9
--- /dev/null
+++ b/src/Pages/ReSeller/Sales/Page.tsx
@@ -0,0 +1,38 @@
+import { ModalEnum } from "../../../enums/Model";
+import { useTranslation } from "react-i18next";
+import { lazy, Suspense } from "react";
+import { Spin } from "antd";
+import { canAddSales } from "../../../utils/hasAbilityFn";
+import useSetPageTitle from "../../../Hooks/useSetPageTitle";
+import { useDeleteTag } from "../../../api/tags";
+import PageHeader from "../../../Layout/Dashboard/PageHeader";
+import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
+import FilterForm from "./Model/FilterForm";
+const Table = lazy(() => import("./Table"));
+const AddModalForm = lazy(() => import("./Model/AddModel"));
+
+const TableHeader = () => {
+ const [t] = useTranslation();
+ useSetPageTitle([
+ {name:`${t(`page_header.home`)}`, path:"/"},
+ {name:`${t(`page_header.sales`)}`, path:"sales"}
+ ]); return (
+
+
}>
+
+
}
+ filterTitle="table.sales"
+ />
+
+
+
+
+ );
+};
+
+export default TableHeader;
diff --git a/src/Pages/ReSeller/Sales/Table.tsx b/src/Pages/ReSeller/Sales/Table.tsx
new file mode 100644
index 0000000..9981329
--- /dev/null
+++ b/src/Pages/ReSeller/Sales/Table.tsx
@@ -0,0 +1,20 @@
+import React from "react";
+import DataTable from "../../../Layout/Dashboard/Table/DataTable";
+import { useColumns } from "./useTableColumns";
+import useSearchQuery from "../../../api/utils/useSearchQuery";
+import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
+import { useGetAllSales } from "../../../api/sales";
+const App: React.FC = () => {
+ const [searchQuery] = useSearchQuery("name");
+ const { filterState } = useFilterState();
+
+ const response = useGetAllSales({
+ name: searchQuery,
+ pagination: true,
+ ...filterState,
+ });
+
+ return ;
+};
+
+export default App;
diff --git a/src/Pages/ReSeller/Sales/index.tsx b/src/Pages/ReSeller/Sales/index.tsx
new file mode 100644
index 0000000..447f22d
--- /dev/null
+++ b/src/Pages/ReSeller/Sales/index.tsx
@@ -0,0 +1,17 @@
+import { useColumns } from "./useTableColumns";
+import Table from "./Table";
+
+import { FaPlus } from "react-icons/fa";
+
+import AddModalForm from "./Model/AddModel";
+import EditModalForm from "./Model/EditModel";
+// import DeleteModalForm from "../../";
+
+export {
+ Table,
+ useColumns,
+ AddModalForm,
+ EditModalForm,
+ // DeleteModalForm,
+ FaPlus,
+};
diff --git a/src/Pages/ReSeller/Sales/useTableColumns.tsx b/src/Pages/ReSeller/Sales/useTableColumns.tsx
new file mode 100644
index 0000000..ea81cfc
--- /dev/null
+++ b/src/Pages/ReSeller/Sales/useTableColumns.tsx
@@ -0,0 +1,49 @@
+import { TableColumnsType } from "antd";
+import { Sales } from "../../../types/Item";
+import { useTranslation } from "react-i18next";
+
+export const useColumns = () => {
+ const [t] = useTranslation();
+
+
+ const columns: TableColumnsType = [
+ {
+ title: t("columns.id"),
+ dataIndex: "id",
+ key: "id",
+ align: "center",
+ },
+ {
+ title: t("columns.student_full_name"),
+ dataIndex: "activation_date",
+ key: "activation_date",
+ align: "center",
+ },
+ {
+ title: t("columns.grade"),
+ dataIndex: "grade",
+ key: "grade",
+ align: "center",
+ },
+ {
+ title: t("columns.package"),
+ dataIndex: "package",
+ key: "package",
+ align: "center",
+ },
+ {
+ title: t("columns.amount_paid"),
+ dataIndex: "amount_paid",
+ key: "amount_paid",
+ align: "center",
+ },
+ {
+ title: t("columns.sale_date"),
+ dataIndex: "sale_date",
+ key: "sale_date",
+ align: "center",
+ },
+ ];
+
+ return columns;
+};
diff --git a/src/Routes.tsx b/src/Routes.tsx
index 8f6c45e..02ddcf1 100644
--- a/src/Routes.tsx
+++ b/src/Routes.tsx
@@ -25,6 +25,7 @@ const Student = React.lazy(() => import("./Pages/Admin/Student/Page"));
const ShowStudent = React.lazy(() => import("./Pages/Admin/Student/show/Page"));
const Manager = React.lazy(() => import("./Pages/Admin/Manager/Page"));
const AddManager = React.lazy(() => import("./Pages/Admin/Manager/Add/Page"));
+const EditManager = React.lazy(() => import("./Pages/Admin/Manager/Edit/Page"));
const ReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Page"));
@@ -44,9 +45,12 @@ const Report = React.lazy(() => import("./Pages/Admin/Report/Page"));
const Param = React.lazy(() => import("./Pages/Admin/Param/Page"));
/// RESELLER ///
-const Student_Package = React.lazy(
- () => import("./Pages/ReSeller/StudentPackage/Page"),
-);
+const Sales = React.lazy(() => import("./Pages/ReSeller/Sales/Page"));
+const Collections = React.lazy(() => import("./Pages/ReSeller/Collections/Page"));
+
+const NotificationReSeller = React.lazy(() => import("./Pages/ReSeller/Notifications/Page"));
+const ProfileReSeller = React.lazy(() => import("./Pages/ReSeller/Profile/Page"));
+
import { hasAbility } from "./utils/hasAbility";
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "./enums/abilities";
@@ -97,16 +101,16 @@ export const menuItems: TMenuItem[] = [
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0,
},
- // {
- // header: "page_header.managers",
- // element: ,
- // icon: ,
- // text: "sidebar.managers",
- // path: `/${ABILITIES_ENUM?.MANAGERS}`,
- // abilities: ABILITIES_ENUM?.MANAGERS,
- // abilities_value: ABILITIES_VALUES_ENUM.INDEX,
- // prevPath: 0,
- // },
+ {
+ header: "page_header.managers",
+ element: ,
+ icon: ,
+ text: "sidebar.managers",
+ path: `/${ABILITIES_ENUM?.MANAGERS}`,
+ abilities: ABILITIES_ENUM?.MANAGERS,
+ abilities_value: ABILITIES_VALUES_ENUM.INDEX,
+ prevPath: 0,
+ },
]
},
{
@@ -174,14 +178,35 @@ export const menuItems: TMenuItem[] = [
/// RESELLER /////
-
{
- header: "page_header.student_package",
- element: ,
+ header: "page_header.sales",
+ element: ,
icon: ,
- text: "sidebar.student_package",
- path: `/${ABILITIES_ENUM?.Student_Package}`,
- abilities: ABILITIES_ENUM?.Student_Package,
+ text: "sidebar.sales",
+ path: `/${ABILITIES_ENUM?.Sales}`,
+ abilities: ABILITIES_ENUM?.Sales,
+ abilities_value: ABILITIES_VALUES_ENUM.INDEX,
+ prevPath: 0,
+ type: UserTypeEnum.RE_SELLER,
+ },
+ {
+ header: "page_header.collections",
+ element: ,
+ icon: ,
+ text: "sidebar.collections",
+ path: `/${ABILITIES_ENUM?.Collections}`,
+ abilities: ABILITIES_ENUM?.Collections,
+ abilities_value: ABILITIES_VALUES_ENUM.INDEX,
+ prevPath: 0,
+ type: UserTypeEnum.RE_SELLER,
+ },
+ {
+ header: "page_header.profile",
+ element: ,
+ icon: ,
+ text: "sidebar.profile",
+ path: `//${ABILITIES_ENUM?.PROFILE}`,
+ abilities: ABILITIES_ENUM?.Profile_RE_SELLER,
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0,
type: UserTypeEnum.RE_SELLER,
@@ -281,14 +306,6 @@ export const CrudRoute: TCrudRoute[] = [
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0,
},
- {
- header: "page_header.notifications",
- element: ,
- path: `/${ABILITIES_ENUM?.NOTIFICATIONS}`,
- abilities: ABILITIES_ENUM?.NOTIFICATIONS,
- abilities_value: ABILITIES_VALUES_ENUM.INDEX,
- prevPath: 0,
- },
{
header: "page_header.permissions",
element: ,
@@ -297,6 +314,14 @@ export const CrudRoute: TCrudRoute[] = [
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0,
},
+ {
+ header: "page_header.notifications",
+ element: ,
+ path: `/${ABILITIES_ENUM?.NOTIFICATIONS}`,
+ abilities: ABILITIES_ENUM?.NOTIFICATIONS,
+ abilities_value: ABILITIES_VALUES_ENUM.INDEX,
+ prevPath: 0,
+ },
{
header: "page_header.add_manager",
element: ,
@@ -305,6 +330,24 @@ export const CrudRoute: TCrudRoute[] = [
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0,
},
+ {
+ header: "page_header.edit_manager",
+ element: ,
+ path: `/${ABILITIES_ENUM?.MANAGERS}/edit`,
+ abilities: ABILITIES_ENUM?.MANAGERS,
+ abilities_value: ABILITIES_VALUES_ENUM.INDEX,
+ prevPath: 0,
+ },
+ //// RE_SELLER
+ {
+ header: "page_header.notifications",
+ element: ,
+ path: `/${ABILITIES_ENUM?.NOTIFICATIONS}`,
+ abilities: ABILITIES_ENUM?.NOTIFICATIONS_RE_SELLER,
+ abilities_value: ABILITIES_VALUES_ENUM.INDEX,
+ prevPath: 0,
+ type: UserTypeEnum.RE_SELLER,
+ },
];
export const AppRoutes: Record = Object.fromEntries(
diff --git a/src/Styles/Antd/Model.scss b/src/Styles/Antd/Model.scss
index 61be301..45a3171 100644
--- a/src/Styles/Antd/Model.scss
+++ b/src/Styles/Antd/Model.scss
@@ -5,6 +5,7 @@
.ant-modal .ant-modal-content {
padding: 0;
border-radius: 10px;
+
.ant-modal-close {
display: none !important;
}
@@ -12,10 +13,12 @@
.ModalForm {
position: relative;
+
.ant-divider-horizontal {
// width: 90% !important;
margin: 10px 0;
}
+
header {
display: flex;
justify-content: space-between;
@@ -26,12 +29,14 @@
color: var(--black);
border-top-left-radius: 10px;
border-top-right-radius: 10px;
+
span {
font-size: 25px;
}
+
svg {
font-size: 30px;
- color: #6a7287;
+ color: var(--value);
}
}
@@ -41,6 +46,7 @@
flex-direction: column;
width: 100%;
}
+
main {
.buttons {
padding-inline: 0 10px;
@@ -48,8 +54,9 @@
gap: 10px;
align-items: end;
justify-content: end;
- > button,
- > div {
+
+ >button,
+ >div {
position: relative;
outline: none;
border: none;
@@ -63,6 +70,7 @@
align-items: center;
justify-content: center;
gap: 5px;
+
&:nth-child(1) {
background: var(--white);
color: var(--primary);
@@ -71,13 +79,16 @@
}
}
}
+
label {
color: var(--secondary) !important;
}
}
+
.ant-modal-root .ant-modal-centered .ant-modal {
width: 45vw;
}
+
.ant-modal .ant-modal-body {
padding-inline: 1vw !important;
-}
+}
\ No newline at end of file
diff --git a/src/Styles/App/App.scss b/src/Styles/App/App.scss
index 2ecd94d..139918e 100644
--- a/src/Styles/App/App.scss
+++ b/src/Styles/App/App.scss
@@ -13,6 +13,7 @@ body {
font-weight: 600;
font-size: 16px;
}
+
h1,
h2,
h3,
@@ -42,26 +43,32 @@ svg {
justify-content: center;
text-align: center;
padding-top: 30px;
- .not_found_container{
- display: flex; flex-direction: column;
+
+ .not_found_container {
+ display: flex;
+ flex-direction: column;
align-items: center;
gap: 20px;
- p{
- color: #6A7287;
+
+ p {
+ color: var(--value);
font-size: 17px;
}
- h3{
+
+ h3 {
font-weight: 900;
}
- .not_found_button{
+
+ .not_found_button {
@include Flex;
width: 240px;
- padding: 24px 22px ;
+ padding: 24px 22px;
background: var(--primary);
color: var(--white);
border: none;
transition: ease-in-out .3s;
- &:hover{
+
+ &:hover {
transform: scale(1.05);
background: var(--primary);
color: var(--white);
diff --git a/src/Styles/App/Varibils.scss b/src/Styles/App/Varibils.scss
index 9d6875d..300a964 100644
--- a/src/Styles/App/Varibils.scss
+++ b/src/Styles/App/Varibils.scss
@@ -5,10 +5,12 @@
--text: #202C4B;
--subtext: #9d9d9d;
--label: #0d5190;
+ --value: #6A7287;
--bg: rgb(255, 255, 255);
--bg2: #f4f7fe;
--bg3: rgba(255, 255, 255, 0.82);
--border-color: #b0d9ff;
+ --border-color-2: #E9EDF4;
--shadow: rgba(0, 0, 0, 0.15);
--white: white;
--bgSideBar: #0f0c1c;
@@ -36,5 +38,4 @@
--borderColor: #ffffff91;
--opacity: #bcbcbc;
--fieldHeight: 40px;
-}
-
+}
\ No newline at end of file
diff --git a/src/Styles/DataTable/SearchField.scss b/src/Styles/DataTable/SearchField.scss
index e7c31f4..2886f12 100644
--- a/src/Styles/DataTable/SearchField.scss
+++ b/src/Styles/DataTable/SearchField.scss
@@ -4,17 +4,20 @@
border-radius: 8px;
width: 280px;
direction: ltr;
- color: #6a7287b2;
+ color: var(--value)b2;
}
+
.NavBar {
.search-header {
color: var(--white) !important;
background-color: inherit;
border-radius: 8px;
border: 1px solid var(--borderColor);
- svg{
+
+ svg {
font-size: 24px;
}
+
input {
color: #fff !important;
text-align: end;
@@ -22,6 +25,7 @@
}
}
}
+
.search-header {
display: flex;
align-items: center;
@@ -49,6 +53,7 @@
outline: none;
border: none;
position: relative;
+
.search__input_text {
color: var(--white);
position: absolute;
@@ -57,6 +62,7 @@
font-size: 30px;
width: 100px !important;
}
+
font-weight: normal;
}
@@ -76,6 +82,7 @@
direction: rtl;
scroll-behavior: smooth;
scroll-padding: 10rem;
+
&::-webkit-scrollbar {
width: 10px;
}
@@ -83,19 +90,23 @@
/* Handle */
&::-webkit-scrollbar-thumb {
background-color: transparent;
- border-radius: 5px; /* Adjust border-radius as needed */
+ border-radius: 5px;
+ /* Adjust border-radius as needed */
}
/* Track */
&::-webkit-scrollbar-track {
- border-radius: 5px; /* Adjust border-radius as needed */
- background-color: transparent; /* Set to desired background color */
+ border-radius: 5px;
+ /* Adjust border-radius as needed */
+ background-color: transparent;
+ /* Set to desired background color */
}
}
@mixin CustomScrollbar($color) {
scroll-behavior: smooth;
scroll-padding: 10rem;
+
&::-webkit-scrollbar {
width: 10px;
}
@@ -103,13 +114,16 @@
/* Handle */
&::-webkit-scrollbar-thumb {
background-color: $color;
- border-radius: 5px; /* Adjust border-radius as needed */
+ border-radius: 5px;
+ /* Adjust border-radius as needed */
}
/* Track */
&::-webkit-scrollbar-track {
- border-radius: 5px; /* Adjust border-radius as needed */
- background-color: transparent; /* Set to desired background color */
+ border-radius: 5px;
+ /* Adjust border-radius as needed */
+ background-color: transparent;
+ /* Set to desired background color */
}
}
@@ -157,4 +171,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Styles/Layout/FilterLayout.scss b/src/Styles/Layout/FilterLayout.scss
index b138b96..a0a42c2 100644
--- a/src/Styles/Layout/FilterLayout.scss
+++ b/src/Styles/Layout/FilterLayout.scss
@@ -3,13 +3,15 @@
border-radius: 10px 10px 0 0;
box-shadow: 0px 0px 32px 2px #080F3414;
- > div {
+ >div {
display: flex;
align-items: center;
justify-content: space-between;
+
.filter_and_order_by {
display: flex;
gap: 10px;
+
.filter_button {
display: flex;
justify-content: space-between;
@@ -21,41 +23,51 @@
border: 1px solid var(--opacity) !important;
transition: ease-in-out 0.4s;
cursor: pointer;
+
&:hover {
background: var(--bg4);
}
+
svg {
font-size: 25px;
}
}
}
+
span {
display: flex;
align-items: center;
- color: #6A7287;
+ color: var(--value);
+
.pagination_select,
.order_by_select,
.filter_modal_select {
border: 1px solid var(--opacity);
border-radius: 10px;
+
.addition_select_icon {
font-size: 25px;
}
- div{
- color: #6A7287;
+
+ div {
+ color: var(--value);
}
}
+
p {
padding-inline: 10px;
}
}
}
+
.search-field {
border: 1px solid rgba(0, 0, 0, 0.1);
- .search__input{
+
+ .search__input {
width: 90%;
- text-align: end ;
+ text-align: end;
}
+
.search__icon {
color: var(--primary);
}
@@ -64,16 +76,12 @@
.pagination_column,
.order_by_filter {
- .ant-select-outlined:not(.ant-select-disabled):not(
- .ant-select-customize-input
- ):not(.ant-pagination-size-changer):hover
- .ant-select-selector,
- .ant-select-outlined:not(.ant-select-disabled):not(
- .ant-select-customize-input
- ):not(.ant-pagination-size-changer):hover
- .ant-select-selector {
+
+ .ant-select-outlined:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer):hover .ant-select-selector,
+ .ant-select-outlined:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer):hover .ant-select-selector {
transition: ease-in-out 0.4s !important;
cursor: pointer !important;
+
&:hover {
background: var(--bg4) !important;
}
@@ -86,6 +94,7 @@
}
@media screen and (max-width: 800px) {
+
.filter_modal_add_button,
.filter_modal_cancel_button {
font-size: 8px !important;
@@ -93,6 +102,6 @@
}
-.model_sub_children{
+.model_sub_children {
padding-bottom: 30px;
}
diff --git a/src/Styles/Layout/PageHeader.scss b/src/Styles/Layout/PageHeader.scss
index 723ff39..a5be4fe 100644
--- a/src/Styles/Layout/PageHeader.scss
+++ b/src/Styles/Layout/PageHeader.scss
@@ -1,12 +1,15 @@
.page_header {
margin-bottom: 0px !important;
+
.page_header_links {
display: flex;
flex-direction: column;
+
.page_title {
font-weight: bolder;
font-size: 24px;
}
+
.page_links {
color: var(--opacity);
display: flex;
@@ -17,24 +20,25 @@
}
.filter_header_top {
- h4{
+ h4 {
color: var(--secondary);
- font-weight:600;
+ font-weight: 600;
font-size: 18px;
}
}
-.PageTitle{
+.PageTitle {
display: flex;
- gap: 10px;
- margin-block: 10px;
- .PageTitleItems{
- cursor: pointer;
- color: #6A7287;
- }
+ gap: 10px;
+ margin-block: 10px;
+
+ .PageTitleItems {
+ cursor: pointer;
+ color: var(--value);
+ }
}
-.PageTitleLastItem{
+.PageTitleLastItem {
color: #202C4B !important;
}
\ No newline at end of file
diff --git a/src/Styles/Pages/InfoCard.scss b/src/Styles/Pages/InfoCard.scss
index 1041fd7..2f125e1 100644
--- a/src/Styles/Pages/InfoCard.scss
+++ b/src/Styles/Pages/InfoCard.scss
@@ -28,7 +28,7 @@
padding: 20px 15px;
p {
- color: #6A7287;
+ color: var(--value);
}
.info_card_header {
@@ -68,7 +68,8 @@
font-size: 20px;
}
}
- .info_card_button{
+
+ .info_card_button {
background: var(--primary);
color: var(--white);
padding: 25px 0px;
@@ -80,15 +81,18 @@
.address_card {
margin-block: 30px;
+
.address_card_body {
display: flex;
- flex-direction: column;
+ flex-direction: column;
align-items: center;
- div{
+
+ div {
margin-block: 20px;
gap: 15px;
display: flex !important;
}
+
svg {
@include Flex;
border-radius: 5px;
@@ -99,8 +103,9 @@
}
}
}
-.tab_icon{
- font-size: 30px ;
+
+.tab_icon {
+ font-size: 30px;
}
@media screen and (max-width:1250px) {
@@ -131,32 +136,41 @@
.student_table {
width: 100%;
}
- .reseller_info{
- display: flex; flex-wrap: wrap;
+
+ .reseller_info {
+ display: flex;
+ flex-wrap: wrap;
+
.address_card,
.attachments_card,
- .info_card{
+ .info_card {
width: 45%;
- div{
- span{
+
+ div {
+ span {
font-size: 1.6vw !important;
}
- h4{
+
+ h4 {
font-size: 1.8vw;
}
- h2{
+
+ h2 {
font-size: 1.6vw !important;
}
- h6{
- font-size: 1.6vw !important;
+
+ h6 {
+ font-size: 1.6vw !important;
}
- p{
+
+ p {
font-size: 1.6vw !important;
}
}
}
+
.address_card,
- .attachments_card{
+ .attachments_card {
max-height: 40vh !important;
}
}
diff --git a/src/Styles/Pages/collections.scss b/src/Styles/Pages/collections.scss
new file mode 100644
index 0000000..ba14340
--- /dev/null
+++ b/src/Styles/Pages/collections.scss
@@ -0,0 +1,26 @@
+.collection_infos {
+ margin-block: 20px;
+ display: flex;justify-content: space-between;
+ gap: 5px;
+ .collection_info_card {
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ width: 15vw;
+ padding: 1.2vw 1.2vw;
+ box-shadow: 0px 0px 32px 0px #080F3414;
+ border: 1px solid var(--border-color-2) !important;
+ border-radius: 8px;
+ gap: 10px;
+ h5{
+ color: var(--secondary);
+ font-size: 1vw;
+ font-weight: bold;
+ }
+ p{
+ font-size: .9vw ;
+ color: var(--value);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/Styles/Pages/index.scss b/src/Styles/Pages/index.scss
index 5f71030..a1122fc 100644
--- a/src/Styles/Pages/index.scss
+++ b/src/Styles/Pages/index.scss
@@ -12,4 +12,5 @@
@import './reSeller.scss';
@import './InfoCard.scss';
@import './notifications.scss';
-@import './profile.scss';
\ No newline at end of file
+@import './profile.scss';
+@import './collections.scss'
diff --git a/src/Styles/Pages/notifications.scss b/src/Styles/Pages/notifications.scss
index 2cd760f..35f5982 100644
--- a/src/Styles/Pages/notifications.scss
+++ b/src/Styles/Pages/notifications.scss
@@ -1,52 +1,68 @@
-.notification_container{
- display: flex; flex-direction: column;
+.notification_container {
+ display: flex;
+ flex-direction: column;
width: 96%;
margin-inline: auto;
- padding: 30px 20px ;
+ padding: 30px 20px;
margin-block: 20px 50px;
box-shadow: 2px 2px 8px 3px rgba(0, 0, 0, 0.1);
border: 1.5px solid #E9EDF4;
border-radius: 10px;
background: #fff;
- .notification_header{
- display: flex;align-items: center;justify-content: space-between;
+
+ .notification_header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
padding-inline: 20px;
- h4{
+
+ h4 {
color: var(--secondary);
}
}
- .notification_body{
- display: flex; flex-direction: column;
+
+ .notification_body {
+ display: flex;
+ flex-direction: column;
justify-content: center;
- padding-inline: 10px ;
+ padding-inline: 10px;
gap: 30px;
- .notification_card{
- display: flex; justify-content: space-between;
+
+ .notification_card {
+ display: flex;
+ justify-content: space-between;
padding: 20px 20px;
@include Shadow;
border: 2px solid #E9EDF4;
border-radius: 10px;
background: #fff;
cursor: pointer;
- >div{
- display: flex;align-items: center;
+
+ >div {
+ display: flex;
+ align-items: center;
gap: 14px;
- h5{
+
+ h5 {
color: var(--secondary);
}
- img{
+
+ img {
width: 70px;
}
- p{
+
+ p {
margin-top: 12px;
- color: #6A7287;
+ color: var(--value);
}
- .trash_button{
+
+ .trash_button {
visibility: hidden;
}
}
- &:hover{
- .trash_button{
+
+ &:hover {
+ .trash_button {
visibility: visible;
}
}
@@ -55,16 +71,18 @@
}
-.trash_button{
+.trash_button {
background: #E93553;
@include Flex;
color: var(--white);
- padding: 20px 23px ;
+ padding: 20px 23px;
border: none !important;
- svg{
+
+ svg {
font-size: 22px;
}
- &:hover{
+
+ &:hover {
background: #E93553 !important;
color: var(--white) !important;
border: none !important;
diff --git a/src/api/collections.ts b/src/api/collections.ts
new file mode 100644
index 0000000..3546a5c
--- /dev/null
+++ b/src/api/collections.ts
@@ -0,0 +1,10 @@
+import useGetQuery from "./helper/useGetQuery";
+
+const API = {
+ GET: "/collections",
+};
+
+const KEY = "collections";
+
+export const useGetAllSales = (params?: any, options?: any) =>
+ useGetQuery(KEY, API.GET, params, options);
diff --git a/src/api/sales.ts b/src/api/sales.ts
new file mode 100644
index 0000000..fb15fcf
--- /dev/null
+++ b/src/api/sales.ts
@@ -0,0 +1,15 @@
+import useAddMutation from "./helper/useAddMutation";
+import useGetQuery from "./helper/useGetQuery";
+
+const API = {
+ GET: "/sales",
+ ADD: "/sales",
+ DELETE: "/sales",
+ UPDATE: "/sales",
+};
+
+const KEY = "sales";
+
+export const useGetAllSales = (params?: any, options?: any) =>
+ useGetQuery(KEY, API.GET, params, options);
+export const useAddSales = () => useAddMutation(KEY, API.ADD);
\ No newline at end of file
diff --git a/src/enums/Model.ts b/src/enums/Model.ts
index f3f1739..8480f8c 100644
--- a/src/enums/Model.ts
+++ b/src/enums/Model.ts
@@ -206,8 +206,13 @@ export enum ModalEnum {
QUESTION_BANK_DELETE = "QuestionBank.delete",
/// permission
+
PERMISSION_EDIT = "PERMISSION.edit",
PERMISSION_ADD = "PERMISSION.add",
PERMISSION_DELETE = "PERMISSION.delete",
+
+ /// sales
+
+ Sales_ADD = "Sales.add",
}
diff --git a/src/enums/abilities.ts b/src/enums/abilities.ts
index 929b3ea..cac07e7 100644
--- a/src/enums/abilities.ts
+++ b/src/enums/abilities.ts
@@ -52,6 +52,10 @@ export enum ABILITIES_ENUM {
PROFILE = "profile",
PERMISSIONS = "permissions",
MANAGERS = "managers",
+ NOTIFICATIONS_RE_SELLER = "notification_re_seller" ,
+ Profile_RE_SELLER = "profile_re_seller" ,
+ Sales = "sales",
+ Collections = "collections"
////
}
diff --git a/src/faker/item.ts b/src/faker/item.ts
new file mode 100644
index 0000000..bb4990b
--- /dev/null
+++ b/src/faker/item.ts
@@ -0,0 +1,7 @@
+export const CollectionData = [
+ {label:"إجمالي المبيعات",value:"2.000.000"},
+ {label:"نسبة الأرباح (10%)",value:"2.000.000"},
+ {label:"المستحقات",value:"2.000.000"},
+ {label:"تم تحصيله",value:"2.000.000"},
+ {label:"المتبقي",value:"2.000.000"},
+ ]
\ No newline at end of file
diff --git a/src/translate/ar.json b/src/translate/ar.json
index b9b2379..1247b79 100644
--- a/src/translate/ar.json
+++ b/src/translate/ar.json
@@ -140,6 +140,7 @@
"change": "تغيير",
"role_list": "قائمة الأدوار",
"managers":"مدراء",
+ "sales":"المبيعات",
"hide_hint":"اخفاء الشرح",
"show_hint":"عرض الشرح"
},
@@ -282,7 +283,8 @@
"id_photo": "صورة الهوية",
"sorry_something_went_wrong": "عفوا ، حدث خطأ ما",
"error_404_Page_not_found._Sorry,_the_page_you_are_looking_for_does_not_exist": "خطأ 404 لم يتم العثور على الصفحة. عذرا الصفحة التي تبحث عنها غير موجودة ",
- "return_to_the_dashboard": "العودة إلى لوحة القيادة"
+ "return_to_the_dashboard": "العودة إلى لوحة القيادة",
+ "save_changes":"حفظ التغييرات"
},
"Table": {
"header": "",
@@ -359,7 +361,9 @@
"role_details": "تفاصيل الأدوار",
"created_at": "تم إنشاؤه في",
"managers":"مدراء",
- "manager":"مدير"
+ "manager":"مدير",
+ "sale":"عملية بيع",
+ "collections": "التحصيلات"
},
"education_class_actions": {
"Student_Records": "سجلات الطلاب",
@@ -485,7 +489,9 @@
"current_password": "كلمة المرور الحالية",
"created_at": "تم إنشاؤه في",
"empty":"",
- "role":"الدور"
+ "role":"الدور",
+ "submit_password":"تأكيد كلمة المرور",
+ "join_date":"تاريخ الانضمام"
},
"select": {
"enums": {
@@ -818,7 +824,9 @@
"notifications": "الإشعارات",
"profile": "الملف الشخصي",
"users":"المستخدمون",
- "managers":"مدراء"
+ "managers":"مدراء",
+ "sales":"المبيعات",
+ "collections": "التحصيلات"
},
"message": {
"some_thing_went_wrong": "حدث خطأ ما",
@@ -860,7 +868,10 @@
"profile": "الملف الشخصي",
"permissions":"اذونات",
"managers":"مدراء",
- "add_manager":"إضافة مدير"
+ "add_manager":"إضافة مدير",
+ "collections": "التحصيلات",
+ "sales":"المبيعات",
+ "edit_manager":"تعديل مدير"
},
"page_header": {
"home": "لوحة القيادة",
@@ -904,7 +915,9 @@
"profile": "الملف الشخصي",
"user": "مستخدم",
"permissions":"اذونات",
- "managers":"مدراء"
+ "managers":"مدراء",
+ "collections": "التحصيلات",
+ "sales":"المبيعات"
},
"table": {
"student": "قائمة الطلاب",
@@ -913,7 +926,9 @@
"subjects": "مواد الصف",
"QuestionBank": "بنك الأسئلة",
"managers":"مدراء",
- "managers_list":"قائمة المدراء"
+ "managers_list":"قائمة المدراء",
+ "sales":"المبيعات",
+ "collections": "التحصيلات"
},
"alphabet": {
"A": "A",
diff --git a/src/types/Item.ts b/src/types/Item.ts
index fec4221..dbd4a49 100644
--- a/src/types/Item.ts
+++ b/src/types/Item.ts
@@ -354,4 +354,20 @@ type student = {
first_name:string;
last_name:string;
sex:string
-}
\ No newline at end of file
+}
+
+
+export type Sales = {
+ id: number;
+ student: student;
+ expiration_date: string;
+ activation_date: string;
+};
+
+
+export type Collection = {
+ id: number;
+ student: student;
+ expiration_date: string;
+ activation_date: string;
+};
diff --git a/src/utils/hasAbilityFn.ts b/src/utils/hasAbilityFn.ts
index e6de73d..6cc137b 100644
--- a/src/utils/hasAbilityFn.ts
+++ b/src/utils/hasAbilityFn.ts
@@ -719,3 +719,20 @@ export const canShowQuestionBank = hasAbility(
ABILITIES_ENUM.QUESTION_BANK,
ABILITIES_VALUES_ENUM.SHOW,
);
+
+
+/// User
+
+export const canAddSales = hasAbility(
+ ABILITIES_ENUM.Sales,
+ ABILITIES_VALUES_ENUM.STORE,
+);
+
+export const canEditSales = hasAbility(
+ ABILITIES_ENUM.Sales,
+ ABILITIES_VALUES_ENUM.UPDATE,
+);
+export const canDeleteSales = hasAbility(
+ ABILITIES_ENUM.Sales,
+ ABILITIES_VALUES_ENUM.DELETE,
+);