diff --git a/package-lock.json b/package-lock.json index 93f110d..193e19e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,6 +45,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.22", "globals": "^16.4.0", + "prettier": "^3.8.1", "typescript": "~5.9.3", "typescript-eslint": "^8.45.0", "vite": "^7.1.7" @@ -4339,6 +4340,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", diff --git a/package.json b/package.json index 7dc1b98..c2406a6 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.22", "globals": "^16.4.0", + "prettier": "^3.8.1", "typescript": "~5.9.3", "typescript-eslint": "^8.45.0", "vite": "^7.1.7" diff --git a/src/config/Paths.tsx b/src/config/Paths.tsx index 9feaa9b..5ed51ce 100644 --- a/src/config/Paths.tsx +++ b/src/config/Paths.tsx @@ -1,86 +1,91 @@ export const Paths = { - requests: { - list: '/requests', + requests: { + list: '/requests', + }, + product: { + list: '/product/list', + create: '/product/create', + update: '/product/update/', + category: { + create: '/product/category/create', + list: '/product/category/list', + update: '/product/category/update/', }, - product: { - list: '/product/list', - create: '/product/create', - update: '/product/update/', - category: { - create: '/product/category/create', - list: '/product/category/list', - update: '/product/category/update/' - }, - attribute: { - list: '/product/attribute/', - create: '/product/attribute/create/', - update: '/product/attribute/update/' - }, - attributeValue: { - list: '/product/attribute-value/' - } + attribute: { + list: '/product/attribute/', + create: '/product/attribute/create/', + update: '/product/attribute/update/', }, - users: { - list: '/users/list' + attributeValue: { + list: '/product/attribute-value/', }, - formBuilder: { - list: '/form-builder/list/', - create: '/form-builder/create/', - update: '/form-builder/update/', - values: '/form-builder/values/' - }, - order: { - list: '/order/list', - details: '/order/detail/', - create: '/order/create', - edit: '/order/edit/' - }, - features: { - list: '/features/list', - create: '/features/create' - }, - service: { - print: '/service/print' - }, - home: '/home', - myOrders: '/my-orders', - perfomaInvoice: { - list: '/perfoma-invoice/list', - detail: '/perfoma-invoice/' - }, - newOrder: '/new-order', - orderDetails: '/order/', - tickets: { - list: '/tickets', - }, - auth: { - login: '/auth/login', - }, - ticket: { - list: "/tickets/list", - create: "/tickets/create", - detail: "/tickets/messages/", - category: "/tickets/category", - }, - announcement: { - list: "/announcement", - detail: "/announcement/detail/", - create: "/announcement/create", - }, - criticisms: { - list: "/criticisms", - detail: "/criticisms/detail/", - }, - learning: { - list: "/learning/list", - detail: "/learning/detail/", - create: "/learning/create", - category: "/learning/category", - }, - print: { - list: '/print/list', - create: '/print/create', - update: '/print/update/', - form: '/print/form/' - } -} \ No newline at end of file + }, + users: { + list: '/users/list', + }, + admin: { + list: '/admin/list', + create: '/admin/create', + update: '/admin/update/', + }, + formBuilder: { + list: '/form-builder/list/', + create: '/form-builder/create/', + update: '/form-builder/update/', + values: '/form-builder/values/', + }, + order: { + list: '/order/list', + details: '/order/detail/', + create: '/order/create', + edit: '/order/edit/', + }, + features: { + list: '/features/list', + create: '/features/create', + }, + service: { + print: '/service/print', + }, + home: '/home', + myOrders: '/my-orders', + perfomaInvoice: { + list: '/perfoma-invoice/list', + detail: '/perfoma-invoice/', + }, + newOrder: '/new-order', + orderDetails: '/order/', + tickets: { + list: '/tickets', + }, + auth: { + login: '/auth/login', + }, + ticket: { + list: '/tickets/list', + create: '/tickets/create', + detail: '/tickets/messages/', + category: '/tickets/category', + }, + announcement: { + list: '/announcement', + detail: '/announcement/detail/', + create: '/announcement/create', + }, + criticisms: { + list: '/criticisms', + detail: '/criticisms/detail/', + }, + learning: { + list: '/learning/list', + detail: '/learning/detail/', + create: '/learning/create', + category: '/learning/category', + }, + print: { + list: '/print/list', + create: '/print/create', + update: '/print/update/', + form: '/print/form/', + }, +}; diff --git a/src/pages/admin/List.tsx b/src/pages/admin/List.tsx new file mode 100644 index 0000000..48f2c0e --- /dev/null +++ b/src/pages/admin/List.tsx @@ -0,0 +1,58 @@ +import { useState, type FC } from "react"; +import { useGetAdmins } from "./hooks/useAdminData"; +import Table from "@/components/Table"; +import moment from "moment-jalaali"; + +const AdminList: FC = () => { + + const [page, setPage] = useState(1); + const { data } = useGetAdmins(page); + + return ( +
+
+

