create admin
This commit is contained in:
@@ -0,0 +1,131 @@
|
|||||||
|
import { useFormik } from 'formik';
|
||||||
|
import { type FC } from 'react';
|
||||||
|
import type { CreateAdminType } from './types/Types';
|
||||||
|
import * as Yup from 'yup';
|
||||||
|
import Button from '@/components/Button';
|
||||||
|
import { AddSquare } from 'iconsax-react';
|
||||||
|
import Input from '@/components/Input';
|
||||||
|
import Select from '@/components/Select';
|
||||||
|
import { useCreateAdmin, useGetRoles } from './hooks/useAdminData';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
import { extractErrorMessage } from '@/config/func';
|
||||||
|
import { Paths } from '@/config/Paths';
|
||||||
|
|
||||||
|
const CreateAdmin: FC = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { mutate: createAdmin, isPending } = useCreateAdmin();
|
||||||
|
const { data: rolesData } = useGetRoles();
|
||||||
|
|
||||||
|
const formik = useFormik<CreateAdminType>({
|
||||||
|
initialValues: {
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
phone: '',
|
||||||
|
roleId: '',
|
||||||
|
notificationPrefrences: ['test']
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
firstName: Yup.string()
|
||||||
|
.required('نام اجباری می باشد')
|
||||||
|
.min(2, 'نام باید حداقل 2 کاراکتر باشد'),
|
||||||
|
lastName: Yup.string()
|
||||||
|
.required('نام خانوادگی اجباری می باشد')
|
||||||
|
.min(2, 'نام خانوادگی باید حداقل 2 کاراکتر باشد'),
|
||||||
|
phone: Yup.string()
|
||||||
|
.required('شماره موبایل اجباری می باشد')
|
||||||
|
.matches(/^09[0-9]{9}$/, 'شماره موبایل معتبر نمی باشد'),
|
||||||
|
roleId: Yup.string().required('نقش اجباری می باشد'),
|
||||||
|
}),
|
||||||
|
onSubmit: (values) => {
|
||||||
|
createAdmin(values, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success('ادمین با موفقیت ایجاد شد');
|
||||||
|
navigate(Paths.admin.list);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const roleOptions =
|
||||||
|
rolesData?.data?.map((role) => ({
|
||||||
|
label: role.title || role.name,
|
||||||
|
value: role.id,
|
||||||
|
})) || [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-5'>
|
||||||
|
<div className='flex justify-between items-center'>
|
||||||
|
<h1 className='text-lg font-light'>ایجاد ادمین جدید</h1>
|
||||||
|
<Button
|
||||||
|
className='w-fit px-6'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={isPending}
|
||||||
|
>
|
||||||
|
<div className='flex gap-1.5'>
|
||||||
|
<AddSquare size={18} color='black' />
|
||||||
|
<div className='text-[13px] font-light'>ایجاد ادمین</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-8 bg-white p-6 rounded-3xl flex-1'>
|
||||||
|
<div className='rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label='نام'
|
||||||
|
placeholder='نام را وارد کنید'
|
||||||
|
{...formik.getFieldProps('firstName')}
|
||||||
|
error_text={
|
||||||
|
formik.touched.firstName && formik.errors.firstName
|
||||||
|
? formik.errors.firstName
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label='نام خانوادگی'
|
||||||
|
placeholder='نام خانوادگی را وارد کنید'
|
||||||
|
{...formik.getFieldProps('lastName')}
|
||||||
|
error_text={
|
||||||
|
formik.touched.lastName && formik.errors.lastName
|
||||||
|
? formik.errors.lastName
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-6'>
|
||||||
|
<Input
|
||||||
|
label='شماره موبایل'
|
||||||
|
placeholder='شماره موبایل را وارد کنید'
|
||||||
|
{...formik.getFieldProps('phone')}
|
||||||
|
error_text={
|
||||||
|
formik.touched.phone && formik.errors.phone
|
||||||
|
? formik.errors.phone
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-6'>
|
||||||
|
<Select
|
||||||
|
label='نقش'
|
||||||
|
placeholder='نقش را انتخاب کنید'
|
||||||
|
items={roleOptions}
|
||||||
|
{...formik.getFieldProps('roleId')}
|
||||||
|
error_text={
|
||||||
|
formik.touched.roleId && formik.errors.roleId
|
||||||
|
? formik.errors.roleId
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateAdmin;
|
||||||
@@ -2,9 +2,12 @@ import { useState, type FC } from "react";
|
|||||||
import { useGetAdmins } from "./hooks/useAdminData";
|
import { useGetAdmins } from "./hooks/useAdminData";
|
||||||
import Table from "@/components/Table";
|
import Table from "@/components/Table";
|
||||||
import moment from "moment-jalaali";
|
import moment from "moment-jalaali";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { Paths } from "@/config/Paths";
|
||||||
|
import Button from "@/components/Button";
|
||||||
|
import { AddSquare } from "iconsax-react";
|
||||||
|
|
||||||
const AdminList: FC = () => {
|
const AdminList: FC = () => {
|
||||||
|
|
||||||
const [page, setPage] = useState<number>(1);
|
const [page, setPage] = useState<number>(1);
|
||||||
const { data } = useGetAdmins(page);
|
const { data } = useGetAdmins(page);
|
||||||
|
|
||||||
@@ -12,6 +15,14 @@ const AdminList: FC = () => {
|
|||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<h1 className="text-lg font-light">مدیران</h1>
|
<h1 className="text-lg font-light">مدیران</h1>
|
||||||
|
<Link to={Paths.admin.create}>
|
||||||
|
<Button className="w-fit px-6">
|
||||||
|
<div className="flex gap-1.5">
|
||||||
|
<AddSquare size={18} color="black" />
|
||||||
|
<div className="text-[13px] font-light">ادمین جدید</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Table
|
<Table
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as api from "../service/AdminService";
|
import * as api from "../service/AdminService";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
export const useGetAdmins = (page: number) => {
|
export const useGetAdmins = (page: number) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
@@ -7,3 +7,16 @@ export const useGetAdmins = (page: number) => {
|
|||||||
queryFn: () => api.getAdmins(page),
|
queryFn: () => api.getAdmins(page),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useCreateAdmin = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.createAdmin,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetRoles = () => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["roles"],
|
||||||
|
queryFn: api.getRoles,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import axios from "@/config/axios";
|
import axios from "@/config/axios";
|
||||||
import type { AdminsType } from "../types/Types";
|
import type {
|
||||||
|
AdminsType,
|
||||||
|
CreateAdminType,
|
||||||
|
RolesResponseType,
|
||||||
|
} from "../types/Types";
|
||||||
|
|
||||||
export const getAdmins = async (page: number) => {
|
export const getAdmins = async (page: number) => {
|
||||||
const { data } = await axios.get<AdminsType>("/admin/admins", {
|
const { data } = await axios.get<AdminsType>("/admin/admins", {
|
||||||
@@ -7,3 +11,13 @@ export const getAdmins = async (page: number) => {
|
|||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createAdmin = async (params: CreateAdminType) => {
|
||||||
|
const { data } = await axios.post("/admin/admin", params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRoles = async () => {
|
||||||
|
const { data } = await axios.get<RolesResponseType>("/admin/roles");
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -19,3 +19,31 @@ export interface AdminItemType extends RowDataType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type AdminsType = BaseResponse<AdminItemType[]>;
|
export type AdminsType = BaseResponse<AdminItemType[]>;
|
||||||
|
|
||||||
|
export type CreateAdminType = {
|
||||||
|
phone: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
roleId: string;
|
||||||
|
notificationPrefrences?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PermissionItemType = {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RoleItemType = {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
isSystem: boolean;
|
||||||
|
permissions: PermissionItemType[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RolesResponseType = BaseResponse<RoleItemType[]>;
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import UpdateSection from '@/pages/print/Update'
|
|||||||
import PrintForm from '@/pages/print/Form'
|
import PrintForm from '@/pages/print/Form'
|
||||||
import UsersList from '@/pages/user/List'
|
import UsersList from '@/pages/user/List'
|
||||||
import AdminList from '@/pages/admin/List'
|
import AdminList from '@/pages/admin/List'
|
||||||
|
import CreateAdmin from '@/pages/admin/Create'
|
||||||
|
|
||||||
const MainRouter: FC = () => {
|
const MainRouter: FC = () => {
|
||||||
return (
|
return (
|
||||||
@@ -92,6 +93,7 @@ const MainRouter: FC = () => {
|
|||||||
<Route path={Paths.users.list} element={<UsersList />} />
|
<Route path={Paths.users.list} element={<UsersList />} />
|
||||||
|
|
||||||
<Route path={Paths.admin.list} element={<AdminList />} />
|
<Route path={Paths.admin.list} element={<AdminList />} />
|
||||||
|
<Route path={Paths.admin.create} element={<CreateAdmin />} />
|
||||||
|
|
||||||
<Route path={Paths.features.list} element={<FeaturesList />} />
|
<Route path={Paths.features.list} element={<FeaturesList />} />
|
||||||
<Route path={Paths.features.create} element={<CreateFeature />} />
|
<Route path={Paths.features.create} element={<CreateFeature />} />
|
||||||
|
|||||||
Reference in New Issue
Block a user