Add SSE live updates for bestellungen
This commit is contained in:
@@ -352,3 +352,28 @@ SQL;
|
||||
'next_limit' => min($totalCount, $limit + $pageSize),
|
||||
];
|
||||
}
|
||||
|
||||
function get_sales_order_realtime_snapshot(PDO $pdo, int $limit = 1000): array
|
||||
{
|
||||
$limit = max(1, min(2000, $limit));
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
'SELECT id, created_at, updated_at
|
||||
FROM public.sales_order
|
||||
ORDER BY updated_at DESC NULLS LAST, id DESC
|
||||
LIMIT :limit'
|
||||
);
|
||||
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
$rows = [];
|
||||
foreach ($stmt->fetchAll() as $row) {
|
||||
$rows[] = [
|
||||
'id' => (int) ($row['id'] ?? 0),
|
||||
'created_at' => (string) ($row['created_at'] ?? ''),
|
||||
'updated_at' => (string) ($row['updated_at'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ function auth_render_bestellungen_large_table(array $bestellungenTable): string
|
||||
$city = (string) ($row['city'] ?? '');
|
||||
$country = (string) ($row['country_name'] ?? '');
|
||||
|
||||
$html[] = '<div class="' . $rowClass . '" role="row" data-component-part="large-table-row" data-bestellungen-row="true">';
|
||||
$html[] = '<div class="' . $rowClass . '" role="row" data-component-part="large-table-row" data-bestellungen-row="true" data-order-id="' . (int) ($row['id'] ?? 0) . '">';
|
||||
$html[] = '<div class="sg-large-table__cell" role="cell">' . auth_escape_html($orderDate) . '</div>';
|
||||
$html[] = '<div class="sg-large-table__cell" role="cell">';
|
||||
$html[] = '<a class="sg-hyperlink" href="#" aria-haspopup="dialog" aria-expanded="false" data-order-drawer-open="true" data-order-id="' . (int) ($row['id'] ?? 0) . '" data-order-number="' . auth_escape_html($orderNumber) . '" data-order-date="' . auth_escape_html($orderDate) . '" data-order-total="' . auth_escape_html($totalAmount) . '" data-order-first-name="' . auth_escape_html($firstName) . '" data-order-last-name="' . auth_escape_html($lastName) . '" data-order-street="' . auth_escape_html($street) . '" data-order-house-number="' . auth_escape_html($houseNumber) . '" data-order-zip="' . auth_escape_html($zip) . '" data-order-city="' . auth_escape_html($city) . '" data-order-country="' . auth_escape_html($country) . '">' . auth_escape_html($orderNumber) . '</a>';
|
||||
@@ -509,6 +509,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
||||
echo " mediaQuery.addEventListener('change', syncMode);";
|
||||
echo "})();";
|
||||
echo "let bestellungenTableHandlersInstalled = false;";
|
||||
echo "let bestellungenRealtimeSource = null;";
|
||||
echo "function initBestellungenBindings() {";
|
||||
echo " const contentRoot = document.querySelector('[data-left-navigation-content-body]');";
|
||||
echo " if (!contentRoot) { return; }";
|
||||
@@ -677,6 +678,74 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
||||
echo " }";
|
||||
echo " syncSearchState();";
|
||||
echo " };";
|
||||
echo " const getCurrentQueryParams = () => ({";
|
||||
echo " bestellungen_search: getSearchValue(),";
|
||||
echo " bestellungen_sort: getSortColumn(),";
|
||||
echo " bestellungen_dir: getSortDirection(),";
|
||||
echo " bestellungen_limit: getCurrentLimit(),";
|
||||
echo " });";
|
||||
echo " const getOpenDrawerOrderId = () => {";
|
||||
echo " const trigger = Array.from(contentRoot.querySelectorAll('[data-order-drawer-open]')).find((button) => button.getAttribute('aria-expanded') === 'true');";
|
||||
echo " return trigger ? (trigger.dataset.orderId || '') : '';";
|
||||
echo " };";
|
||||
echo " const reloadBestellungenSection = () => loadFragment(getCurrentQueryParams());";
|
||||
echo " const reloadBestellungenRow = async (orderId) => {";
|
||||
echo " const targetOrderId = String(orderId || '');";
|
||||
echo " if (targetOrderId === '') {";
|
||||
echo " await reloadBestellungenSection();";
|
||||
echo " return;";
|
||||
echo " }";
|
||||
echo " const response = await fetch(buildFragmentUrl(getCurrentQueryParams()).toString(), { credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } });";
|
||||
echo " if (!response.ok) {";
|
||||
echo " await reloadBestellungenSection();";
|
||||
echo " return;";
|
||||
echo " }";
|
||||
echo " const html = await response.text();";
|
||||
echo " const doc = new DOMParser().parseFromString(html, 'text/html');";
|
||||
echo " const newRow = Array.from(doc.querySelectorAll('[data-bestellungen-row]')).find((row) => (row.dataset.orderId || '') === targetOrderId) || null;";
|
||||
echo " const currentRow = Array.from(contentRoot.querySelectorAll('[data-bestellungen-row]')).find((row) => (row.dataset.orderId || '') === targetOrderId) || null;";
|
||||
echo " if (!newRow || !currentRow) {";
|
||||
echo " await reloadBestellungenSection();";
|
||||
echo " return;";
|
||||
echo " }";
|
||||
echo " const openDrawerOrderId = getOpenDrawerOrderId();";
|
||||
echo " currentRow.outerHTML = newRow.outerHTML;";
|
||||
echo " if (openDrawerOrderId === targetOrderId) {";
|
||||
echo " const reopenedTrigger = Array.from(contentRoot.querySelectorAll('[data-order-drawer-open]')).find((button) => (button.dataset.orderId || '') === targetOrderId) || null;";
|
||||
echo " if (reopenedTrigger) {";
|
||||
echo " openDrawer(reopenedTrigger);";
|
||||
echo " }";
|
||||
echo " }";
|
||||
echo " };";
|
||||
echo " const connectBestellungenRealtime = () => {";
|
||||
echo " if (!window.EventSource) { return null; }";
|
||||
echo " if (bestellungenRealtimeSource) {";
|
||||
echo " bestellungenRealtimeSource.close();";
|
||||
echo " }";
|
||||
echo " const source = new EventSource('/api/realtime/bestellungen.php', { withCredentials: true });";
|
||||
echo " source.addEventListener('bestellungen.changed', (event) => {";
|
||||
echo " const payload = parseJsonRealtimeEvent(event.data);";
|
||||
echo " if (!payload) { return; }";
|
||||
echo " const kind = String(payload.kind || '');";
|
||||
echo " const orderId = payload.orderId !== undefined && payload.orderId !== null ? String(payload.orderId) : '';";
|
||||
echo " if (kind === 'updated' && orderId !== '') {";
|
||||
echo " void reloadBestellungenRow(orderId);";
|
||||
echo " return;";
|
||||
echo " }";
|
||||
echo " void reloadBestellungenSection();";
|
||||
echo " });";
|
||||
echo " bestellungenRealtimeSource = source;";
|
||||
echo " return source;";
|
||||
echo " };";
|
||||
echo " const parseJsonRealtimeEvent = (raw) => {";
|
||||
echo " if (typeof raw !== 'string' || raw.trim() === '') { return null; }";
|
||||
echo " try {";
|
||||
echo " const parsed = JSON.parse(raw);";
|
||||
echo " return parsed && typeof parsed === 'object' ? parsed : null;";
|
||||
echo " } catch (error) {";
|
||||
echo " return null;";
|
||||
echo " }";
|
||||
echo " };";
|
||||
echo " if (!bestellungenTableHandlersInstalled) {";
|
||||
echo " bestellungenTableHandlersInstalled = true;";
|
||||
echo " contentRoot.addEventListener('click', (event) => {";
|
||||
@@ -727,6 +796,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
||||
echo " });";
|
||||
echo " }";
|
||||
echo " bindTable();";
|
||||
echo " connectBestellungenRealtime();";
|
||||
echo "}";
|
||||
echo "(() => {";
|
||||
echo " const overlay = document.querySelector('[data-otc-order-overlay]');";
|
||||
|
||||
Reference in New Issue
Block a user