622 lines
19 KiB
TypeScript
622 lines
19 KiB
TypeScript
"use client";
|
||
import { requestType, ticketStatuses } from "@/core/constant";
|
||
import {
|
||
exportToExcel,
|
||
formatDurationPersian,
|
||
handleAxiosError,
|
||
} from "@/core/utils";
|
||
import {
|
||
useMutateAgentEfficiency,
|
||
useMutateAgentPerformance,
|
||
useMutateAgingReport,
|
||
useMutateAvgResolutionTime,
|
||
useMutateClosureRate,
|
||
useMutateCriticalTickets,
|
||
useMutateDepartmentLoad,
|
||
useMutateDepartmentReport,
|
||
useMutateKpiReport,
|
||
useMutatePredictionReport,
|
||
useMutateSlaBreach,
|
||
useMutateStatsReport,
|
||
} from "@/services/hooks/report.hook";
|
||
import { DownloadOutlined } from "@mui/icons-material";
|
||
import {
|
||
Box,
|
||
Button,
|
||
Card,
|
||
CardContent,
|
||
Stack,
|
||
Typography,
|
||
} from "@mui/material";
|
||
import { UseMutateAsyncFunction } from "@tanstack/react-query";
|
||
import { toast } from "react-toastify";
|
||
|
||
export default function Page() {
|
||
// ۱. آمار کلی تیکتها
|
||
const { mutateAsync: totalStatsAsync } = useMutateStatsReport();
|
||
|
||
// ۲. گزارش عملکرد دپارتمانها
|
||
const { mutateAsync: deptReportAsync } = useMutateDepartmentReport();
|
||
|
||
// ۳. گزارش عملکرد کارشناسان
|
||
const { mutateAsync: agentPerfAsync } = useMutateAgentPerformance();
|
||
|
||
// ۴. میانگین زمان پاسخگویی
|
||
const { mutateAsync: avgResTimeAsync } = useMutateAvgResolutionTime();
|
||
|
||
// ۵. تیکتهای بحرانی
|
||
const { mutateAsync: criticalTicketsAsync } = useMutateCriticalTickets();
|
||
|
||
// ۶. روند ثبت تیکتها (نیاز به params دارد)
|
||
// const { mutateAsync: ticketsTrend, isLoading: trendLoading } = useMutateTicketsTrend(dateParams);
|
||
|
||
// ۷. نرخ بستن تیکتها
|
||
const { mutateAsync: closureRateAsync } = useMutateClosureRate();
|
||
|
||
// ۸. تیکتهای خارج از SLA
|
||
const { mutateAsync: slaBreachAsync } = useMutateSlaBreach();
|
||
|
||
// ۹. گزارش قدمت تیکتها
|
||
const { mutateAsync: agingReportAsync } = useMutateAgingReport();
|
||
|
||
// ۱۰. بهرهوری کارشناسان
|
||
const { mutateAsync: agentEfficiencyAsync } = useMutateAgentEfficiency();
|
||
|
||
// ۱۱. بار کاری دپارتمانها
|
||
const { mutateAsync: deptLoadAsync } = useMutateDepartmentLoad();
|
||
|
||
// ۱۲. شاخصهای کلیدی عملکرد (KPI)
|
||
const { mutateAsync: kpiReportAsync } = useMutateKpiReport();
|
||
|
||
// ۱۳. پیشبینی وضعیت تیکتها
|
||
const { mutateAsync: predictionReportAsync } = useMutatePredictionReport();
|
||
|
||
const handleGetStatsReport = async () => {
|
||
try {
|
||
const { data } = await totalStatsAsync();
|
||
|
||
const formattedData = [data]?.map((t: any) => ({
|
||
"كل تيكت ها": t.total,
|
||
"تيكت هاي باز": t.open,
|
||
"تيكت هاي در حال بررسي": t.inProgress,
|
||
"تيكت هاي حل شده": t.resolved,
|
||
"تيكت هاي بسته شده": t.closed,
|
||
}));
|
||
exportToExcel("excel", formattedData, "گزارش كلي تيكت ها");
|
||
} catch (error) {
|
||
console.log(error);
|
||
toast.error(handleAxiosError(error));
|
||
}
|
||
};
|
||
|
||
const handleDepReport = async () => {
|
||
try {
|
||
const { data } = await deptReportAsync();
|
||
|
||
const formattedData = data?.map((t: any) => ({
|
||
"بخش / واحد": t.department?.displayName,
|
||
"كل تيكت ها": t.totalTickets,
|
||
"تيكت هاي باز": t.openTickets,
|
||
"تيكت هاي حل شده": t.resolvedTickets,
|
||
}));
|
||
exportToExcel("excel", formattedData, "گزارش تيكت ها به تفكيك واحد");
|
||
} catch (error) {
|
||
console.log(error);
|
||
toast.error(handleAxiosError(error));
|
||
}
|
||
};
|
||
|
||
const handleAgentPerformanceReport = async () => {
|
||
try {
|
||
const { data } = await agentPerfAsync();
|
||
|
||
const formattedData = data?.map((t: any) => ({
|
||
"كارشناس مربوطه": t.assignee?.fullname,
|
||
"كل تيكت ها": t.totalAssigned,
|
||
"تيكت هاي باز": t.open,
|
||
"تيكت هاي حل شده": t.resolved,
|
||
}));
|
||
exportToExcel("excel", formattedData, "گزارش تيكت ها به تفكيك كارشناسان");
|
||
} catch (error) {
|
||
console.log(error);
|
||
toast.error(handleAxiosError(error));
|
||
}
|
||
};
|
||
|
||
const handleAvgPerformanceReport = async () => {
|
||
try {
|
||
const { data } = await avgResTimeAsync();
|
||
|
||
const formattedData = [data]?.map((t: any) => ({
|
||
"نرخ زمان پاسخگويي": formatDurationPersian(t.avgResolutionSeconds),
|
||
"نرخ دقيق بر حسب ثانيه": t.avgResolutionSeconds,
|
||
}));
|
||
exportToExcel("excel", formattedData, "گزارش نرخ پاسخگويي ");
|
||
} catch (error) {
|
||
console.log(error);
|
||
toast.error(handleAxiosError(error));
|
||
}
|
||
};
|
||
|
||
const handleCriticalTicketsReport = async () => {
|
||
try {
|
||
const { data } = await criticalTicketsAsync();
|
||
|
||
const formattedData = data?.map((t: any) => ({
|
||
"شماره تيكت": t.ticketNumber,
|
||
"واحد / بخش": t.department?.displayName,
|
||
"تلفن داخلي": t.internalPhone,
|
||
كاربر: t.createdBy,
|
||
"محل وقوع مشكل": t.location,
|
||
"نوع درخواست": requestType.find((p) => p.id === t.requestType)
|
||
?.displayName,
|
||
|
||
"كارشناس مربوطه": t.assignee?.fullname,
|
||
"دستگاه مربوطه": t.relatedSystem,
|
||
وضعيت: ticketStatuses.find((p) => p.id === t.status)?.displayName,
|
||
توضيحات: t.description,
|
||
|
||
"اقدامات كارشناس": t.helpdeskAction,
|
||
"يادداشت ها": t.finalNotes,
|
||
"تاريخ ثبت": new Date(t.createdAt).toLocaleDateString("fa-IR"),
|
||
}));
|
||
exportToExcel("excel", formattedData, "گزارش تيكت هاي بحراني");
|
||
} catch (error) {
|
||
console.log(error);
|
||
toast.error(handleAxiosError(error));
|
||
}
|
||
};
|
||
return (
|
||
<div>
|
||
<Box
|
||
sx={{
|
||
display: "grid",
|
||
// ریسپانسیو بودن: در موبایل ۱ ستون، در تبلت ۲، در دسکتاپ ۴ ستون
|
||
gridTemplateColumns: {
|
||
xs: "1fr",
|
||
sm: "1fr 1fr",
|
||
md: "repeat(6, 1fr)",
|
||
},
|
||
gap: 3,
|
||
}}
|
||
>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
آمار کلی تیکتها{" "}
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
onClick={handleGetStatsReport}
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
گزارش عملکرد دپارتمانها
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
onClick={handleDepReport}
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
گزارش عملکرد کارشناسان
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
onClick={handleAgentPerformanceReport}
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
میانگین زمان پاسخگویی
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
onClick={handleAvgPerformanceReport}
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
تیکتهای بحرانی
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
onClick={handleCriticalTicketsReport}
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
روند ثبت تیکتها{" "}
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
نرخ بستن تیکتها
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
تیکتهای خارج از SLA
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
گزارش قدمت تیکتها
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
بهرهوری کارشناسان
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
بار کاری دپارتمانها{" "}
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
شاخصهای کلیدی عملکرد (KPI){" "}
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
<Card
|
||
sx={{
|
||
aspectRatio: "1/1", // مربع کردن کارت
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "space-between",
|
||
transition: "0.3s",
|
||
"&:hover": { boxShadow: 6, transform: "translateY(-5px)" },
|
||
}}
|
||
>
|
||
<CardContent>
|
||
<Typography variant="h6" align="center" gutterBottom>
|
||
پیشبینی وضعیت تیکتها{" "}
|
||
</Typography>
|
||
</CardContent>
|
||
|
||
<Stack spacing={1} sx={{ p: 2 }}>
|
||
{/* <Button
|
||
variant="contained"
|
||
startIcon={<VisibilityIcon />}
|
||
fullWidth
|
||
>
|
||
مشاهده
|
||
</Button> */}
|
||
<Button
|
||
variant="outlined"
|
||
startIcon={<DownloadOutlined />}
|
||
fullWidth
|
||
>
|
||
اکسل
|
||
</Button>
|
||
</Stack>
|
||
</Card>
|
||
</Box>
|
||
</div>
|
||
);
|
||
}
|