Count agent workload stats across all statuses, sorted by count

The "agent workload" chart on the stats page only counted non-closed
tickets. Now it counts every ticket regardless of status and sorts
agents descending by count, so the busiest agent (by total ticket
volume, not just currently-open) shows first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012o9j9RezxbZVKQMrB7oRLY
This commit is contained in:
ogrechkoandClaude Sonnet 5 committed 2026-08-08 12:16:58 +00:00
1 parent 3416d82d4f
commit fcf8511ac7
2 files changed
+12 -12

No files matched your search

+3 -3
View File
@@ -28,7 +28,7 @@ export default async function StatsPage() {
const stats = await getStatsOverview(); const stats = await getStatsOverview();
const maxChannelCount = Math.max(...Object.values(stats.channelCounts), 1); const maxChannelCount = Math.max(...Object.values(stats.channelCounts), 1);
const maxAgentWorkload = Math.max(...stats.agentWorkload.map((a) => a.openCount), 1); const maxAgentWorkload = Math.max(...stats.agentWorkload.map((a) => a.ticketCount), 1);
return ( return (
<div> <div>
@@ -89,7 +89,7 @@ export default async function StatsPage() {
</div> </div>
<div className="card p-4 lg:col-span-2"> <div className="card p-4 lg:col-span-2">
<h2 className="mb-3 text-sm font-semibold text-text-muted">Загрузка агентов (открытые заявки)</h2> <h2 className="mb-3 text-sm font-semibold text-text-muted">Заявки по агентам (все статусы)</h2>
{stats.agentWorkload.length === 0 ? ( {stats.agentWorkload.length === 0 ? (
<p className="text-sm text-text-faint">Пока нет данных.</p> <p className="text-sm text-text-faint">Пока нет данных.</p>
) : ( ) : (
@@ -98,7 +98,7 @@ export default async function StatsPage() {
<HorizontalBar <HorizontalBar
key={agent.name} key={agent.name}
label={agent.name} label={agent.name}
value={agent.openCount} value={agent.ticketCount}
max={maxAgentWorkload} max={maxAgentWorkload}
colorClass="bg-chart-1" colorClass="bg-chart-1"
/> />
+9 -9
View File
@@ -705,7 +705,7 @@ export interface StatsOverview {
statusCounts: Record<TicketStatus, number>; statusCounts: Record<TicketStatus, number>;
channelCounts: Record<TicketChannel, number>; channelCounts: Record<TicketChannel, number>;
ticketsPerDay: { label: string; count: number }[]; ticketsPerDay: { label: string; count: number }[];
agentWorkload: { name: string; openCount: number }[]; agentWorkload: { name: string; ticketCount: number }[];
} }
/** /**
@@ -771,20 +771,20 @@ export async function getStatsOverview(): Promise<StatsOverview> {
: null; : null;
const agents = await listAgents(); const agents = await listAgents();
const openCountByAgent = new Map<string, number>(); const ticketCountByAgent = new Map<string, number>();
let unassignedOpen = 0; let unassignedCount = 0;
for (const t of allTickets) { for (const t of allTickets) {
if (t.status === "closed") continue;
if (t.assigneeId) { if (t.assigneeId) {
openCountByAgent.set(t.assigneeId, (openCountByAgent.get(t.assigneeId) ?? 0) + 1); ticketCountByAgent.set(t.assigneeId, (ticketCountByAgent.get(t.assigneeId) ?? 0) + 1);
} else { } else {
unassignedOpen += 1; unassignedCount += 1;
} }
} }
const agentWorkload = agents.map((a) => ({ name: a.name, openCount: openCountByAgent.get(a.id) ?? 0 })); const agentWorkload = agents.map((a) => ({ name: a.name, ticketCount: ticketCountByAgent.get(a.id) ?? 0 }));
if (unassignedOpen > 0) { if (unassignedCount > 0) {
agentWorkload.push({ name: "Не назначено", openCount: unassignedOpen }); agentWorkload.push({ name: "Не назначено", ticketCount: unassignedCount });
} }
agentWorkload.sort((a, b) => b.ticketCount - a.ticketCount);
return { return {
totalTickets: allTickets.length, totalTickets: allTickets.length,