Quelltext des aktuellen Standes
// Deep-Link auf eine Bestellung (#order-N): Liegt die Karte in einem anderen
// als dem aktiven Tab (z. B. alter Ticket-Link auf "Offen", Bestellung ist
// inzwischen archiviert), zum richtigen Tab wechseln und hinscrollen.
document.addEventListener('DOMContentLoaded', function () {
var m = /^#order-(\d+)$/.exec(window.location.hash);
if (!m) { return; }
var card = document.getElementById('order-' + m[1]);
if (!card) { return; }
var panel = card.closest('.tab-panel');
if (panel && !panel.classList.contains('active')) {
switchTab(panel.getAttribute('data-panel'));
}
card.scrollIntoView({ block: 'center' });
});
// Tab-Umschaltung (clientseitig im Browse-Modus; im Such-/Filtermodus ohne
// lokale Panels wird serverseitig zum Tab gewechselt).
function switchTab(tab) {
var target = document.querySelector('.tab-panel[data-panel="' + tab + '"]');
if (!target) {
window.location.href = '/orders?tab=' + encodeURIComponent(tab);
return;
}
document.querySelectorAll('.subnav-tab').forEach(function(btn) {
btn.classList.toggle('active', btn.getAttribute('data-tab') === tab);
});
document.querySelectorAll('.tab-panel').forEach(function(panel) {
panel.classList.toggle('active', panel.getAttribute('data-panel') === tab);
});
var hidden = document.getElementById('ordersTabInput');
if (hidden) { hidden.value = tab; }
var url = new URL(window.location);
url.searchParams.set('tab', tab);
history.replaceState(null, '', url);
}
// Doppel-Submit verhindern (z. B. „Neue Bestellung" zweimal angeklickt).
function guardSubmit(form) {
if (form.dataset.submitting) { return false; }
form.dataset.submitting = '1';
setTimeout(function () {
var btn = form.querySelector('[type=submit]');
if (btn) { btn.disabled = true; }
}, 0);
return true;
}
// Kurze Bestätigungs-Meldung (überlebt einen Karten-Reload, da am Body).
function ordersToast(msg) {
var t = document.createElement('div');
t.textContent = msg;
t.style.cssText = 'position:fixed;bottom:20px;left:50%;transform:translateX(-50%);'
+ 'background:#16a34a;color:#fff;padding:.55rem 1.1rem;border-radius:6px;font-size:.85rem;'
+ 'z-index:3000;box-shadow:0 4px 16px rgba(0,0,0,.2);opacity:0;transition:opacity .2s;';
document.body.appendChild(t);
requestAnimationFrame(function () { t.style.opacity = '1'; });
setTimeout(function () { t.style.opacity = '0'; setTimeout(function () { t.remove(); }, 250); }, 1800);
}
// ── Modals: einheitliches Muster (.modal-overlay/.modal-card) ──────
// Öffnen/Schließen via style.display, plus Escape + Backdrop-Klick +
// data-modal-close. Gilt für alle Order-Modals (Neue Bestellung,
// Abholbereit-Bestätigung), damit sie sich projektweit gleich verhalten.
function openModal(modal) {
if (typeof modal === 'string') { modal = document.getElementById(modal); }
if (!modal) { return; }
modal.style.display = 'flex';
document.body.style.overflow = 'hidden';
var first = modal.querySelector('input:not([type=hidden]), select, textarea, button');
if (first) { first.focus(); }
}
function closeModal(modal) {
if (typeof modal === 'string') { modal = document.getElementById(modal); }
if (!modal) { return; }
modal.style.display = 'none';
// Body-Scroll nur freigeben, wenn kein weiteres Modal offen ist.
var stillOpen = Array.prototype.some.call(document.querySelectorAll('.modal-overlay'), function (m) {
return m.style.display === 'flex';
});
if (!stillOpen) { document.body.style.overflow = ''; }
}
// Backdrop-Klick + Close-Buttons
document.addEventListener('click', function (e) {
if (e.target.classList && e.target.classList.contains('modal-overlay')) {
closeModal(e.target);
return;
}
var closer = e.target.closest('[data-modal-close]');
if (closer) {
var m = closer.closest('.modal-overlay');
if (m) { closeModal(m); }
}
});
// Escape schließt das oberste offene Modal (person-search fängt Escape
// bei offenem Dropdown vorher ab -> dann bleibt das Modal offen).
document.addEventListener('keydown', function (e) {
if (e.key !== 'Escape') { return; }
var open = Array.prototype.filter.call(document.querySelectorAll('.modal-overlay'), function (m) {
return m.style.display === 'flex';
});
if (open.length) { closeModal(open[open.length - 1]); }
});
function openNewOrderModal() {
resetOrderCompRows();
openModal('newOrderModal');
var titleInput = document.querySelector('#newOrderModal input[name="title"]');
if (titleInput) { titleInput.focus(); }
}
function closeNewOrderModal() { closeModal('newOrderModal'); }
// ── Komponente bearbeiten: Inline-Edit-Form ein-/ausblenden ────────
function toggleCompEdit(btn) {
var item = btn.closest('.comp-item');
var form = item ? item.nextElementSibling : btn.closest('.comp-edit-form');
if (!form || !form.classList.contains('comp-edit-form')) { return; }
var row = form.previousElementSibling;
if (form.hasAttribute('hidden')) {
form.removeAttribute('hidden');
if (row) { row.style.display = 'none'; }
var inp = form.querySelector('.comp-edit-name');
if (inp) { inp.focus(); inp.select(); }
} else {
form.setAttribute('hidden', '');
if (row) { row.style.display = ''; }
}
}
// ── Kommentar bearbeiten: Inline-Edit-Form ein-/ausblenden ─────────
function toggleCommentEdit(btn) {
var item = btn.closest('.comment-item');
if (!item) { return; }
var form = item.querySelector('.comment-edit-form');
var body = item.querySelector('.comment-body');
if (!form) { return; }
form.removeAttribute('hidden');
if (body) { body.style.display = 'none'; }
var inp = form.querySelector('textarea');
if (inp) { inp.focus(); inp.select(); }
}
function cancelCommentEdit(btn) {
var item = btn.closest('.comment-item');
if (!item) { return; }
var form = item.querySelector('.comment-edit-form');
var body = item.querySelector('.comment-body');
if (form) { form.setAttribute('hidden', ''); }
if (body) { body.style.display = ''; }
}
// Komponenten-Zeilen (Name + Menge) im Neue-Bestellung-Modal
function ocBuildCompRow() {
var row = document.createElement('div');
row.className = 'oc-row';
row.innerHTML =
'<input type="text" name="comp_name[]" class="form-control oc-name" placeholder="z. B. Monitor Dell 27" autocomplete="off">' +
'<input type="number" name="comp_qty[]" class="form-control oc-qty" value="1" min="1" max="9999" title="Menge" aria-label="Menge">' +
'<button type="button" class="oc-row-remove" onclick="removeOrderCompRow(this)" aria-label="Zeile entfernen" title="Zeile entfernen">×</button>';
return row;
}
function addOrderCompRow() {
var rows = document.getElementById('order-comp-rows');
if (!rows) return;
var row = ocBuildCompRow();
rows.appendChild(row);
var inp = row.querySelector('.oc-name');
if (inp) inp.focus();
}
function removeOrderCompRow(btn) {
var rows = document.getElementById('order-comp-rows');
var row = btn.closest('.oc-row');
if (!rows || !row) return;
if (rows.querySelectorAll('.oc-row').length > 1) {
row.remove();
} else {
// Letzte Zeile nicht entfernen, nur leeren.
var n = row.querySelector('.oc-name'); if (n) n.value = '';
var q = row.querySelector('.oc-qty'); if (q) q.value = '1';
}
}
function resetOrderCompRows() {
var rows = document.getElementById('order-comp-rows');
if (!rows) return;
rows.innerHTML = '';
rows.appendChild(ocBuildCompRow());
}
// Enter im Namensfeld legt eine neue Zeile an, statt das Formular abzuschicken.
document.addEventListener('keydown', function (e) {
if (e.key !== 'Enter') return;
var t = e.target;
if (t && t.classList && t.classList.contains('oc-name')) {
e.preventDefault();
addOrderCompRow();
}
});
// Backdrop-Klick und Escape werden zentral von openModal/closeModal behandelt.
// Lieferart: Textfeld ein-/ausblenden
function handleDeliveryMethod(select) {
var noteInput = select.parentElement.querySelector('[name=delivery_note]');
if (!noteInput) return;
if (select.value === 'Abgeholt') {
noteInput.style.display = 'block';
noteInput.placeholder = 'Abgeholt von...';
noteInput.required = true;
} else if (select.value === 'Freitext') {
noteInput.style.display = 'block';
noteInput.placeholder = 'Notiz...';
noteInput.required = true;
} else {
noteInput.style.display = 'none';
noteInput.value = '';
noteInput.required = false;
}
}
// Verlauf togglen
function toggleHistory(orderId) {
var el = document.getElementById('history-' + orderId);
if (!el) return;
el.style.display = (el.style.display === 'none' || el.style.display === '') ? 'block' : 'none';
}
// AJAX Komponenten-Toggle
function toggleComponentAjax(checkbox) {
var compId = checkbox.getAttribute('data-comp-id');
var csrf = checkbox.getAttribute('data-csrf');
var compItem = checkbox.closest('.comp-item');
var orderCard = checkbox.closest('.order-card');
checkbox.disabled = true;
var formData = new FormData();
formData.append('_csrf', csrf);
fetch('/orders/components/' + compId + '/toggle', {
method: 'POST',
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' },
body: formData
})
.then(function(resp) { return resp.json(); })
.then(function(data) {
if (data.error) {
alert(data.error);
checkbox.checked = !checkbox.checked;
checkbox.disabled = false;
return;
}
checkbox.disabled = false;
var comp = data.component;
var nameEl = compItem.querySelector('.comp-name');
var metaEl = compItem.querySelector('.comp-meta');
if (comp && parseInt(comp.is_done) === 1) {
nameEl.classList.add('done');
metaEl.innerHTML = '<div>' + (comp.done_by_name || '') + '</div>';
if (comp.done_at) {
var d = new Date(comp.done_at);
metaEl.innerHTML += '<div>' + d.toLocaleDateString('de-DE', {day:'2-digit',month:'2-digit'}) + ' ' + d.toLocaleTimeString('de-DE', {hour:'2-digit',minute:'2-digit'}) + '</div>';
}
var existingDel = compItem.querySelector('.comp-delete');
if (!existingDel) {
var delForm = document.createElement('form');
delForm.method = 'POST';
delForm.action = '/orders/components/' + compId;
delForm.onsubmit = function() { return confirm(window.onitText('Eintrag löschen?')); };
delForm.innerHTML = '<input type="hidden" name="_csrf" value="' + csrf + '">'
+ '<input type="hidden" name="_method" value="DELETE">'
+ '<button type="submit" class="comp-delete">×</button>';
compItem.appendChild(delForm);
}
} else {
nameEl.classList.remove('done');
metaEl.innerHTML = '';
var delForm = compItem.querySelector('form[action*="/orders/components/"]');
if (delForm) delForm.remove();
}
if (orderCard) {
var done = data.order_done;
var total = data.order_total;
var pct = total > 0 ? Math.floor(done * 100 / total) : 0;
var progLabel = orderCard.querySelector('.progress-label');
if (progLabel) progLabel.innerHTML = '<span>' + done + '/' + total + '</span><span>' + pct + '%</span>';
var progFill = orderCard.querySelector('.progress-fill');
if (progFill) {
progFill.style.width = pct + '%';
progFill.classList.toggle('complete', pct === 100);
}
var panel = orderCard.closest('.tab-panel');
if (panel && data.order_status !== panel.getAttribute('data-panel') && data.order_status !== 'all') {
window.location.reload();
}
}
})
.catch(function(err) {
console.error('Toggle-Fehler:', err);
checkbox.checked = !checkbox.checked;
checkbox.disabled = false;
});
}
// Empfänger- und Lieferanten-Suche laufen über die wiederverwendbaren
// Komponenten person-search.js und company-search.js (data-person-search bzw.
// data-company-search an den Feldern in _card.php / index.php).
// ============================================================
// Metadaten: ein gemeinsamer Speichern-Button + AJAX-Speichern
// (kein Seiten-Reload -> die geöffnete Bestellung bleibt offen)
// ============================================================
function clearSupplier(orderId) {
document.getElementById('supplier-id-' + orderId).value = '0';
var input = document.querySelector('[data-order-id="' + orderId + '"].supplier-search-input');
if (input) input.value = '';
}
function clearRecipient(orderId) {
document.getElementById('person-id-' + orderId).value = '0';
var input = document.querySelector('[data-order-id="' + orderId + '"].person-search-input');
if (input) input.value = '';
var emailEl = document.getElementById('person-email-' + orderId);
if (emailEl) { emailEl.value = ''; emailEl.readOnly = false; }
}
// E-Mail-Feld der Empfänger-Suche sperren, solange eine Verzeichnisperson mit
// hinterlegter E-Mail gewählt ist – serverseitig zählt dann ohnehin die
// Verzeichnis-Mail. Nur für Orders-Felder (.person-search-input).
function _orderRecipientEmailEl(inp) {
if (!inp || !inp.classList || !inp.classList.contains('person-search-input')) { return null; }
var id = inp.getAttribute('data-ps-fill-email');
return id ? document.getElementById(id) : null;
}
document.addEventListener('person-search:select', function (e) {
var emailEl = _orderRecipientEmailEl(e.target);
if (emailEl) { emailEl.readOnly = !!(e.detail && e.detail.email); }
});
document.addEventListener('person-search:clear', function (e) {
var emailEl = _orderRecipientEmailEl(e.target);
if (emailEl) { emailEl.readOnly = false; }
});
document.addEventListener('submit', function(e) {
var form = e.target.closest('form.meta-form');
if (!form) return;
e.preventDefault();
var btn = form.querySelector('.meta-save-btn');
var status = form.querySelector('.meta-save-status');
if (status) { status.textContent = ''; status.className = 'meta-save-status'; }
if (btn) btn.disabled = true;
fetch(form.action, {
method: 'POST',
body: new FormData(form),
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }
})
.then(function(r) { return r.json().catch(function() { return {}; }).then(function(j) { return { ok: r.ok, j: j }; }); })
.then(function(res) {
if (res.ok && res.j && res.j.success) {
// Karte neu laden -> Kopf (Titel/Priorität/Chips) und Verlauf aktualisieren.
var card = form.closest('.order-card');
var orderId = card ? card.id.replace('order-', '') : null;
ordersToast('Gespeichert');
if (orderId) { reloadOrderCard(orderId); return; }
if (btn) btn.disabled = false;
} else {
if (btn) btn.disabled = false;
if (status) {
status.textContent = (res.j && res.j.error) ? res.j.error : 'Fehler beim Speichern';
status.className = 'meta-save-status meta-save-err';
}
}
})
.catch(function() {
if (btn) btn.disabled = false;
if (status) { status.textContent = 'Netzwerkfehler'; status.className = 'meta-save-status meta-save-err'; }
});
});
// Fallback ohne JS-Fetch / Direktlinks: per #order-<id> verlinkte Bestellung
// öffnen und in den Blick scrollen (z.B. nach klassischem Redirect).
(function() {
if (!/^#order-\d+$/.test(location.hash)) return;
var el = document.querySelector(location.hash);
if (el && el.tagName === 'DETAILS') {
el.open = true;
if (typeof loadLazyDetail === 'function') { loadLazyDetail(el); }
el.scrollIntoView({ block: 'start' });
}
})();
// ── Datei-Upload: Drag & Drop + Dateiname (idempotent, auch nach Neuladen) ──
function initOrderUploads() {
document.querySelectorAll('.cs-upload-drop').forEach(function (label) {
if (label.dataset.uploadBound) return;
label.dataset.uploadBound = '1';
var input = label.querySelector('input[type=file]');
var name = label.querySelector('.cs-upload-name');
if (!input || !name) return;
var placeholder = name.textContent;
function showName() {
var has = input.files && input.files[0];
name.textContent = has ? input.files[0].name : placeholder;
name.style.color = has ? '#374151' : '';
name.style.fontWeight = has ? '500' : '';
}
input.addEventListener('change', showName);
['dragenter', 'dragover'].forEach(function (ev) {
label.addEventListener(ev, function (e) { e.preventDefault(); label.classList.add('cs-upload-dragging'); });
});
['dragleave', 'drop'].forEach(function (ev) {
label.addEventListener(ev, function (e) { e.preventDefault(); label.classList.remove('cs-upload-dragging'); });
});
label.addEventListener('drop', function (e) {
if (e.dataTransfer && e.dataTransfer.files.length) {
input.files = e.dataTransfer.files;
showName();
}
});
});
}
initOrderUploads();
// ── Detail erst beim Aufklappen laden (Lazy) ────────────────────
// Die Liste rendert nur die Zusammenfassung; das Detail (Komponenten,
// Kommentare, Dateien, Verlauf, Aktionen) wird beim ersten Öffnen der
// Karte per AJAX vom /orders/{id}/card-Endpoint nachgeladen.
function loadLazyDetail(card) {
var ph = card.querySelector('.order-detail--lazy');
if (!ph || ph.dataset.loading) { return; }
ph.dataset.loading = '1';
fetch(ph.getAttribute('data-card-url'), { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(function (r) { return r.text(); })
.then(function (html) {
var tmp = document.createElement('div');
tmp.innerHTML = html.trim();
var detail = tmp.querySelector('.order-detail');
if (detail) {
ph.replaceWith(detail);
initOrderUploads();
if (window.PersonSearch) { window.PersonSearch.init(detail); }
if (window.CompanySearch) { window.CompanySearch.init(detail); }
} else {
ph.dataset.loading = '';
}
})
.catch(function () {
ph.dataset.loading = '';
ph.innerHTML = '<div class="empty-mini" style="padding:1.5rem;">Detail konnte nicht geladen werden.</div>';
});
}
function initLazyDetails() {
document.querySelectorAll('.order-card').forEach(function (card) {
if (card.dataset.lazyBound) { return; }
card.dataset.lazyBound = '1';
// toggle deckt alle Öffnungswege ab (Klick, Tastatur, programmatisch).
card.addEventListener('toggle', function () {
if (card.open) { loadLazyDetail(card); }
});
// Auf Touch-Geräten schon beim Antippen vorab laden, damit das Detail
// bereits da ist, wenn die Karte aufklappt (kein zweites Tippen nötig).
var summary = card.querySelector('summary');
if (summary) {
summary.addEventListener('pointerdown', function () {
if (!card.open) { loadLazyDetail(card); }
});
}
});
}
initLazyDetails();
// ── Bestell-Karte ohne Seiten-Reload aktualisieren ──────────────
// Holt die frische Karte vom Server und ersetzt sie; offener Zustand bleibt.
function reloadOrderCard(orderId) {
var card = document.getElementById('order-' + orderId);
if (!card) { window.location.reload(); return; }
var activePanel = document.querySelector('.tab-panel.active');
var tab = activePanel ? activePanel.getAttribute('data-panel') : 'open';
var wasOpen = card.hasAttribute('open');
fetch('/orders/' + orderId + '/card?tab=' + encodeURIComponent(tab), {
headers: { 'X-Requested-With': 'XMLHttpRequest' }
})
.then(function (r) { return r.text(); })
.then(function (html) {
var tmp = document.createElement('div');
tmp.innerHTML = html.trim();
var fresh = tmp.querySelector('#order-' + orderId);
if (!fresh) { window.location.reload(); return; }
if (wasOpen) { fresh.setAttribute('open', ''); } else { fresh.removeAttribute('open'); }
card.replaceWith(fresh);
initOrderUploads();
initLazyDetails();
if (window.PersonSearch) { window.PersonSearch.init(fresh); }
if (window.CompanySearch) { window.CompanySearch.init(fresh); }
})
.catch(function () { window.location.reload(); });
}
// ── Closed-Tab: weitere abgeschlossene Bestellungen nachladen ────
function loadMoreClosed(btn) {
var offset = parseInt(btn.getAttribute('data-offset'), 10) || 0;
var total = parseInt(btn.getAttribute('data-total'), 10) || 0;
btn.disabled = true;
btn.textContent = 'Lädt…';
// Aktive Sortierung/Filter aus der URL beim Nachladen beibehalten.
var cur = new URLSearchParams(window.location.search);
var qs = 'offset=' + offset;
if (cur.get('sort')) { qs += '&sort=' + encodeURIComponent(cur.get('sort')); }
if (cur.get('priority')) { qs += '&priority=' + encodeURIComponent(cur.get('priority')); }
fetch('/orders/closed-more?' + qs, {
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }
})
.then(function (r) { return r.json(); })
.then(function (data) {
var list = document.getElementById('closed-list');
if (list && data.html) {
var tmp = document.createElement('div');
tmp.innerHTML = data.html.trim();
while (tmp.firstChild) { list.appendChild(tmp.firstChild); }
initOrderUploads();
initLazyDetails();
if (window.PersonSearch) { window.PersonSearch.init(list); }
if (window.CompanySearch) { window.CompanySearch.init(list); }
}
if (data.hasMore) {
btn.setAttribute('data-offset', data.nextOffset);
btn.textContent = 'Weitere anzeigen (' + Math.max(0, total - data.nextOffset) + ')';
btn.disabled = false;
} else {
var wrap = btn.closest('.closed-more-wrap');
if (wrap) { wrap.remove(); }
}
})
.catch(function () { btn.disabled = false; btn.textContent = 'Weitere anzeigen'; alert('Fehler beim Laden.'); });
}
// ── In-Place-Formulare (Komponenten, Kommentare, Dateien) per AJAX ──
// Statt Seiten-Reload wird nur die betroffene Bestell-Karte neu geladen.
document.addEventListener('submit', function (e) {
var form = e.target.closest('form.js-card-form');
if (!form) return;
e.preventDefault();
var confirmMsg = form.getAttribute('data-confirm');
if (confirmMsg && !window.confirm(confirmMsg)) return;
var card = form.closest('.order-card');
var orderId = card ? card.id.replace('order-', '') : null;
var btn = form.querySelector('[type=submit]');
if (btn) btn.disabled = true;
fetch(form.action, {
method: 'POST',
body: new FormData(form),
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }
})
.then(function (r) { return r.json().catch(function () { return {}; }).then(function (j) { return { ok: r.ok, j: j }; }); })
.then(function (res) {
if (res.ok && res.j && res.j.success) {
if (orderId) { reloadOrderCard(orderId); } else { window.location.reload(); }
} else {
if (btn) btn.disabled = false;
alert((res.j && res.j.error) ? res.j.error : 'Fehler beim Speichern.');
}
})
.catch(function () { if (btn) btn.disabled = false; alert('Netzwerkfehler.'); });
});
// ── Bestellung weiterleiten (Modal) per AJAX ──
// Eigener Handler statt js-card-form: bei Erfolg erst das Modal schliessen
// (gibt body-scroll wieder frei), dann die Karte neu laden (zeigt den
// Weiterleiten-Eintrag im Verlauf).
document.addEventListener('submit', function (e) {
var form = e.target.closest('form.js-order-forward');
if (!form) return;
e.preventDefault();
var modal = form.closest('.modal-overlay');
var card = form.closest('.order-card');
var orderId = card ? card.id.replace('order-', '') : null;
var btn = form.querySelector('[type=submit]');
if (btn) btn.disabled = true;
fetch(form.action, {
method: 'POST',
body: new FormData(form),
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }
})
.then(function (r) { return r.json().catch(function () { return {}; }).then(function (j) { return { ok: r.ok, j: j }; }); })
.then(function (res) {
if (res.ok && res.j && res.j.success) {
if (modal) { closeModal(modal); }
if (orderId) { reloadOrderCard(orderId); }
} else {
if (btn) btn.disabled = false;
alert((res.j && res.j.error) ? res.j.error : 'Weiterleitung fehlgeschlagen.');
}
})
.catch(function () { if (btn) btn.disabled = false; alert('Netzwerkfehler.'); });
});
// ── Metadaten: Lese-Ansicht <-> Bearbeiten-Formular umschalten ──
document.addEventListener('click', function (e) {
var tog = e.target.closest('.meta-edit-toggle');
if (tog) {
var p = tog.closest('.order-meta-panel');
if (!p) return;
var rd = p.querySelector('.meta-read'); if (rd) rd.setAttribute('hidden', '');
var ed = p.querySelector('.meta-edit'); if (ed) ed.removeAttribute('hidden');
tog.style.display = 'none';
return;
}
var cnl = e.target.closest('.meta-edit-cancel');
if (cnl) {
var p2 = cnl.closest('.order-meta-panel');
if (!p2) return;
var ed2 = p2.querySelector('.meta-edit'); if (ed2) ed2.setAttribute('hidden', '');
var rd2 = p2.querySelector('.meta-read'); if (rd2) rd2.removeAttribute('hidden');
var t2 = p2.querySelector('.meta-edit-toggle'); if (t2) t2.style.display = '';
}
});