diff --git a/src/config/Pages.ts b/src/config/Pages.ts
index 96fa881..6b80049 100644
--- a/src/config/Pages.ts
+++ b/src/config/Pages.ts
@@ -56,4 +56,8 @@ export const Pages = {
add: "/roles/add",
update: "/roles/update/",
},
+ admins: {
+ list: "/admins/list",
+ update: "/admins/update/",
+ },
};
diff --git a/src/langs/fa.json b/src/langs/fa.json
index b983ea5..5227222 100644
--- a/src/langs/fa.json
+++ b/src/langs/fa.json
@@ -62,7 +62,8 @@
"setting": "تنظیمات",
"logout": "خروج",
"roles": "سطح دسترسی ها",
- "payment_methods": "روش های پرداخت"
+ "payment_methods": "روش های پرداخت",
+ "admins": "مدیران"
},
"slider": {
"new_slider": "اسلایدر جدید",
diff --git a/src/pages/admin/List.tsx b/src/pages/admin/List.tsx
new file mode 100644
index 0000000..4bfaecd
--- /dev/null
+++ b/src/pages/admin/List.tsx
@@ -0,0 +1,60 @@
+import { type FC } from 'react'
+import Table from '@/components/Table'
+import Filters from '@/components/Filters'
+import { useGetAdmins, useDeleteAdmin } from './hooks/useAdminData'
+import { useAdminFilters } from './hooks/useAdminFilters'
+import { getAdminTableColumns } from './components/AdminTableColumns'
+import { useAdminFiltersFields } from './components/AdminFiltersFields'
+
+const AdminList: FC = () => {
+ const {
+ filters,
+ currentPage,
+ apiParams,
+ handleFiltersChange,
+ handlePageChange,
+ limit,
+ } = useAdminFilters()
+
+ const { data: adminsData, isLoading } = useGetAdmins(apiParams)
+ const { mutate: deleteAdmin, isPending: isDeleting } = useDeleteAdmin()
+
+ const admins = adminsData?.data || []
+ const columns = getAdminTableColumns({
+ onDelete: (id: string) => deleteAdmin(id),
+ isDeleting
+ })
+ const filterFields = useAdminFiltersFields()
+
+ const totalPages = Math.ceil(admins.length / limit) || 1
+
+ return (
+
+
+
لیست مدیران
+
+
+
+
+
+
+
+
+ )
+}
+
+export default AdminList
\ No newline at end of file
diff --git a/src/pages/admin/components/AdminFiltersFields.tsx b/src/pages/admin/components/AdminFiltersFields.tsx
new file mode 100644
index 0000000..ad0dd94
--- /dev/null
+++ b/src/pages/admin/components/AdminFiltersFields.tsx
@@ -0,0 +1,13 @@
+import { useMemo } from 'react'
+import type { FieldType } from '@/components/Filters'
+
+export const useAdminFiltersFields = (): FieldType[] => {
+ return useMemo(() => [
+ {
+ type: 'input',
+ name: 'search',
+ placeholder: 'جستجو',
+ },
+ ], [])
+}
+
diff --git a/src/pages/admin/components/AdminTableColumns.tsx b/src/pages/admin/components/AdminTableColumns.tsx
new file mode 100644
index 0000000..81b9676
--- /dev/null
+++ b/src/pages/admin/components/AdminTableColumns.tsx
@@ -0,0 +1,75 @@
+import type { ColumnType } from '@/components/types/TableTypes'
+import type { Admin } from '../types/Types'
+import TrashWithConfrim from '@/components/TrashWithConfrim'
+import { Eye } from 'iconsax-react'
+import { Link } from 'react-router-dom'
+import { Pages } from '@/config/Pages'
+
+interface GetAdminTableColumnsParams {
+ onDelete?: (id: string) => void
+ isDeleting?: boolean
+}
+
+export const getAdminTableColumns = ({ onDelete, isDeleting }: GetAdminTableColumnsParams = {}): ColumnType[] => {
+ return [
+ {
+ key: 'firstName',
+ title: 'نام',
+ render: (item: Admin) => {
+ return item.firstName || '-'
+ }
+ },
+ {
+ key: 'lastName',
+ title: 'نام خانوادگی',
+ render: (item: Admin) => {
+ return item.lastName || '-'
+ }
+ },
+ {
+ key: 'phone',
+ title: 'شماره تماس',
+ render: (item: Admin) => {
+ return item.phone || '-'
+ }
+ },
+ {
+ key: 'roles',
+ title: 'تعداد نقشها',
+ render: (item: Admin) => {
+ return item.roles?.length || 0
+ }
+ },
+ {
+ key: 'createdAt',
+ title: 'تاریخ ایجاد',
+ render: (item: Admin) => {
+ return new Date(item.createdAt).toLocaleDateString('fa-IR')
+ }
+ },
+ {
+ key: 'actions',
+ title: '',
+ render: (item: Admin) => {
+ return (
+
+
+
+
+ {onDelete && (
+ onDelete(item.id)}
+ isloading={isDeleting}
+ />
+ )}
+
+ )
+ }
+ },
+ ]
+}
+
diff --git a/src/pages/admin/hooks/useAdminData.ts b/src/pages/admin/hooks/useAdminData.ts
new file mode 100644
index 0000000..702c08e
--- /dev/null
+++ b/src/pages/admin/hooks/useAdminData.ts
@@ -0,0 +1,22 @@
+import * as api from "../service/AdminService";
+import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
+import type { GetAdminsParams } from "../types/Types";
+
+export const useGetAdmins = (params?: GetAdminsParams) => {
+ return useQuery({
+ queryKey: ["admins", params],
+ queryFn: () => api.getAdmins(params),
+ });
+};
+
+export const useDeleteAdmin = () => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: api.deleteAdmin,
+ onSuccess: () => {
+ queryClient.invalidateQueries({
+ queryKey: ["admins"],
+ });
+ },
+ });
+};
diff --git a/src/pages/admin/hooks/useAdminFilters.ts b/src/pages/admin/hooks/useAdminFilters.ts
new file mode 100644
index 0000000..e6c2b5a
--- /dev/null
+++ b/src/pages/admin/hooks/useAdminFilters.ts
@@ -0,0 +1,44 @@
+import { useState, useMemo } from 'react'
+import type { FilterValues } from '@/components/Filters'
+import type { GetAdminsParams } from '../types/Types'
+
+const DEFAULT_PAGE = 1
+const DEFAULT_LIMIT = 10
+
+export const useAdminFilters = () => {
+ const [filters, setFilters] = useState({})
+ const [currentPage, setCurrentPage] = useState(DEFAULT_PAGE)
+ const [limit] = useState(DEFAULT_LIMIT)
+
+ const apiParams = useMemo(() => {
+ const params: GetAdminsParams = {
+ page: currentPage,
+ limit: limit,
+ }
+
+ if (filters.search) {
+ params.search = filters.search
+ }
+
+ return params
+ }, [filters, currentPage, limit])
+
+ const handleFiltersChange = (newFilters: FilterValues) => {
+ setFilters(newFilters)
+ setCurrentPage(DEFAULT_PAGE)
+ }
+
+ const handlePageChange = (page: number) => {
+ setCurrentPage(page)
+ }
+
+ return {
+ filters,
+ currentPage,
+ apiParams,
+ handleFiltersChange,
+ handlePageChange,
+ limit,
+ }
+}
+
diff --git a/src/pages/admin/service/AdminService.ts b/src/pages/admin/service/AdminService.ts
new file mode 100644
index 0000000..6e73cf1
--- /dev/null
+++ b/src/pages/admin/service/AdminService.ts
@@ -0,0 +1,16 @@
+import axios from "@/config/axios";
+import type { GetAdminsResponse, GetAdminsParams } from "../types/Types";
+
+export const getAdmins = async (
+ params?: GetAdminsParams
+): Promise => {
+ const { data } = await axios.get("/admin/admins", {
+ params,
+ });
+ return data;
+};
+
+export const deleteAdmin = async (id: string) => {
+ const { data } = await axios.delete(`/admin/admins/${id}`);
+ return data;
+};
diff --git a/src/pages/admin/types/Types.ts b/src/pages/admin/types/Types.ts
new file mode 100644
index 0000000..5ba7e98
--- /dev/null
+++ b/src/pages/admin/types/Types.ts
@@ -0,0 +1,40 @@
+import type { IResponse } from "@/types/response.types";
+
+export type RoleDetail = {
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ deletedAt: string | null;
+ name: string;
+ restaurant: string | null;
+};
+
+export type AdminRole = {
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ deletedAt: string | null;
+ admin: string;
+ role: RoleDetail;
+ restaurant: string;
+};
+
+export type Admin = {
+ id: string;
+ createdAt: string;
+ updatedAt: string;
+ deletedAt: string | null;
+ firstName: string;
+ lastName: string;
+ phone: string;
+ roles: AdminRole[];
+};
+
+export type GetAdminsParams = {
+ page?: number
+ limit?: number
+ search?: string
+}
+
+export type GetAdminsResponse = IResponse;
+
diff --git a/src/router/Main.tsx b/src/router/Main.tsx
index 609aa03..44a6086 100644
--- a/src/router/Main.tsx
+++ b/src/router/Main.tsx
@@ -27,6 +27,7 @@ import Setting from '@/pages/settings/Setting'
import PaymentMethodsList from '@/pages/paymentMethods/List'
import CreatePaymentMethod from '@/pages/paymentMethods/Create'
import UpdatePaymentMethod from '@/pages/paymentMethods/Update'
+import AdminList from '@/pages/admin/List'
const MainRouter: FC = () => {
const { hasSubMenu } = useSharedStore()
@@ -66,6 +67,8 @@ const MainRouter: FC = () => {
} />
} />
} />
+
+ } />
diff --git a/src/shared/SideBar.tsx b/src/shared/SideBar.tsx
index 1df712d..736a2e4 100644
--- a/src/shared/SideBar.tsx
+++ b/src/shared/SideBar.tsx
@@ -2,7 +2,7 @@ import { type FC, useEffect } from 'react'
import LogoImage from '../assets/images/logo.svg'
import LogoSmall from '../assets/images/logo-small.svg'
import { useTranslation } from 'react-i18next'
-import { DocumentText, Home2, Logout, Message, NotificationStatus, People, Setting2, TicketDiscount, Chart, Calendar, Security, Card } from 'iconsax-react'
+import { DocumentText, Home2, Logout, Message, NotificationStatus, People, Setting2, TicketDiscount, Chart, Calendar, Security, Card, SecurityUser } from 'iconsax-react'
import SideBarItem from './SideBarItem'
import { useLocation } from 'react-router-dom'
import { Pages } from '../config/Pages'
@@ -110,6 +110,16 @@ const SideBar: FC = () => {
name='customers'
activeName='customers'
/>
+
+ }
+ title={t('sidebar.admins')}
+ isActive={isActive('admins')}
+ link={Pages.admins.list}
+ name='admins'
+ activeName='admins'
+ />
+
}
title={t('sidebar.discount')}