list and create admin
This commit is contained in:
@@ -0,0 +1,145 @@
|
|||||||
|
import { useFormik } from 'formik'
|
||||||
|
import { type FC } from 'react'
|
||||||
|
import { useGetPermissions, useCreateAdmin } from './hooks/useAdminData'
|
||||||
|
import type { CreateAdminType } from './types/Types'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import Input from '../../components/Input'
|
||||||
|
import MultiSelectSearchable from '../../components/MultiSelectSearchable'
|
||||||
|
import Button from '../../components/Button'
|
||||||
|
import { TickCircle } from 'iconsax-react'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { extractErrorMessage } from '@/helpers/utils'
|
||||||
|
import { Pages } from '../../config/Pages'
|
||||||
|
|
||||||
|
const Create: FC = () => {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const { data: permissionsData } = useGetPermissions()
|
||||||
|
const createAdminMutation = useCreateAdmin()
|
||||||
|
|
||||||
|
const formik = useFormik<CreateAdminType>({
|
||||||
|
initialValues: {
|
||||||
|
fullName: "",
|
||||||
|
userName: "",
|
||||||
|
email: "",
|
||||||
|
phoneNumber: "",
|
||||||
|
permissions: [],
|
||||||
|
password: "",
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
fullName: Yup.string().required("نام کامل الزامی است"),
|
||||||
|
userName: Yup.string().required("نام کاربری الزامی است"),
|
||||||
|
email: Yup.string().email("ایمیل معتبر نیست").required("ایمیل الزامی است"),
|
||||||
|
phoneNumber: Yup.string().required("شماره تلفن الزامی است"),
|
||||||
|
permissions: Yup.array().min(1, "دسترسی های الزامی است").required("دسترسی های الزامی است"),
|
||||||
|
password: Yup.string().min(6, "رمز عبور باید حداقل ۶ کاراکتر باشد").required("رمز عبور الزامی است"),
|
||||||
|
}),
|
||||||
|
onSubmit: async (values) => {
|
||||||
|
createAdminMutation.mutate(values, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success('ادمین با موفقیت ایجاد شد')
|
||||||
|
navigate(Pages.admin.list)
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const permissionsOptions = permissionsData?.results?.permissions?.map((permission) => ({
|
||||||
|
value: permission._id,
|
||||||
|
label: permission.name
|
||||||
|
})) || []
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-4'>
|
||||||
|
<div className='flex justify-between items-center'>
|
||||||
|
<div className='flex items-center gap-3'>
|
||||||
|
<h1>ساخت ادمین جدید</h1>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
className='px-6'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={createAdminMutation.isPending}
|
||||||
|
disabled={!formik.isValid || createAdminMutation.isPending}
|
||||||
|
>
|
||||||
|
<div className='flex gap-2 items-center'>
|
||||||
|
<TickCircle size={16} color='#fff' />
|
||||||
|
<div>ثبت ادمین</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex gap-6 xl:mt-8 mt-6'>
|
||||||
|
{/* اطلاعات اصلی */}
|
||||||
|
<div className='flex-1 text-sm bg-white py-8 xl:px-10 px-6 rounded-3xl'>
|
||||||
|
<h2 className='text-lg font-medium mb-6'>اطلاعات اصلی</h2>
|
||||||
|
|
||||||
|
<div className='space-y-6'>
|
||||||
|
<div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
|
||||||
|
<Input
|
||||||
|
label='نام کامل'
|
||||||
|
placeholder='مثال: علی احمدی'
|
||||||
|
{...formik.getFieldProps('fullName')}
|
||||||
|
error_text={formik.touched.fullName && formik.errors.fullName ? formik.errors.fullName : ''}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label='نام کاربری'
|
||||||
|
placeholder='مثال: ali_ahmadi'
|
||||||
|
{...formik.getFieldProps('userName')}
|
||||||
|
error_text={formik.touched.userName && formik.errors.userName ? formik.errors.userName : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
|
||||||
|
<Input
|
||||||
|
label='ایمیل'
|
||||||
|
placeholder='مثال: ali@example.com'
|
||||||
|
type='email'
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
error_text={formik.touched.email && formik.errors.email ? formik.errors.email : ''}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label='شماره تلفن'
|
||||||
|
placeholder='مثال: ۰۹۱۲۳۴۵۶۷۸۹'
|
||||||
|
{...formik.getFieldProps('phoneNumber')}
|
||||||
|
error_text={formik.touched.phoneNumber && formik.errors.phoneNumber ? formik.errors.phoneNumber : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label='رمز عبور'
|
||||||
|
placeholder='رمز عبور را وارد کنید'
|
||||||
|
type='password'
|
||||||
|
{...formik.getFieldProps('password')}
|
||||||
|
error_text={formik.touched.password && formik.errors.password ? formik.errors.password : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* دسترسیها */}
|
||||||
|
<div className='w-80 space-y-6'>
|
||||||
|
<div className='text-sm bg-white py-8 px-6 rounded-3xl'>
|
||||||
|
<h2 className='text-lg font-medium mb-6'>دسترسیها</h2>
|
||||||
|
|
||||||
|
<div className='space-y-6'>
|
||||||
|
<MultiSelectSearchable
|
||||||
|
label='دسترسیهای ادمین'
|
||||||
|
placeholder='انتخاب دسترسیها'
|
||||||
|
options={permissionsOptions}
|
||||||
|
value={formik.values.permissions}
|
||||||
|
onChange={(value) => formik.setFieldValue('permissions', value)}
|
||||||
|
error_text={formik.touched.permissions && formik.errors.permissions ? String(formik.errors.permissions) : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Create
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
import { type FC, useState } from 'react'
|
||||||
|
import { useDeleteAdmin, useGetAdmins } from './hooks/useAdminData'
|
||||||
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
|
import { type Admin } from './types/Types'
|
||||||
|
import PageLoading from '../../components/PageLoading'
|
||||||
|
import Error from '../../components/Error'
|
||||||
|
import PaginationUi from '../../components/PaginationUi'
|
||||||
|
import Td from '../../components/Td'
|
||||||
|
import { Calendar, Call, Card, User as UserIcon } from 'iconsax-react'
|
||||||
|
import Button from '@/components/Button'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { Pages } from '@/config/Pages'
|
||||||
|
import TrashWithConfrim from '../../components/TrashWithConfrim'
|
||||||
|
|
||||||
|
const List: FC = () => {
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const { data: adminsData, isLoading, error } = useGetAdmins(currentPage);
|
||||||
|
const deleteAdminMutation = useDeleteAdmin();
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<PageLoading />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<Error errorText="خطا در بارگذاری ادمینها" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const admins = adminsData?.results?.admins || [];
|
||||||
|
const pager = adminsData?.results?.pager;
|
||||||
|
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
if (!dateString) return '-';
|
||||||
|
return new Date(dateString).toLocaleDateString('fa-IR');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='flex justify-end mt-5'>
|
||||||
|
<Button
|
||||||
|
label='افزودن ادمین'
|
||||||
|
onClick={() => navigate(`${Pages.admin.create}`)}
|
||||||
|
className='w-fit'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative overflow-x-auto rounded-3xl mt-5 w-full'>
|
||||||
|
<table className='w-full text-sm'>
|
||||||
|
<thead className='thead'>
|
||||||
|
<tr>
|
||||||
|
<Td text={'نام و نام خانوادگی'} />
|
||||||
|
<Td text={'نام کاربری'} />
|
||||||
|
<Td text={'ایمیل'} />
|
||||||
|
<Td text={'شماره تلفن'} />
|
||||||
|
<Td text={'نقش'} />
|
||||||
|
<Td text={'تاریخ ایجاد'} />
|
||||||
|
<Td text={'عملیات'} />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{admins.length === 0 ? (
|
||||||
|
<tr className='tr'>
|
||||||
|
<td colSpan={7} className="text-center py-8 text-gray-500">
|
||||||
|
هیچ ادمینی یافت نشد
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
admins.map((admin: Admin) => (
|
||||||
|
<tr key={admin._id} className='tr'>
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<UserIcon size={16} color="#8C90A3" />
|
||||||
|
<span>{admin.fullName || '-'}</span>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
<Td text={admin.userName} />
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Card size={16} color="#8C90A3" />
|
||||||
|
<span>{admin.email}</span>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Call size={16} color="#8C90A3" />
|
||||||
|
<span>{admin.phoneNumber}</span>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
<Td text={admin.role?.name || '-'} />
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Calendar size={16} color="#8C90A3" />
|
||||||
|
<span>{formatDate(admin.createdAt)}</span>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
|
||||||
|
<TrashWithConfrim
|
||||||
|
onDelete={() => {
|
||||||
|
deleteAdminMutation.mutate(admin._id, {
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['admins'] })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PaginationUi
|
||||||
|
pager={pager}
|
||||||
|
onPageChange={(page) => {
|
||||||
|
setCurrentPage(page);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default List
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
import { useFormik } from 'formik'
|
||||||
|
import { type FC, useEffect } from 'react'
|
||||||
|
import { useParams } from 'react-router-dom'
|
||||||
|
import { useGetPermissions, useGetAdminDetail, useUpdateAdmin } from './hooks/useAdminData'
|
||||||
|
import type { UpdateAdminType } from './types/Types'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import Input from '../../components/Input'
|
||||||
|
import MultiSelectSearchable from '../../components/MultiSelectSearchable'
|
||||||
|
import Button from '../../components/Button'
|
||||||
|
import { TickCircle } from 'iconsax-react'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { extractErrorMessage } from '@/helpers/utils'
|
||||||
|
import { Pages } from '../../config/Pages'
|
||||||
|
|
||||||
|
const Update: FC = () => {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const { id } = useParams<{ id: string }>()
|
||||||
|
const { data: permissionsData } = useGetPermissions()
|
||||||
|
const { data: adminDetail, isLoading: adminDetailLoading, error: adminDetailError } = useGetAdminDetail(id!)
|
||||||
|
const updateAdminMutation = useUpdateAdmin()
|
||||||
|
|
||||||
|
const formik = useFormik<UpdateAdminType>({
|
||||||
|
initialValues: {
|
||||||
|
fullName: "",
|
||||||
|
userName: "",
|
||||||
|
email: "",
|
||||||
|
phoneNumber: "",
|
||||||
|
permissions: [],
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
fullName: Yup.string().required("نام کامل الزامی است"),
|
||||||
|
userName: Yup.string().required("نام کاربری الزامی است"),
|
||||||
|
email: Yup.string().email("ایمیل معتبر نیست").required("ایمیل الزامی است"),
|
||||||
|
phoneNumber: Yup.string().required("شماره تلفن الزامی است"),
|
||||||
|
permissions: Yup.array().min(1, "دسترسی های الزامی است").required("دسترسی های الزامی است"),
|
||||||
|
}),
|
||||||
|
onSubmit: async (values) => {
|
||||||
|
updateAdminMutation.mutate({ id: id!, ...values }, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success('ادمین با موفقیت ویرایش شد')
|
||||||
|
navigate(Pages.admin.list)
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (adminDetail) {
|
||||||
|
formik.setValues({
|
||||||
|
fullName: adminDetail.results.admin.fullName,
|
||||||
|
userName: adminDetail.results.admin.userName,
|
||||||
|
email: adminDetail.results.admin.email,
|
||||||
|
phoneNumber: adminDetail.results.admin.phoneNumber,
|
||||||
|
permissions: adminDetail.results.admin.permissions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [adminDetail])
|
||||||
|
|
||||||
|
const permissionsOptions = permissionsData?.results?.permissions?.map((permission) => ({
|
||||||
|
value: permission._id,
|
||||||
|
label: permission.name
|
||||||
|
})) || []
|
||||||
|
|
||||||
|
if (adminDetailLoading) {
|
||||||
|
return <div>در حال بارگذاری...</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adminDetailError) {
|
||||||
|
return <div>خطا در بارگذاری دادهها</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-4'>
|
||||||
|
<div className='flex justify-between items-center'>
|
||||||
|
<div className='flex items-center gap-3'>
|
||||||
|
<h1>ویرایش ادمین</h1>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
className='px-6'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={updateAdminMutation.isPending}
|
||||||
|
disabled={!formik.isValid || updateAdminMutation.isPending}
|
||||||
|
>
|
||||||
|
<div className='flex gap-2 items-center'>
|
||||||
|
<TickCircle size={16} color='#fff' />
|
||||||
|
<div>ویرایش ادمین</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex gap-6 xl:mt-8 mt-6'>
|
||||||
|
{/* اطلاعات اصلی */}
|
||||||
|
<div className='flex-1 text-sm bg-white py-8 xl:px-10 px-6 rounded-3xl'>
|
||||||
|
<h2 className='text-lg font-medium mb-6'>اطلاعات اصلی</h2>
|
||||||
|
|
||||||
|
<div className='space-y-6'>
|
||||||
|
<div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
|
||||||
|
<Input
|
||||||
|
label='نام کامل'
|
||||||
|
placeholder='مثال: علی احمدی'
|
||||||
|
{...formik.getFieldProps('fullName')}
|
||||||
|
error_text={formik.touched.fullName && formik.errors.fullName ? formik.errors.fullName : ''}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label='نام کاربری'
|
||||||
|
placeholder='مثال: ali_ahmadi'
|
||||||
|
{...formik.getFieldProps('userName')}
|
||||||
|
error_text={formik.touched.userName && formik.errors.userName ? formik.errors.userName : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
|
||||||
|
<Input
|
||||||
|
label='ایمیل'
|
||||||
|
placeholder='مثال: ali@example.com'
|
||||||
|
type='email'
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
error_text={formik.touched.email && formik.errors.email ? formik.errors.email : ''}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label='شماره تلفن'
|
||||||
|
placeholder='مثال: ۰۹۱۲۳۴۵۶۷۸۹'
|
||||||
|
{...formik.getFieldProps('phoneNumber')}
|
||||||
|
error_text={formik.touched.phoneNumber && formik.errors.phoneNumber ? formik.errors.phoneNumber : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* دسترسیها */}
|
||||||
|
<div className='w-80 space-y-6'>
|
||||||
|
<div className='text-sm bg-white py-8 px-6 rounded-3xl'>
|
||||||
|
<h2 className='text-lg font-medium mb-6'>دسترسیها</h2>
|
||||||
|
|
||||||
|
<div className='space-y-6'>
|
||||||
|
<MultiSelectSearchable
|
||||||
|
label='دسترسیهای ادمین'
|
||||||
|
placeholder='انتخاب دسترسیها'
|
||||||
|
options={permissionsOptions}
|
||||||
|
value={formik.values.permissions}
|
||||||
|
onChange={(value) => formik.setFieldValue('permissions', value)}
|
||||||
|
error_text={formik.touched.permissions && formik.errors.permissions ? String(formik.errors.permissions) : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Update
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import * as api from "../service/AdminService";
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
export const useGetAdmins = (page: number = 1, limit: number = 10) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["admins", page, limit],
|
||||||
|
queryFn: () => api.getAdmins(page, limit),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetPermissions = () => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["permissions"],
|
||||||
|
queryFn: () => api.getPermissions(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCreateAdmin = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.createAdmin,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDeleteAdmin = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.deleteAdmin,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetAdminDetail = (id: string) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["admin", id],
|
||||||
|
queryFn: () => api.getAdminDetail(id),
|
||||||
|
enabled: !!id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateAdmin = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.updateAdmin,
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import axios from "../../../config/axios";
|
||||||
|
import type {
|
||||||
|
GetPermissionsResponse,
|
||||||
|
CreateAdminType,
|
||||||
|
UpdateAdminType,
|
||||||
|
GetAdminsResponse,
|
||||||
|
Admin,
|
||||||
|
} from "../types/Types";
|
||||||
|
|
||||||
|
export const getAdmins = async (
|
||||||
|
page: number = 1,
|
||||||
|
limit: number = 10
|
||||||
|
): Promise<GetAdminsResponse> => {
|
||||||
|
const { data } = await axios.get(`/admin/admins`, {
|
||||||
|
params: { page, limit },
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPermissions = async (): Promise<GetPermissionsResponse> => {
|
||||||
|
const { data } = await axios.get(`/admin/permissions`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createAdmin = async (admin: CreateAdminType) => {
|
||||||
|
const { data } = await axios.post(`/admin/create`, admin);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteAdmin = async (id: string) => {
|
||||||
|
const { data } = await axios.delete(`/admin/${id}/delete`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAdminDetail = async (
|
||||||
|
id: string
|
||||||
|
): Promise<{ status: number; success: boolean; results: { admin: Admin } }> => {
|
||||||
|
const { data } = await axios.get(`/admin/${id}`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateAdmin = async ({
|
||||||
|
id,
|
||||||
|
...admin
|
||||||
|
}: { id: string } & UpdateAdminType) => {
|
||||||
|
const { data } = await axios.put(`/admin/${id}/update`, admin);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
export interface Permission {
|
||||||
|
_id: string;
|
||||||
|
name: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetPermissionsResponse {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
permissions: Permission[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CreateAdminType = {
|
||||||
|
fullName: string;
|
||||||
|
userName: string;
|
||||||
|
email: string;
|
||||||
|
phoneNumber: string;
|
||||||
|
permissions: string[];
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UpdateAdminType = {
|
||||||
|
fullName: string;
|
||||||
|
userName: string;
|
||||||
|
email: string;
|
||||||
|
phoneNumber: string;
|
||||||
|
permissions: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface AdminRole {
|
||||||
|
_id: string;
|
||||||
|
name: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreatedBy {
|
||||||
|
_id: string;
|
||||||
|
fullName: string;
|
||||||
|
userName: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Admin {
|
||||||
|
_id: string;
|
||||||
|
fullName: string;
|
||||||
|
userName: string;
|
||||||
|
email: string;
|
||||||
|
phoneNumber: string;
|
||||||
|
role: AdminRole;
|
||||||
|
createdBy: CreatedBy;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
permissions: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Pager {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
totalItems: number;
|
||||||
|
totalPages: number;
|
||||||
|
prevPage: boolean;
|
||||||
|
nextPage: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetAdminsResponse {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
admins: Admin[];
|
||||||
|
pager: Pager;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -33,6 +33,8 @@ import CouponList from '@/pages/Coupon/List'
|
|||||||
import CreateCoupon from '@/pages/Coupon/Create'
|
import CreateCoupon from '@/pages/Coupon/Create'
|
||||||
import UpdateCoupon from '@/pages/Coupon/Update'
|
import UpdateCoupon from '@/pages/Coupon/Update'
|
||||||
import UsersList from '@/pages/user/List'
|
import UsersList from '@/pages/user/List'
|
||||||
|
import AdminList from '@/pages/admin/List'
|
||||||
|
import AdminCreate from '@/pages/admin/Create'
|
||||||
|
|
||||||
const MainRouter: FC = () => {
|
const MainRouter: FC = () => {
|
||||||
|
|
||||||
@@ -86,6 +88,10 @@ const MainRouter: FC = () => {
|
|||||||
<Route path={`${Pages.coupon.detail}:id`} element={<UpdateCoupon />} />
|
<Route path={`${Pages.coupon.detail}:id`} element={<UpdateCoupon />} />
|
||||||
|
|
||||||
<Route path={Pages.buyUsers.list} element={<UsersList />} />
|
<Route path={Pages.buyUsers.list} element={<UsersList />} />
|
||||||
|
|
||||||
|
<Route path={Pages.admin.list} element={<AdminList />} />
|
||||||
|
<Route path={Pages.admin.create} element={<AdminCreate />} />
|
||||||
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user