Files
shomal-hospital-ticketing-f…/app/(panel)/reports/page.tsx
2026-05-23 13:22:10 +03:30

622 lines
19 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"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>
);
}