feat(helpdesk): enrich team ticket table with links, customer name, description, last activity

- Switch gateway from PBI_LV_Tickets to PBI_FP_Tickets to get
  Description and Company_Contact_Name fields
- Ticket number links to ticket detail page
- Customer column shows Company_Contact_Name with link to debitor detail
- Description column with text-overflow ellipsis
- Last activity column shows formatted date (was: age in hours)
- Backend provides last_activity ISO string and customer_name per ticket
- Table headers use i18n labels via data attributes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 19:29:02 +02:00
parent 8fd742141c
commit 98f703b231
5 changed files with 82 additions and 14 deletions

View File

@@ -202,10 +202,36 @@
.helpdesk-team-ticket-no {
font-variant-numeric: tabular-nums;
font-weight: 500;
white-space: nowrap;
}
.helpdesk-team-ticket-no a,
.helpdesk-team-ticket-table td a {
color: inherit;
text-decoration: none;
}
.helpdesk-team-ticket-no a:hover,
.helpdesk-team-ticket-table td a:hover {
color: var(--app-primary, #0d6efd);
text-decoration: underline;
}
.helpdesk-team-ticket-desc {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 20ch;
}
.helpdesk-team-ticket-date {
white-space: nowrap;
color: var(--app-muted-color);
}
/* Critical: only highlight the ticket number, not the entire row */
.helpdesk-team-ticket-critical .helpdesk-team-ticket-no {
.helpdesk-team-ticket-critical .helpdesk-team-ticket-no,
.helpdesk-team-ticket-critical .helpdesk-team-ticket-no a {
color: var(--app-warning, #f59e0b);
font-weight: 600;
}

View File

@@ -10,6 +10,8 @@ if (container) {
const labelQueue = container.dataset.labelQueue || 'Queue';
const labelTickets = container.dataset.labelTickets || 'Tickets';
const labelCritical = container.dataset.labelCritical || 'Critical (>48h open)';
const ticketBaseUrl = container.dataset.ticketBaseUrl || '';
const debitorBaseUrl = container.dataset.debitorBaseUrl || '';
const elLoading = document.getElementById('team-loading');
const elError = document.getElementById('team-error');
@@ -55,18 +57,46 @@ if (container) {
return d.toLocaleDateString(undefined, { day: '2-digit', month: '2-digit', year: 'numeric' });
}
function formatDateTime(isoString) {
if (!isoString) return '—';
const d = new Date(isoString);
if (isNaN(d.getTime())) return '—';
return d.toLocaleDateString(undefined, { day: '2-digit', month: '2-digit', year: 'numeric' });
}
/**
* Build a ticket table row: No | Customer | Last activity | Age
* Build a ticket table row: No (link) | Customer (link) | Description | Last activity
*/
function buildTicketRow(t) {
const tr = h('tr', t.critical ? 'helpdesk-team-ticket-critical' : '');
const noCell = h('td', 'helpdesk-team-ticket-no', t.no);
// Ticket number as link
const noCell = h('td', 'helpdesk-team-ticket-no');
if (ticketBaseUrl && t.no) {
const a = h('a', '', t.no);
a.href = ticketBaseUrl + encodeURIComponent(t.no);
noCell.appendChild(a);
} else {
noCell.textContent = t.no || '—';
}
tr.appendChild(noCell);
tr.appendChild(h('td', '', t.customer || '—'));
tr.appendChild(h('td', '', t.description || '—'));
const ageCell = h('td', '', formatAge(t.age_hours));
tr.appendChild(ageCell);
// Customer name as link to debitor
const customerCell = h('td');
if (debitorBaseUrl && t.customer_name) {
const a = h('a', '', t.customer_name);
a.href = debitorBaseUrl + encodeURIComponent(t.customer_name);
customerCell.appendChild(a);
} else {
customerCell.textContent = t.customer_name || '—';
}
tr.appendChild(customerCell);
// Description
tr.appendChild(h('td', 'helpdesk-team-ticket-desc', t.description || '—'));
// Last activity date
tr.appendChild(h('td', 'helpdesk-team-ticket-date', formatDateTime(t.last_activity)));
return tr;
}
@@ -97,10 +127,10 @@ if (container) {
const table = h('table', 'helpdesk-team-ticket-table');
const thead = h('thead');
const headRow = h('tr');
headRow.appendChild(h('th', '', 'Ticket'));
headRow.appendChild(h('th', '', 'Kunde'));
headRow.appendChild(h('th', '', 'Beschreibung'));
headRow.appendChild(h('th', '', 'Alter'));
headRow.appendChild(h('th', '', container.dataset.labelTicket || 'Ticket'));
headRow.appendChild(h('th', '', container.dataset.labelCustomer || 'Customer'));
headRow.appendChild(h('th', '', container.dataset.labelDescription || 'Description'));
headRow.appendChild(h('th', '', container.dataset.labelLastActivity || 'Last activity'));
thead.appendChild(headRow);
table.appendChild(thead);