مدیران

+
+ + { + return
{item.firstName + " " + item.lastName}
; + }, + }, + { + key: "phone", + title: "موبایل", + }, + { + key: "role", + title: "نقش", + render: (item) => { + return
{item.role.title || item.role.name}
; + }, + }, + { + key: "createdAt", + title: "تاریخ ثبت", + render: (item) => { + return ( +
{moment(item.createdAt).format("jYYYY-jMM-jDD")}
+ ); + }, + }, + ]} + data={data?.data} + pagination={{ + currentPage: page, + onPageChange: setPage, + totalPages: data?.meta?.totalPages as number, + }} + /> + + ); +}; + +export default AdminList; diff --git a/src/pages/admin/hooks/useAdminData.ts b/src/pages/admin/hooks/useAdminData.ts new file mode 100644 index 0000000..41fe7dd --- /dev/null +++ b/src/pages/admin/hooks/useAdminData.ts @@ -0,0 +1,9 @@ +import * as api from "../service/AdminService"; +import { useQuery } from "@tanstack/react-query"; + +export const useGetAdmins = (page: number) => { + return useQuery({ + queryKey: ["admins", page], + queryFn: () => api.getAdmins(page), + }); +}; diff --git a/src/pages/admin/service/AdminService.ts b/src/pages/admin/service/AdminService.ts new file mode 100644 index 0000000..a400f4a --- /dev/null +++ b/src/pages/admin/service/AdminService.ts @@ -0,0 +1,9 @@ +import axios from "@/config/axios"; +import type { AdminsType } from "../types/Types"; + +export const getAdmins = async (page: number) => { + const { data } = await axios.get("/admin/admins", { + params: { page }, + }); + return data; +}; diff --git a/src/pages/admin/types/Types.ts b/src/pages/admin/types/Types.ts new file mode 100644 index 0000000..b7eedee --- /dev/null +++ b/src/pages/admin/types/Types.ts @@ -0,0 +1,21 @@ +import type { RowDataType } from "@/components/types/TableTypes"; +import type { BaseResponse } from "@/shared/types/Types"; + +export interface AdminItemType extends RowDataType { + id: string; + createdAt: string; + deletedAt: string | null; + firstName: string; + lastName: string; + role: { + id: string; + createdAt: string; + deletedAt: string | null; + name: string; + title: string; + isSystem: boolean; + }; + phone: string; +} + +export type AdminsType = BaseResponse; diff --git a/src/router/MainRouter.tsx b/src/router/MainRouter.tsx index 57a844f..c9f8371 100644 --- a/src/router/MainRouter.tsx +++ b/src/router/MainRouter.tsx @@ -45,6 +45,7 @@ import CreateSection from '@/pages/print/Create' import UpdateSection from '@/pages/print/Update' import PrintForm from '@/pages/print/Form' import UsersList from '@/pages/user/List' +import AdminList from '@/pages/admin/List' const MainRouter: FC = () => { return ( @@ -90,6 +91,8 @@ const MainRouter: FC = () => { } /> + } /> + } /> } /> } /> diff --git a/src/shared/Sidebar.tsx b/src/shared/Sidebar.tsx index 0cdc71e..a47bcdd 100644 --- a/src/shared/Sidebar.tsx +++ b/src/shared/Sidebar.tsx @@ -1,158 +1,172 @@ -import { type FC } from 'react' -import LogoImage from '@/assets/images/logo.svg' -import { AddSquare, DocumentText, Element3, ElementEqual, Home2, Messages3, MessageText, NotificationStatus, People, Printer, Profile2User, Receipt21, Teacher } from 'iconsax-react' -import SideBarItem from './SidebarItem' -import { useLocation } from 'react-router-dom' -import { Paths } from '../config/Paths' -import { useSharedStore } from './store/useSharedStore' -import { clx } from '../helpers/utils' -import { t } from '../locale' -import Button from '@/components/Button' +import { type FC } from 'react'; +import LogoImage from '@/assets/images/logo.svg'; +import { + AddSquare, + DocumentText, + Element3, + ElementEqual, + Home2, + Messages3, + MessageText, + NotificationStatus, + People, + Printer, + Profile2User, + Receipt21, + Teacher, + User, +} from 'iconsax-react'; +import SideBarItem from './SidebarItem'; +import { useLocation } from 'react-router-dom'; +import { Paths } from '../config/Paths'; +import { useSharedStore } from './store/useSharedStore'; +import { clx } from '../helpers/utils'; +import { t } from '../locale'; +import Button from '@/components/Button'; const SideBar: FC = () => { + const { openSidebar, setOpenSidebar } = useSharedStore(); + const location = useLocation(); - const { openSidebar, setOpenSidebar } = useSharedStore() - const location = useLocation() + const isActive = (name: string) => { + return location.pathname.includes(name); + }; - const isActive = (name: string) => { - return location.pathname.includes(name) - } + const iconSizeSideBar = 20; - const iconSizeSideBar = 20 + return ( + <> + {openSidebar && ( +
setOpenSidebar(false)} + /> + )} +
+
+
+ +
+
- return ( - <> - { - openSidebar &&
setOpenSidebar(false)} /> - } -
-
-
- -
+
+
{t('sidebar.menu')}
+ +
+ } + title={t('sidebar.mainPage')} + isActive={isActive('/home')} + link={Paths.home} + /> + + } + title={'درخواست ها'} + isActive={isActive('requests')} + link={Paths.requests.list} + /> + + } + title={'سفارشات'} + isActive={isActive('order')} + link={Paths.order.list} + /> + + } + title={'پیش فاکتور'} + isActive={isActive('/proforma-invoice')} + link={Paths.perfomaInvoice.list} + /> + + } + title={'محصولات'} + isActive={isActive('product')} + link={Paths.product.list} + /> + + } + title={'مشتریان'} + isActive={isActive('customer')} + link={Paths.users.list} + /> + + } + title={'چاپ'} + isActive={isActive('print')} + link={Paths.print.list} + /> + + } + title={'ادمین'} + isActive={isActive('admin')} + link={Paths.admin.list} + /> +
+ +
{t('sidebar.other')}
+ +
+ } + title={'کاربران'} + isActive={isActive('/tickets')} + link={Paths.tickets.list} + /> + + } + title={t('sidebar.tickets')} + isActive={isActive('/tickets')} + link={Paths.tickets.list} + /> + + } + title={t('sidebar.announcement')} + isActive={isActive('/announcement')} + link={Paths.announcement.list} + /> + + } + title={t('sidebar.criticisms')} + isActive={isActive('/criticisms')} + link={Paths.criticisms.list} + /> + + } + title={t('sidebar.learning')} + isActive={isActive('/learning')} + link={Paths.learning.list} + /> +
+ +
+
+
{t('sidebar.submitYourOrder')}
+
{t('sidebar.submitYourOrderDescription')}
+ +
-
-
- {t('sidebar.menu')} -
- -
- } - title={t('sidebar.mainPage')} - isActive={isActive('/home')} - link={Paths.home} - /> - - } - title={'درخواست ها'} - isActive={isActive('requests')} - link={Paths.requests.list} - /> - - } - title={'سفارشات'} - isActive={isActive('order')} - link={Paths.order.list} - /> - - } - title={'پیش فاکتور'} - isActive={isActive('/proforma-invoice')} - link={Paths.perfomaInvoice.list} - /> - - } - title={'محصولات'} - isActive={isActive('product')} - link={Paths.product.list} - /> - - } - title={'مشتریان'} - isActive={isActive('customer')} - link={Paths.users.list} - /> - - } - title={'چاپ'} - isActive={isActive('print')} - link={Paths.print.list} - /> - -
- -
- {t('sidebar.other')} -
- -
- - } - title={'کاربران'} - isActive={isActive('/tickets')} - link={Paths.tickets.list} - /> - - } - title={t('sidebar.tickets')} - isActive={isActive('/tickets')} - link={Paths.tickets.list} - /> - - } - title={t('sidebar.announcement')} - isActive={isActive('/announcement')} - link={Paths.announcement.list} - /> - - } - title={t('sidebar.criticisms')} - isActive={isActive('/criticisms')} - link={Paths.criticisms.list} - /> - - } - title={t('sidebar.learning')} - isActive={isActive('/learning')} - link={Paths.learning.list} - /> -
- - -
- -
-
{t('sidebar.submitYourOrder')}
-
{t('sidebar.submitYourOrderDescription')}
- -
- - {/*
+ {/*
} title={t('sidebar.logout')} @@ -161,11 +175,11 @@ const SideBar: FC = () => { isLogout />
*/} -
-
-
- - ) -} +
+
+
+ + ); +}; -export default SideBar \ No newline at end of file +export default SideBar;