feat(helpdesk): add trend delta indicator per agent in team dashboard
Shows a small arrow next to the ticket count in each agent card header: ↑3 (orange) = received 3 more than resolved → backlog growing ↓2 (green) = resolved 2 more than received → backlog shrinking Hidden when delta is 0 (stable). Delta is computed from received_in_period (tickets created in the selected period assigned to this agent) minus resolved_in_period. No snapshot storage needed — derived from existing ticket data. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1621,6 +1621,7 @@ class DebitorDetailService
|
|||||||
'critical_tickets' => 0,
|
'critical_tickets' => 0,
|
||||||
'age_hours_sum' => 0,
|
'age_hours_sum' => 0,
|
||||||
'resolved_in_period' => 0,
|
'resolved_in_period' => 0,
|
||||||
|
'received_in_period' => 0,
|
||||||
'open_ticket_details' => [],
|
'open_ticket_details' => [],
|
||||||
'resolved_customers' => [],
|
'resolved_customers' => [],
|
||||||
'resolved_categories' => [],
|
'resolved_categories' => [],
|
||||||
@@ -1631,6 +1632,9 @@ class DebitorDetailService
|
|||||||
|
|
||||||
if ($isClosed) {
|
if ($isClosed) {
|
||||||
$createdTs = self::parseIsoToTimestamp((string) ($ticket['Created_On'] ?? ''));
|
$createdTs = self::parseIsoToTimestamp((string) ($ticket['Created_On'] ?? ''));
|
||||||
|
if ($createdTs !== null && $createdTs >= $periodStart) {
|
||||||
|
$agents[$normalizedUser]['received_in_period']++;
|
||||||
|
}
|
||||||
if ($activityTs !== null && $activityTs >= $periodStart) {
|
if ($activityTs !== null && $activityTs >= $periodStart) {
|
||||||
$agents[$normalizedUser]['resolved_in_period']++;
|
$agents[$normalizedUser]['resolved_in_period']++;
|
||||||
$globalResolved++;
|
$globalResolved++;
|
||||||
@@ -1659,6 +1663,11 @@ class DebitorDetailService
|
|||||||
$agents[$normalizedUser]['open_tickets']++;
|
$agents[$normalizedUser]['open_tickets']++;
|
||||||
$globalOpen++;
|
$globalOpen++;
|
||||||
|
|
||||||
|
$createdTs = self::parseIsoToTimestamp((string) ($ticket['Created_On'] ?? ''));
|
||||||
|
if ($createdTs !== null && $createdTs >= $periodStart) {
|
||||||
|
$agents[$normalizedUser]['received_in_period']++;
|
||||||
|
}
|
||||||
|
|
||||||
if ($rawUser === '') {
|
if ($rawUser === '') {
|
||||||
$globalUnassigned++;
|
$globalUnassigned++;
|
||||||
}
|
}
|
||||||
@@ -1733,6 +1742,8 @@ class DebitorDetailService
|
|||||||
'critical_tickets' => $agent['critical_tickets'],
|
'critical_tickets' => $agent['critical_tickets'],
|
||||||
'avg_age_hours' => $avgAge,
|
'avg_age_hours' => $avgAge,
|
||||||
'resolved_in_period' => $agent['resolved_in_period'],
|
'resolved_in_period' => $agent['resolved_in_period'],
|
||||||
|
'received_in_period' => $agent['received_in_period'],
|
||||||
|
'trend_delta' => $agent['received_in_period'] - $agent['resolved_in_period'],
|
||||||
'open_ticket_details' => $details,
|
'open_ticket_details' => $details,
|
||||||
'performance' => [
|
'performance' => [
|
||||||
'top_customers' => array_map(
|
'top_customers' => array_map(
|
||||||
|
|||||||
@@ -220,6 +220,22 @@
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Team workload — trend delta indicator */
|
||||||
|
.helpdesk-team-trend-up,
|
||||||
|
.helpdesk-team-trend-down {
|
||||||
|
font-size: var(--text-xs, 0.75rem);
|
||||||
|
font-weight: 600;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helpdesk-team-trend-up {
|
||||||
|
color: var(--app-warning, #f59e0b);
|
||||||
|
}
|
||||||
|
|
||||||
|
.helpdesk-team-trend-down {
|
||||||
|
color: var(--app-success, #198754);
|
||||||
|
}
|
||||||
|
|
||||||
/* Team workload — inline avatar for section titles */
|
/* Team workload — inline avatar for section titles */
|
||||||
.helpdesk-team-avatar-inline {
|
.helpdesk-team-avatar-inline {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -110,6 +110,15 @@ if (container) {
|
|||||||
title.appendChild(document.createTextNode(name));
|
title.appendChild(document.createTextNode(name));
|
||||||
|
|
||||||
title.appendChild(h('span', 'helpdesk-team-title-count', count));
|
title.appendChild(h('span', 'helpdesk-team-title-count', count));
|
||||||
|
|
||||||
|
// Trend delta: ↑3 (growing) or ↓2 (shrinking)
|
||||||
|
const delta = m.trend_delta ?? 0;
|
||||||
|
if (delta !== 0) {
|
||||||
|
const arrow = delta > 0 ? '↑' : '↓';
|
||||||
|
const cls = delta > 0 ? 'helpdesk-team-trend-up' : 'helpdesk-team-trend-down';
|
||||||
|
title.appendChild(h('span', cls, arrow + Math.abs(delta)));
|
||||||
|
}
|
||||||
|
|
||||||
section.appendChild(title);
|
section.appendChild(title);
|
||||||
|
|
||||||
// Ticket table
|
// Ticket table
|
||||||
|
|||||||
Reference in New Issue
Block a user