diff --git a/src/manage_packing_list_items.php b/src/manage_packing_list_items.php
index f0c85bf..ba4d73d 100644
--- a/src/manage_packing_list_items.php
+++ b/src/manage_packing_list_items.php
@@ -160,7 +160,7 @@ $conn->close();
}
.lager-card:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.05); }
.lager-img-wrapper {
- height: 80px; margin-bottom: 8px; display: flex;
+ height: 130px; margin-bottom: 8px; display: flex;
align-items: center; justify-content: center;
}
.lager-img-wrapper img {
@@ -181,6 +181,21 @@ $conn->close();
.editor-pane { display: flex; flex-direction: column; height: 100%; }
.pane-content { flex-grow: 1; overflow-y: auto; padding: 10px; }
+
+ /* Remove empty dropzone on the table specifically */
+ #table-container > .packed-item-container > .nested-sortable:empty {
+ min-height: 0;
+ border: none;
+ background: transparent;
+ margin: 0;
+ }
+ #table-container > .packed-item-container > .nested-sortable:empty::after {
+ display: none;
+ }
+
+ /* Grab cursor for items */
+ .packed-item-content { cursor: grab; }
+ .packed-item-content:active { cursor: grabbing; }
@@ -431,7 +446,7 @@ $conn->close();
sortableInstances['table'] = new Sortable(container, {
group: 'nested',
animation: 150,
- handle: '.handle',
+ handle: '.packed-item-content',
fallbackOnBody: true,
swapThreshold: 0.65,
ghostClass: 'sortable-ghost',
@@ -474,7 +489,7 @@ $conn->close();
sortableInstances['carrier_'+carrierId] = new Sortable(carrierRootList, {
group: 'nested',
animation: 150,
- handle: '.handle',
+ handle: '.packed-item-content',
fallbackOnBody: true,
swapThreshold: 0.65,
ghostClass: 'sortable-ghost',
@@ -485,8 +500,6 @@ $conn->close();
function renderRecursive(items, container, contextMap) {
items.forEach(item => {
- // For flat items array from table, build children tree if needed, but table shouldn't have nested items naturally unless dragged.
- // But if they are dragged out, they might keep children.
let children = item.children || [];
if (!item.children && Array.isArray(contextMap)) {
children = contextMap.filter(i => i.parent_packing_list_item_id === item.id);
@@ -500,7 +513,7 @@ $conn->close();
}
sortableInstances['nested_'+item.id] = new Sortable(nestedContainer, {
- group: 'nested', animation: 150, handle: '.handle',
+ group: 'nested', animation: 150, handle: '.packed-item-content',
fallbackOnBody: true, swapThreshold: 0.65, ghostClass: 'sortable-ghost',
onEnd: function() { syncListState(); }
});
@@ -538,7 +551,7 @@ $conn->close();
div.innerHTML = `
-
+
${nameDisplay} ${metaDisplay}
${controls}
@@ -549,47 +562,51 @@ $conn->close();
return div;
}
+ let syncTimeout = null;
function syncListState() {
- const payload = { action: 'sync_list', list: [] };
-
- function traverse(container, carrierId, parentId) {
- Array.from(container.children).forEach(child => {
- if (!child.classList.contains('packed-item-container')) return;
- const pliId = child.dataset.itemId;
- const articleId = child.dataset.articleId;
-
- payload.list.push({
- pli_id: pliId,
- article_id: articleId,
- carrier_id: carrierId,
- parent_pli_id: parentId,
- backpack_id: child.dataset.backpackId || null,
- backpack_compartment_id: child.dataset.backpackCompartmentId || null
+ if (syncTimeout) clearTimeout(syncTimeout);
+ syncTimeout = setTimeout(() => {
+ const payload = { action: 'sync_list', list: [] };
+
+ function traverse(container, carrierId, parentId) {
+ Array.from(container.children).forEach(child => {
+ if (!child.classList.contains('packed-item-container')) return;
+ const pliId = child.dataset.itemId;
+ const articleId = child.dataset.articleId;
+
+ payload.list.push({
+ pli_id: pliId,
+ article_id: articleId,
+ carrier_id: carrierId,
+ parent_pli_id: parentId,
+ backpack_id: child.dataset.backpackId || null,
+ backpack_compartment_id: child.dataset.backpackCompartmentId || null
+ });
+
+ const nestedContainer = child.querySelector('.nested-sortable');
+ if (nestedContainer) traverse(nestedContainer, carrierId, pliId);
});
-
- const nestedContainer = child.querySelector('.nested-sortable');
- if (nestedContainer) traverse(nestedContainer, carrierId, pliId);
+ }
+
+ const tableList = document.getElementById('table-container');
+ if (tableList) traverse(tableList, 'null', null);
+
+ document.querySelectorAll('.carrier-list').forEach(rootList => {
+ const carrierId = rootList.dataset.carrierId;
+ traverse(rootList, carrierId, null);
});
- }
-
- const tableList = document.getElementById('table-container');
- if (tableList) traverse(tableList, 'null', null);
-
- document.querySelectorAll('.carrier-list').forEach(rootList => {
- const carrierId = rootList.dataset.carrierId;
- traverse(rootList, carrierId, null);
- });
-
- sendApiRequest(payload).then(newItems => {
- if(Array.isArray(newItems)) packedItems = newItems;
- const panes = document.querySelectorAll('.pane-content');
- const scrollMap = Array.from(panes).map(p => p.scrollTop);
- fullRender();
- Array.from(panes).forEach((p, i) => { if (scrollMap[i] !== undefined) p.scrollTop = scrollMap[i]; });
- }).catch(err => {
- console.error("Sync failed:", err);
- alert("Fehler beim Speichern! Bitte Seite neu laden.");
- });
+
+ sendApiRequest(payload).then(newItems => {
+ if(Array.isArray(newItems)) packedItems = newItems;
+ const panes = document.querySelectorAll('.pane-content');
+ const scrollMap = Array.from(panes).map(p => p.scrollTop);
+ fullRender();
+ Array.from(panes).forEach((p, i) => { if (scrollMap[i] !== undefined) p.scrollTop = scrollMap[i]; });
+ }).catch(err => {
+ console.error("Sync failed:", err);
+ alert("Fehler beim Speichern! Bitte Seite neu laden.");
+ });
+ }, 300);
}
function handlePackedItemActions(e) {