fix(helpdesk): neutral count badges, bordered tables, critical legend

- Count badge in section title is always neutral (no warning color)
- Critical highlighting only on ticket number, not entire row
- Ticket tables have border + border-radius + subtle header background
  matching the existing table widget pattern
- Legend at bottom explains the warning color when critical tickets exist

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 19:24:37 +02:00
parent 70bfbbdc30
commit 49c3741c66
3 changed files with 51 additions and 15 deletions

View File

@@ -21,6 +21,7 @@ $periodLabels = [
data-label-tickets="<?php e(t('Tickets')); ?>"
data-label-error="<?php e(t('Could not load team dashboard.')); ?>"
data-label-empty="<?php e(t('No team data available.')); ?>"
data-label-critical="<?php e(t('Critical (>48h open)')); ?>"
>
<section>
<?php

View File

@@ -143,7 +143,7 @@
vertical-align: middle;
}
/* Count badge in section title */
/* Count badge in section title — always neutral */
.helpdesk-team-title-count {
font-variant-numeric: tabular-nums;
font-weight: 600;
@@ -154,27 +154,27 @@
color: var(--app-muted-color);
}
.helpdesk-team-title-count-warning {
background: color-mix(in srgb, var(--app-warning, #f59e0b) 15%, transparent);
color: var(--app-warning, #f59e0b);
}
/* Ticket table inside agent widget */
/* Ticket table inside agent widget — bordered like table widgets */
.helpdesk-team-ticket-table {
width: 100%;
font-size: var(--text-sm, 0.875rem);
border: 1px solid var(--app-muted-border-color);
border-radius: var(--app-radius, 0.375rem);
border-spacing: 0;
overflow: hidden;
}
.helpdesk-team-ticket-table th {
text-align: left;
font-weight: 500;
color: var(--app-muted-color);
padding: calc(var(--app-spacing) * 0.25) calc(var(--app-spacing) * 0.4);
padding: calc(var(--app-spacing) * 0.3) calc(var(--app-spacing) * 0.5);
border-bottom: 1px solid var(--app-muted-border-color);
background: color-mix(in srgb, var(--app-muted-border-color) 20%, transparent);
}
.helpdesk-team-ticket-table td {
padding: calc(var(--app-spacing) * 0.3) calc(var(--app-spacing) * 0.4);
padding: calc(var(--app-spacing) * 0.35) calc(var(--app-spacing) * 0.5);
border-bottom: 1px solid color-mix(in srgb, var(--app-muted-border-color) 40%, transparent);
}
@@ -187,12 +187,37 @@
font-weight: 500;
}
.helpdesk-team-ticket-critical td {
/* Critical: only highlight the ticket number, not the entire row */
.helpdesk-team-ticket-critical .helpdesk-team-ticket-no {
color: var(--app-warning, #f59e0b);
font-weight: 600;
}
.helpdesk-team-ticket-critical .helpdesk-team-ticket-no {
font-weight: 600;
/* Legend */
.helpdesk-team-legend {
display: flex;
align-items: center;
gap: calc(var(--app-spacing) * 0.75);
margin-top: calc(var(--app-spacing) * 0.75);
font-size: var(--text-xs, 0.75rem);
color: var(--app-muted-color);
}
.helpdesk-team-legend-item {
display: inline-flex;
align-items: center;
gap: 0.35em;
}
.helpdesk-team-legend-dot {
width: 0.55rem;
height: 0.55rem;
border-radius: 50%;
flex-shrink: 0;
}
.helpdesk-team-legend-dot-warning {
background: var(--app-warning, #f59e0b);
}
/* Performance tab — compact rows */

View File

@@ -9,6 +9,7 @@ if (container) {
const dataUrl = container.dataset.teamWorkloadUrl;
const labelQueue = container.dataset.labelQueue || 'Queue';
const labelTickets = container.dataset.labelTickets || 'Tickets';
const labelCritical = container.dataset.labelCritical || 'Critical (>48h open)';
const elLoading = document.getElementById('team-loading');
const elError = document.getElementById('team-error');
@@ -87,9 +88,7 @@ if (container) {
}
title.appendChild(document.createTextNode(name));
const badge = h('span', 'helpdesk-team-title-count', count);
if (m.critical_tickets > 0) badge.classList.add('helpdesk-team-title-count-warning');
title.appendChild(badge);
title.appendChild(h('span', 'helpdesk-team-title-count', count));
section.appendChild(title);
// Ticket table
@@ -139,6 +138,17 @@ if (container) {
if (queue) elCurrentCards.appendChild(buildAgentWidget(queue, true));
for (const m of agents) elCurrentCards.appendChild(buildAgentWidget(m, false));
// Legend
const hasCritical = members.some(m => m.critical_tickets > 0);
if (hasCritical) {
const legend = h('div', 'helpdesk-team-legend');
const item = h('span', 'helpdesk-team-legend-item');
item.appendChild(h('span', 'helpdesk-team-legend-dot helpdesk-team-legend-dot-warning'));
item.appendChild(h('span', '', labelCritical));
legend.appendChild(item);
elCurrentCards.appendChild(legend);
}
}
function renderPerformanceTab(members) {