plan users
This commit is contained in:
@@ -110,5 +110,6 @@ export const Pages = {
|
||||
create: "/support/create",
|
||||
list: "/support/list",
|
||||
detail: "/support/detail/",
|
||||
planUsers: "/support/plan-users/",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,4 +6,5 @@ export const SideBarItemHasSubMenu = [
|
||||
"tickets",
|
||||
"learning",
|
||||
"blog",
|
||||
"support",
|
||||
];
|
||||
|
||||
+16
-2
@@ -102,7 +102,10 @@
|
||||
"add_user": "افزودن کاربر",
|
||||
"role_list": "لیست نقش ها",
|
||||
"role_create": "افزودن نقش",
|
||||
"reviews": "نظرات"
|
||||
"reviews": "نظرات",
|
||||
"create_plan": "ایجاد پلن",
|
||||
"plan_users": "کاربران پلن",
|
||||
"plan_list": "لیست پلن ها"
|
||||
},
|
||||
"review": {
|
||||
"title": "عنوان",
|
||||
@@ -779,12 +782,23 @@
|
||||
"on_site_support": "پشتیبانی در محل",
|
||||
"on_site_training": "آموزش در محل",
|
||||
"ticket_limit": "ظرفیت ارسال تیکت",
|
||||
"technical_issue_resolution": "رفع ایراد فنی",
|
||||
"service_functionality_test": "تست عملکرد سرویس",
|
||||
"plans": "پلن ها",
|
||||
"plan_name": "نام پلن",
|
||||
"price": "قیمت",
|
||||
"duration": "مدت",
|
||||
"features": "ویژگی ها",
|
||||
"actions": "عملیات",
|
||||
"new_plan": "پلن جدید"
|
||||
"new_plan": "پلن جدید",
|
||||
"plan_users": "کاربران ",
|
||||
"ACTIVE": "فعال",
|
||||
"INACTIVE": "غیرفعال",
|
||||
"EXPIRED": "منقضی شده",
|
||||
"start_date": "تاریخ شروع",
|
||||
"end_date": "تاریخ پایان",
|
||||
"status": "وضعیت",
|
||||
"full_name": "نام و نام خانوادگی",
|
||||
"users": "کاربران"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,17 +41,28 @@ const SupportList: FC = () => {
|
||||
<Td text={t('support.plan_name')} />
|
||||
<Td text={t('support.price')} />
|
||||
<Td text={t('support.duration')} />
|
||||
<Td text={t('support.users')} />
|
||||
<Td text={''} />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
data?.data?.supportPlans?.map((item: { id: string, name: string, price: number, duration: string }) => {
|
||||
data?.data?.supportPlans?.map((item: { id: string, name: string, price: number, duration: string, userCount: number }) => {
|
||||
return (
|
||||
<tr className='tr' key={item.id}>
|
||||
<Td text={item.name} />
|
||||
<Td text={NumberFormat(item.price)} />
|
||||
<Td text={item.duration} />
|
||||
<Td text={''}>
|
||||
<Link to={Pages.support.planUsers + item.id}>
|
||||
<div className='flex items-center gap-2 text-blue-500'>
|
||||
<div>
|
||||
{item.userCount}
|
||||
</div>
|
||||
کاربر
|
||||
</div>
|
||||
</Link>
|
||||
</Td>
|
||||
<Td text={''}>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Link to={Pages.support.detail + item.id}>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useGetPlanUsers } from './hooks/useSupportData'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import Td from '../../components/Td'
|
||||
import moment from 'moment-jalaali'
|
||||
import { PlanItemUserType } from './types/SupportTypes'
|
||||
const PlanUsers: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
const { id } = useParams()
|
||||
const { data } = useGetPlanUsers(id)
|
||||
|
||||
return (
|
||||
<div className='mt-4'>
|
||||
<div>
|
||||
{t('support.plan_users')} {data?.data?.users?.[0]?.supportPlan?.name}
|
||||
</div>
|
||||
|
||||
<div className='relative overflow-x-auto rounded-3xl mt-9 w-full'>
|
||||
<table className='w-full text-sm '>
|
||||
<thead className='thead'>
|
||||
<tr>
|
||||
<Td text={t('support.full_name')} />
|
||||
<Td text={t('support.start_date')} />
|
||||
<Td text={t('support.end_date')} />
|
||||
<Td text={t('support.status')} />
|
||||
<Td text={''} />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data?.data?.users?.map((item: PlanItemUserType) => (
|
||||
<tr className='tr' key={item.id}>
|
||||
<Td text={item.user.firstName + ' ' + item.user.lastName} />
|
||||
<Td text={''}>
|
||||
<div className='dltr text-right'>
|
||||
{moment(item.startDate).format('jYYYY/jMM/jDD HH:mm')}
|
||||
</div>
|
||||
</Td>
|
||||
<Td text={''}>
|
||||
<div className='dltr text-right'>
|
||||
{moment(item.endDate).format('jYYYY/jMM/jDD HH:mm')}
|
||||
</div>
|
||||
</Td>
|
||||
<Td text={t(`support.${item.status}`)} />
|
||||
<Td text={''} />
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PlanUsers
|
||||
@@ -1,11 +1,13 @@
|
||||
export enum SupportPlanFeatureKey {
|
||||
LEARNING_DOCS = "learning_docs", // راهنما و مستندات آموزشی
|
||||
TICKET_SUPPORT = "ticket_support", // ارسال تیکت
|
||||
TICKET_LIMIT = "ticket_limit", // ظرفیت ارسال تیکت
|
||||
RESPONSE_TIME = "response_time", // زمان پاسخگویی به تیکت
|
||||
PHONE_SUPPORT = "phone_support", // پاسخگویی تلفنی
|
||||
BACKUP_VERSION = "backup_version", // نسخه بکاپ
|
||||
TECHNICAL_ISSUE_RESOLUTION = "technical_issue_resolution", // رفع ایراد فنی
|
||||
TECHNICAL_EXPERT_ACCESS = "technical_expert_access", // دسترسی به متخصصین فنی
|
||||
BACKUP_VERSION = "backup_version", // نسخه بکاپ
|
||||
SERVICE_FUNCTIONALITY_TEST = "service_functionality_test", // تست عملکرد سرویس
|
||||
ON_SITE_SUPPORT = "on_site_support", // پشتیبانی در محل
|
||||
ON_SITE_TRAINING = "on_site_training", // آموزش در محل
|
||||
TICKET_LIMIT = "ticket_limit", // ظرفیت ارسال تیکت
|
||||
}
|
||||
|
||||
@@ -34,3 +34,11 @@ export const useDeletePlan = () => {
|
||||
mutationFn: (id: string) => api.deletePlan(id),
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetPlanUsers = (id?: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["plan-users", id],
|
||||
queryFn: () => api.getPlanUsers(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -25,3 +25,8 @@ export const deletePlan = async (id: string) => {
|
||||
const { data } = await axios.delete(`/support-plans/${id}`);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getPlanUsers = async (id?: string) => {
|
||||
const { data } = await axios.get(`/support-plans/${id}/users`);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -10,3 +10,40 @@ export type CreatePlanType = {
|
||||
featureType: "boolean" | "text";
|
||||
}[];
|
||||
};
|
||||
|
||||
export type PlanItemUserType = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
user: {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
userName: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
birthDate: string;
|
||||
nationalCode: string;
|
||||
profilePic: string | null;
|
||||
emailVerified: boolean;
|
||||
financialType: string;
|
||||
deletedAt: string | null;
|
||||
};
|
||||
supportPlan: {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
name: string;
|
||||
description: string;
|
||||
price: number;
|
||||
isFree: boolean;
|
||||
duration: number;
|
||||
isActive: boolean;
|
||||
deletedAt: string | null;
|
||||
};
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
status: string;
|
||||
};
|
||||
|
||||
@@ -68,6 +68,7 @@ import Comments from '../pages/blog/Comments'
|
||||
import CreatePlan from '../pages/support/Create'
|
||||
import SupportList from '../pages/support/List'
|
||||
import UpdateSupport from '../pages/support/Update'
|
||||
import PlanUsers from '../pages/support/PlanUsers'
|
||||
const MainRouter: FC = () => {
|
||||
|
||||
const { hasSubMenu } = useSharedStore()
|
||||
@@ -147,6 +148,7 @@ const MainRouter: FC = () => {
|
||||
<Route path={Pages.support.create} element={<CreatePlan />} />
|
||||
<Route path={Pages.support.list} element={<SupportList />} />
|
||||
<Route path={Pages.support.detail + ':id'} element={<UpdateSupport />} />
|
||||
<Route path={Pages.support.planUsers + ':id'} element={<PlanUsers />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,7 @@ import UsersSubMenu from './components/UsersSubMenu'
|
||||
import LearningSubMenu from './components/LearningSubMenu'
|
||||
import BlogSubMenu from './components/BlogSubMenu'
|
||||
import { useGetProfile } from '../pages/profile/hooks/useProfileData'
|
||||
import SupportSubMenu from './components/SupportSubMenu'
|
||||
const SideBar: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
@@ -324,7 +325,9 @@ const SideBar: FC = () => {
|
||||
<LearningSubMenu />
|
||||
: subMenuName === 'blog' ?
|
||||
<BlogSubMenu />
|
||||
: null
|
||||
: subMenuName === 'support' ?
|
||||
<SupportSubMenu />
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Headphone } from 'iconsax-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { Pages } from '../../config/Pages'
|
||||
import SubMenuItem from './SubMenuItem'
|
||||
|
||||
const SupportSubMenu: FC = () => {
|
||||
|
||||
const location = useLocation()
|
||||
const { t } = useTranslation('global')
|
||||
|
||||
|
||||
const isActive = (name: string) => {
|
||||
return location.pathname.includes(name)
|
||||
}
|
||||
|
||||
|
||||
return <div className='py-12'>
|
||||
<div className='flex gap-3 items-center border-b pb-10 px-6'>
|
||||
<Headphone
|
||||
size={24}
|
||||
color='#000'
|
||||
variant='Bold'
|
||||
/>
|
||||
<div className='text-xs'>
|
||||
{t('sidebar.support')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col mt-10 gap-4'>
|
||||
<SubMenuItem
|
||||
title={t('submenu.plan_list')}
|
||||
isActive={isActive('list')}
|
||||
link={Pages.support.list}
|
||||
/>
|
||||
<SubMenuItem
|
||||
title={t('submenu.create_plan')}
|
||||
isActive={isActive('create')}
|
||||
link={Pages.support.create}
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
export default SupportSubMenu
|
||||
Reference in New Issue
Block a user