Split agent workload chart on /stats into one chart per status
Previously showed a single combined bar chart across all ticket statuses; now renders a separate sorted bar chart per status (new/open/pending/closed), each scaled to its own max. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012o9j9RezxbZVKQMrB7oRLY
This commit is contained in:
1 parent
fcf8511ac7
commit
bae653b7a9
2 files changed
+57
-32
No files matched your search
+26
-14
@@ -705,7 +705,7 @@ export interface StatsOverview {
|
||||
statusCounts: Record<TicketStatus, number>;
|
||||
channelCounts: Record<TicketChannel, number>;
|
||||
ticketsPerDay: { label: string; count: number }[];
|
||||
agentWorkload: { name: string; ticketCount: number }[];
|
||||
agentWorkloadByStatus: Record<TicketStatus, { name: string; count: number }[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -771,20 +771,32 @@ export async function getStatsOverview(): Promise<StatsOverview> {
|
||||
: null;
|
||||
|
||||
const agents = await listAgents();
|
||||
const ticketCountByAgent = new Map<string, number>();
|
||||
let unassignedCount = 0;
|
||||
for (const t of allTickets) {
|
||||
if (t.assigneeId) {
|
||||
ticketCountByAgent.set(t.assigneeId, (ticketCountByAgent.get(t.assigneeId) ?? 0) + 1);
|
||||
} else {
|
||||
unassignedCount += 1;
|
||||
|
||||
/** Per-agent ticket count for one status, sorted busiest-first. */
|
||||
function workloadForStatus(status: TicketStatus): { name: string; count: number }[] {
|
||||
const countByAgent = new Map<string, number>();
|
||||
let unassignedCount = 0;
|
||||
for (const t of allTickets) {
|
||||
if (t.status !== status) continue;
|
||||
if (t.assigneeId) {
|
||||
countByAgent.set(t.assigneeId, (countByAgent.get(t.assigneeId) ?? 0) + 1);
|
||||
} else {
|
||||
unassignedCount += 1;
|
||||
}
|
||||
}
|
||||
const workload = agents.map((a) => ({ name: a.name, count: countByAgent.get(a.id) ?? 0 }));
|
||||
if (unassignedCount > 0) {
|
||||
workload.push({ name: "Не назначено", count: unassignedCount });
|
||||
}
|
||||
return workload.sort((a, b) => b.count - a.count);
|
||||
}
|
||||
const agentWorkload = agents.map((a) => ({ name: a.name, ticketCount: ticketCountByAgent.get(a.id) ?? 0 }));
|
||||
if (unassignedCount > 0) {
|
||||
agentWorkload.push({ name: "Не назначено", ticketCount: unassignedCount });
|
||||
}
|
||||
agentWorkload.sort((a, b) => b.ticketCount - a.ticketCount);
|
||||
|
||||
const agentWorkloadByStatus: Record<TicketStatus, { name: string; count: number }[]> = {
|
||||
new: workloadForStatus("new"),
|
||||
open: workloadForStatus("open"),
|
||||
pending: workloadForStatus("pending"),
|
||||
closed: workloadForStatus("closed"),
|
||||
};
|
||||
|
||||
return {
|
||||
totalTickets: allTickets.length,
|
||||
@@ -794,6 +806,6 @@ export async function getStatsOverview(): Promise<StatsOverview> {
|
||||
statusCounts,
|
||||
channelCounts,
|
||||
ticketsPerDay,
|
||||
agentWorkload,
|
||||
agentWorkloadByStatus,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user