add adminns
This commit is contained in:
@@ -884,6 +884,7 @@
|
|||||||
"active": "فعال",
|
"active": "فعال",
|
||||||
"inactive": "غیرفعال",
|
"inactive": "غیرفعال",
|
||||||
"admins": "مدیران",
|
"admins": "مدیران",
|
||||||
|
"add_admin": "افزودن مدیر",
|
||||||
"sms_count": "تعداد پیامک"
|
"sms_count": "تعداد پیامک"
|
||||||
},
|
},
|
||||||
"cancel": "لغو"
|
"cancel": "لغو"
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import * as api from "../service/IconService";
|
import * as api from "../service/IconService";
|
||||||
import { GroupIconsResponse, ReportsResponse } from "../types/Types";
|
import {
|
||||||
|
GroupIconsResponse,
|
||||||
|
ReportsResponse,
|
||||||
|
SystemRolesResponse,
|
||||||
|
} from "../types/Types";
|
||||||
|
|
||||||
export const useGetIcons = () => {
|
export const useGetIcons = () => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
@@ -68,3 +72,28 @@ export const useGetRestaurantSmsCount = () => {
|
|||||||
queryFn: api.getRestaurantSmsCount,
|
queryFn: api.getRestaurantSmsCount,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useDeleteRestaurantAdmin = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
restaurantId,
|
||||||
|
adminId,
|
||||||
|
}: {
|
||||||
|
restaurantId: string;
|
||||||
|
adminId: string;
|
||||||
|
}) => api.deleteRestaurantAdmin(restaurantId, adminId),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAddAdminRestaurant = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.addAdminRestaurant,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetSystemRoles = () => {
|
||||||
|
return useQuery<SystemRolesResponse>({
|
||||||
|
queryKey: ["system-roles"],
|
||||||
|
queryFn: api.getSystemRoles,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { AddAdminRestaurantType } from '../../types/Types'
|
||||||
|
import Input from '../../../../components/Input'
|
||||||
|
import Select from '../../../../components/Select'
|
||||||
|
import Button from '../../../../components/Button'
|
||||||
|
import { useAddAdminRestaurant, useGetSystemRoles } from '../../hooks/useIconData'
|
||||||
|
import { SystemRoleType } from '../../types/Types'
|
||||||
|
import { ErrorType } from '../../../../helpers/types'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { TickCircle } from 'iconsax-react'
|
||||||
|
|
||||||
|
interface AddRestaurantAdminFormProps {
|
||||||
|
restaurantId: string
|
||||||
|
onSuccess: () => void
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddRestaurantAdminForm: FC<AddRestaurantAdminFormProps> = ({
|
||||||
|
restaurantId,
|
||||||
|
onSuccess,
|
||||||
|
onClose
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
const { mutate: addAdmin, isPending } = useAddAdminRestaurant()
|
||||||
|
const { data: rolesData } = useGetSystemRoles()
|
||||||
|
|
||||||
|
const rolesList = rolesData?.data || []
|
||||||
|
|
||||||
|
const formik = useFormik<AddAdminRestaurantType>({
|
||||||
|
initialValues: {
|
||||||
|
restaurantId: restaurantId,
|
||||||
|
phone: '',
|
||||||
|
firstName: '',
|
||||||
|
lastName: '',
|
||||||
|
roleId: ''
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
phone: Yup.string().required(t('errors.required')),
|
||||||
|
firstName: Yup.string().required(t('errors.required')),
|
||||||
|
lastName: Yup.string().required(t('errors.required')),
|
||||||
|
roleId: Yup.string().required(t('errors.required'))
|
||||||
|
}),
|
||||||
|
onSubmit: (values) => {
|
||||||
|
addAdmin(values, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success(t('success'))
|
||||||
|
formik.resetForm()
|
||||||
|
onSuccess()
|
||||||
|
onClose()
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast.error(error.response?.data?.error?.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={formik.handleSubmit} className='mt-6'>
|
||||||
|
<div className='flex flex-col gap-6'>
|
||||||
|
<div className='rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label={t('user.name')}
|
||||||
|
{...formik.getFieldProps('firstName')}
|
||||||
|
error_text={formik.touched.firstName && formik.errors.firstName ? formik.errors.firstName : ''}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label={t('user.family')}
|
||||||
|
{...formik.getFieldProps('lastName')}
|
||||||
|
error_text={formik.touched.lastName && formik.errors.lastName ? formik.errors.lastName : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='rowTwoInput'>
|
||||||
|
<Input
|
||||||
|
label={t('restaurant.phone')}
|
||||||
|
{...formik.getFieldProps('phone')}
|
||||||
|
error_text={formik.touched.phone && formik.errors.phone ? formik.errors.phone : ''}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
label={t('user.role')}
|
||||||
|
placeholder={t('select')}
|
||||||
|
items={rolesList.map((item: SystemRoleType) => ({
|
||||||
|
value: item.id,
|
||||||
|
label: item.name
|
||||||
|
}))}
|
||||||
|
{...formik.getFieldProps('roleId')}
|
||||||
|
error_text={formik.touched.roleId && formik.errors.roleId ? formik.errors.roleId : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex gap-4 justify-end mt-4'>
|
||||||
|
<Button
|
||||||
|
type='button'
|
||||||
|
onClick={onClose}
|
||||||
|
className='px-6 bg-gray-200 text-gray-700 hover:bg-gray-300'
|
||||||
|
>
|
||||||
|
{t('cancel')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type='submit'
|
||||||
|
isLoading={isPending}
|
||||||
|
className='px-6'
|
||||||
|
>
|
||||||
|
<div className='flex gap-2'>
|
||||||
|
<TickCircle
|
||||||
|
className='size-5'
|
||||||
|
color='white'
|
||||||
|
/>
|
||||||
|
<div className='text-sm'>
|
||||||
|
{t('restaurant.add_admin')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddRestaurantAdminForm
|
||||||
|
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
import { FC } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import DefaulModal from '../../../../components/DefaulModal'
|
import DefaulModal from '../../../../components/DefaulModal'
|
||||||
import { useGetRestaurantAdmins } from '../../hooks/useIconData'
|
import { useDeleteRestaurantAdmin, useGetRestaurantAdmins } from '../../hooks/useIconData'
|
||||||
import PageLoading from '../../../../components/PageLoading'
|
import PageLoading from '../../../../components/PageLoading'
|
||||||
import Td from '../../../../components/Td'
|
import Td from '../../../../components/Td'
|
||||||
import { RestaurantAdminType } from '../../types/Types'
|
import { RestaurantAdminType } from '../../types/Types'
|
||||||
import moment from 'moment-jalaali'
|
import moment from 'moment-jalaali'
|
||||||
|
import TrashWithConfrim from '../../../../components/TrashWithConfrim'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { ErrorType } from '../../../../helpers/types'
|
||||||
|
import Button from '../../../../components/Button'
|
||||||
|
import AddRestaurantAdminForm from './AddRestaurantAdminForm'
|
||||||
|
|
||||||
interface RestaurantAdminsModalProps {
|
interface RestaurantAdminsModalProps {
|
||||||
open: boolean
|
open: boolean
|
||||||
@@ -15,10 +20,37 @@ interface RestaurantAdminsModalProps {
|
|||||||
|
|
||||||
const RestaurantAdminsModal: FC<RestaurantAdminsModalProps> = ({ open, close, restaurantId }) => {
|
const RestaurantAdminsModal: FC<RestaurantAdminsModalProps> = ({ open, close, restaurantId }) => {
|
||||||
const { t } = useTranslation('global')
|
const { t } = useTranslation('global')
|
||||||
const { data: adminsData, isLoading } = useGetRestaurantAdmins(restaurantId)
|
const { data: adminsData, isLoading, refetch } = useGetRestaurantAdmins(restaurantId)
|
||||||
|
const [showAddForm, setShowAddForm] = useState(false)
|
||||||
|
|
||||||
const adminsList = (adminsData as { data?: RestaurantAdminType[] })?.data || []
|
const adminsList = (adminsData as { data?: RestaurantAdminType[] })?.data || []
|
||||||
|
|
||||||
|
const { mutate: deleteAdmin, isPending } = useDeleteRestaurantAdmin()
|
||||||
|
|
||||||
|
const handleDeleteAdmin = (restaurantId: string, adminId: string) => {
|
||||||
|
deleteAdmin({ restaurantId, adminId }, {
|
||||||
|
onSuccess: () => {
|
||||||
|
refetch()
|
||||||
|
toast.success(t('success'))
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast.error(error.response?.data?.error?.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddAdmin = () => {
|
||||||
|
setShowAddForm(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleFormSuccess = () => {
|
||||||
|
refetch()
|
||||||
|
setShowAddForm(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleFormClose = () => {
|
||||||
|
setShowAddForm(false)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<DefaulModal
|
<DefaulModal
|
||||||
open={open}
|
open={open}
|
||||||
@@ -27,18 +59,34 @@ const RestaurantAdminsModal: FC<RestaurantAdminsModalProps> = ({ open, close, re
|
|||||||
isHeader
|
isHeader
|
||||||
>
|
>
|
||||||
<div className='mt-6'>
|
<div className='mt-6'>
|
||||||
|
{showAddForm ? (
|
||||||
|
<AddRestaurantAdminForm
|
||||||
|
restaurantId={restaurantId}
|
||||||
|
onSuccess={handleFormSuccess}
|
||||||
|
onClose={handleFormClose}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className='flex justify-end'>
|
||||||
|
<Button
|
||||||
|
onClick={handleAddAdmin}
|
||||||
|
className='w-fit px-5'
|
||||||
|
>
|
||||||
|
{t('restaurant.add_admin')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
{
|
{
|
||||||
isLoading ?
|
isLoading ?
|
||||||
<PageLoading />
|
<PageLoading />
|
||||||
:
|
:
|
||||||
<div className='relative overflow-x-auto rounded-3xl w-full'>
|
<div className='relative overflow-x-auto rounded-3xl w-full mt-6'>
|
||||||
<table className='w-full text-sm'>
|
<table className='w-full text-sm'>
|
||||||
<thead className='thead'>
|
<thead className='thead'>
|
||||||
<tr>
|
<tr>
|
||||||
<Td text={t('user.name')} />
|
<Td text={t('user.name')} />
|
||||||
<Td text={t('user.email')} />
|
|
||||||
<Td text={t('restaurant.phone')} />
|
<Td text={t('restaurant.phone')} />
|
||||||
<Td text={t('restaurant.created_at')} />
|
<Td text={t('restaurant.created_at')} />
|
||||||
|
<Td text={''} />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -47,13 +95,20 @@ const RestaurantAdminsModal: FC<RestaurantAdminsModalProps> = ({ open, close, re
|
|||||||
return (
|
return (
|
||||||
<tr key={admin.id} className='tr'>
|
<tr key={admin.id} className='tr'>
|
||||||
<Td text={`${admin.firstName} ${admin.lastName}`} />
|
<Td text={`${admin.firstName} ${admin.lastName}`} />
|
||||||
<Td text={admin.email} />
|
|
||||||
<Td text={admin.phone || '-'} />
|
<Td text={admin.phone || '-'} />
|
||||||
<Td text={''}>
|
<Td text={''}>
|
||||||
<div className='dltr text-right'>
|
<div className='dltr text-right'>
|
||||||
{moment(admin.createdAt).format('jYYYY-jMM-jDD HH:mm')}
|
{moment(admin.createdAt).format('jYYYY-jMM-jDD HH:mm')}
|
||||||
</div>
|
</div>
|
||||||
</Td>
|
</Td>
|
||||||
|
<Td text=''>
|
||||||
|
<div className='flex gap-2'>
|
||||||
|
<TrashWithConfrim
|
||||||
|
onDelete={() => handleDeleteAdmin(restaurantId, admin.id)}
|
||||||
|
isLoading={isPending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -62,6 +117,8 @@ const RestaurantAdminsModal: FC<RestaurantAdminsModalProps> = ({ open, close, re
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</DefaulModal>
|
</DefaulModal>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import {
|
|||||||
ReportsResponse,
|
ReportsResponse,
|
||||||
RestaurantsResponse,
|
RestaurantsResponse,
|
||||||
RestaurantSmsCountResponse,
|
RestaurantSmsCountResponse,
|
||||||
|
AddAdminRestaurantType,
|
||||||
|
SystemRolesResponse,
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
|
|
||||||
export const getIcons = async (): Promise<IconsResponse> => {
|
export const getIcons = async (): Promise<IconsResponse> => {
|
||||||
@@ -62,3 +64,26 @@ export const getRestaurantSmsCount = async (): Promise<
|
|||||||
const { data } = await axios.get(`/admin/dmenu/restaurants/sms-count`);
|
const { data } = await axios.get(`/admin/dmenu/restaurants/sms-count`);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const deleteRestaurantAdmin = async (
|
||||||
|
restaurantId: string,
|
||||||
|
adminId: string
|
||||||
|
) => {
|
||||||
|
const { data } = await axios.delete(
|
||||||
|
`/admin/dmenu/restaurants/${restaurantId}/admins/${adminId}`
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addAdminRestaurant = async (params: AddAdminRestaurantType) => {
|
||||||
|
const { data } = await axios.post(
|
||||||
|
`/admin/dmenu/restaurants/${params.restaurantId}/admins`,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getSystemRoles = async (): Promise<SystemRolesResponse> => {
|
||||||
|
const { data } = await axios.get(`/admin/dmenu/system-roles`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -132,3 +132,35 @@ export interface RestaurantSmsCountResponse
|
|||||||
extends IResponse<RestaurantSmsCountItem[]> {
|
extends IResponse<RestaurantSmsCountItem[]> {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AddAdminRestaurantType = {
|
||||||
|
restaurantId: string;
|
||||||
|
phone: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
roleId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PermissionType = {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SystemRoleType = {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
name: string;
|
||||||
|
isSystem: boolean;
|
||||||
|
restaurant: string | null;
|
||||||
|
permissions: PermissionType[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface SystemRolesResponse extends IResponse<SystemRoleType[]> {
|
||||||
|
statusCode: number;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user