diff --git a/modules/helpdesk/module.php b/modules/helpdesk/module.php
index 1f2f579..81ef5ba 100644
--- a/modules/helpdesk/module.php
+++ b/modules/helpdesk/module.php
@@ -23,6 +23,7 @@ return [
['path' => 'helpdesk/domain-detail-data', 'target' => 'helpdesk/domain-detail-data'],
['path' => 'helpdesk/debitor/{id}', 'target' => 'helpdesk/debitor'],
['path' => 'helpdesk/ticket/{id}', 'target' => 'helpdesk/ticket'],
+ ['path' => 'helpdesk/ticket-fragment/{id}', 'target' => 'helpdesk/ticket-fragment'],
['path' => 'helpdesk/settings', 'target' => 'helpdesk/settings'],
['path' => 'helpdesk/settings/test-connection-data', 'target' => 'helpdesk/settings/test-connection-data'],
['path' => 'helpdesk/settings/diagnose-data', 'target' => 'helpdesk/settings/diagnose-data'],
diff --git a/modules/helpdesk/pages/helpdesk/ticket(default).phtml b/modules/helpdesk/pages/helpdesk/ticket(default).phtml
index 5af11ca..b811fde 100644
--- a/modules/helpdesk/pages/helpdesk/ticket(default).phtml
+++ b/modules/helpdesk/pages/helpdesk/ticket(default).phtml
@@ -20,142 +20,19 @@ $ticketCommunicationUrl = $ticketCommunicationUrl ?? '';
$backUrl = $ticketCustomerNo !== '' ? lurl('helpdesk/debitor/' . rawurlencode($ticketCustomerNo)) : lurl('helpdesk');
-?>
-
-
- t('Ticket') . ' ' . $ticketNo,
- 'backHref' => $backUrl,
- 'backTitle' => t('Back'),
- 'actions' => $ticket !== null ? [
- [
- 'label' => t('Refresh data'),
- 'type' => 'button',
- 'name' => 'ticket-refresh',
- 'class' => 'secondary outline',
- ],
- ] : [],
- ];
- require templatePath('partials/app-details-titlebar.phtml');
- ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- format('d.m.Y H:i')
- : '—';
- $lastActivityRaw = (string) ($ticket['Last_Activity_Date'] ?? '');
- $lastActivityFormatted = $lastActivityRaw !== '' && $lastActivityRaw !== '0001-01-01T00:00:00Z'
- ? (new DateTimeImmutable($lastActivityRaw))->format('d.m.Y H:i')
- : '—';
- $ticketState = (string) ($ticket['Ticket_State'] ?? '');
-
- // Compute ticket age
- $ageLabel = '—';
- if ($createdRaw !== '' && $createdRaw !== '0001-01-01T00:00:00Z') {
- $createdDt = new DateTimeImmutable($createdRaw);
- $diff = $createdDt->diff(new DateTimeImmutable('now'));
- if ($diff->days >= 1) {
- $ageLabel = $diff->days . ' ' . ($diff->days === 1 ? t('day') : t('days'));
- } else {
- $hours = $diff->h + ($diff->days * 24);
- $ageLabel = max(1, $hours) . ' ' . t('hours');
- }
- }
- ?>
-
-
-
-
-
-
+$titlebar = [
+ 'title' => t('Ticket') . ' ' . $ticketNo,
+ 'backHref' => $backUrl,
+ 'backTitle' => t('Back'),
+ 'actions' => $ticket !== null ? [
+ [
+ 'label' => t('Refresh data'),
+ 'type' => 'button',
+ 'name' => 'ticket-refresh',
+ 'class' => 'secondary outline',
+ ],
+ ] : [],
+];
+require templatePath('partials/app-details-titlebar.phtml');
+require templatePath('partials/app-flash.phtml');
+require __DIR__ . '/../../templates/helpdesk-ticket-detail.phtml';
diff --git a/modules/helpdesk/pages/helpdesk/ticket-fragment($id).php b/modules/helpdesk/pages/helpdesk/ticket-fragment($id).php
new file mode 100644
index 0000000..d7ad74c
--- /dev/null
+++ b/modules/helpdesk/pages/helpdesk/ticket-fragment($id).php
@@ -0,0 +1,37 @@
+query('from', ''));
+
+if ($ticketNo === '') {
+ http_response_code(400);
+ $ticket = null;
+ return;
+}
+
+$gateway = app(BcODataGateway::class);
+
+$connectionError = false;
+try {
+ $ticket = $gateway->getTicket($ticketNo);
+} catch (\Throwable) {
+ $ticket = null;
+ $connectionError = true;
+}
+
+if ($ticket === null && !$connectionError) {
+ http_response_code(404);
+ return;
+}
+
+$ticketCustomerNo = $fromCustomerNo;
+$ticketDescription = (string) ($ticket['Description'] ?? $ticketNo);
+$ticketCommunicationUrl = lurl('helpdesk/ticket-communication-data');
diff --git a/modules/helpdesk/pages/helpdesk/ticket-fragment(none).phtml b/modules/helpdesk/pages/helpdesk/ticket-fragment(none).phtml
new file mode 100644
index 0000000..2b09c74
--- /dev/null
+++ b/modules/helpdesk/pages/helpdesk/ticket-fragment(none).phtml
@@ -0,0 +1,5 @@
+
+
+
+
+
+ format('d.m.Y H:i')
+ : '—';
+ $lastActivityRaw = (string) ($ticket['Last_Activity_Date'] ?? '');
+ $lastActivityFormatted = $lastActivityRaw !== '' && $lastActivityRaw !== '0001-01-01T00:00:00Z'
+ ? (new DateTimeImmutable($lastActivityRaw))->format('d.m.Y H:i')
+ : '—';
+ $ticketState = (string) ($ticket['Ticket_State'] ?? '');
+
+ $ageLabel = '—';
+ if ($createdRaw !== '' && $createdRaw !== '0001-01-01T00:00:00Z') {
+ $createdDt = new DateTimeImmutable($createdRaw);
+ $diff = $createdDt->diff(new DateTimeImmutable('now'));
+ if ($diff->days >= 1) {
+ $ageLabel = $diff->days . ' ' . ($diff->days === 1 ? t('day') : t('days'));
+ } else {
+ $hours = $diff->h + ($diff->days * 24);
+ $ageLabel = max(1, $hours) . ' ' . t('hours');
+ }
+ }
+ ?>
+
+
+
+
+
+
diff --git a/modules/helpdesk/web/js/helpdesk-detail.js b/modules/helpdesk/web/js/helpdesk-detail.js
index fae4dfc..5f398e8 100644
--- a/modules/helpdesk/web/js/helpdesk-detail.js
+++ b/modules/helpdesk/web/js/helpdesk-detail.js
@@ -10,6 +10,8 @@ import { initListSection } from '/js/core/app-list-page-module.js';
import { getJson } from '/js/core/app-http.js';
import { resolveHost } from '/js/core/app-dom.js';
import { readPageConfig } from '/js/core/app-page-config.js';
+import { initDetailDrawer } from '/js/components/app-detail-drawer.js';
+import { initHelpdeskTicket } from './helpdesk-ticket.js';
import {
renderCommunicationError,
renderCommunicationFeed,
@@ -776,7 +778,7 @@ function init(container) {
{
name: labels.ticketNo || 'Ticket No.',
sort: true,
- formatter: (cell) => gridjs.html(`${cell.no}`),
+ formatter: (cell) => gridjs.html(`${cell.no}`),
},
{ name: labels.description || 'Description', sort: false },
{
@@ -816,10 +818,13 @@ function init(container) {
return url || '';
},
},
- rowInteraction: { linkColumn: 0 },
+ rowInteraction: { linkColumn: false },
+ rowDataset: (row) => ({
+ uuid: row?.cells?.[0]?.data?.no || '',
+ }),
};
- initListSection({
+ const section = initListSection({
moduleId: 'helpdesk-detail-tickets',
initErrorMessage: 'Helpdesk tickets grid init failed',
initOptions: {
@@ -832,6 +837,26 @@ function init(container) {
},
});
ticketsGridInitialized = true;
+
+ initDetailDrawer({
+ gridConfig: section?.gridConfig || null,
+ triggerSelector: '[data-drawer-trigger][data-ticket-no]',
+ rowUuidAttr: 'uuid',
+ fetchUrl: (ticketNo) => new URL(`helpdesk/ticket-fragment/${encodeURIComponent(ticketNo)}?from=${encodeURIComponent(customerNo || '')}`, appBase).toString(),
+ fullUrl: (ticketNo) => new URL(`helpdesk/ticket/${encodeURIComponent(ticketNo)}?from=${encodeURIComponent(customerNo || '')}`, appBase).toString(),
+ hashPrefix: 'ticket',
+ onContentLoaded: (contentEl) => {
+ try { initHelpdeskTicket(contentEl); } catch (err) { console.warn('[helpdesk-detail] initHelpdeskTicket failed', err); }
+ },
+ labels: {
+ close: labels.drawerClose || 'Close',
+ previous: labels.drawerPrev || 'Previous',
+ next: labels.drawerNext || 'Next',
+ openFull: labels.drawerOpenFull || 'Open full page',
+ loading: labels.drawerLoading || 'Loading',
+ error: labels.drawerError || 'Failed to load',
+ },
+ });
} finally {
ticketsGridInitializing = false;
}