From 862b5672846dd2d05b8bb844e75a43da5c917d15 Mon Sep 17 00:00:00 2001 From: Gemini Agent Date: Mon, 11 May 2026 16:04:47 +0000 Subject: [PATCH] Refactor packing list editor to Virtual Table workflow - Created grid view for available articles (Lager) with +/- buttons. - Added middle pane for staging items (Auf dem Tisch). - Updated drag and drop sync to handle three phases. - Added direct links to Phase 1 and Phase 2 from the packing list overview. --- src/api_packing_list_handler.php | 64 +++- src/manage_packing_list_items.php | 605 ++++++++++++++++-------------- src/packing_lists.php | 4 +- 3 files changed, 385 insertions(+), 288 deletions(-) diff --git a/src/api_packing_list_handler.php b/src/api_packing_list_handler.php index 0a8fc65..8758a9a 100644 --- a/src/api_packing_list_handler.php +++ b/src/api_packing_list_handler.php @@ -150,8 +150,7 @@ try { case 'delete_item': $item_id = intval($data['item_id']); - // Recursive Delete Logic using CTE if MySQL 8+ or manual recursion - // Manual recursion to be safe on older DBs: + // Recursive Delete Logic $ids_to_delete = [$item_id]; $i = 0; while($i < count($ids_to_delete)) { @@ -167,27 +166,80 @@ try { $i++; } - // Delete all gathered IDs $in_query = implode(',', array_fill(0, count($ids_to_delete), '?')); $types = str_repeat('i', count($ids_to_delete)); $stmt_delete = $conn->prepare("DELETE FROM packing_list_items WHERE id IN ($in_query) AND packing_list_id = ?"); - - // Combine ID params and list ID $delete_params = array_merge($ids_to_delete, [$packing_list_id]); $delete_types = $types . 'i'; $stmt_delete->bind_param($delete_types, ...$delete_params); $stmt_delete->execute(); $stmt_delete->close(); break; + + case 'adjust_table_quantity': + $article_id = intval($data['article_id']); + $delta = intval($data['delta']); // 1 or -1 + $include_children = !empty($data['include_children']); + + function adjust_single($conn, $packing_list_id, $art_id, $delta) { + $stmt_find = $conn->prepare("SELECT id, quantity FROM packing_list_items WHERE packing_list_id = ? AND article_id = ? AND carrier_user_id IS NULL AND backpack_id IS NULL AND backpack_compartment_id IS NULL AND parent_packing_list_item_id IS NULL LIMIT 1"); + $stmt_find->bind_param("ii", $packing_list_id, $art_id); + $stmt_find->execute(); + $res = $stmt_find->get_result(); + if ($row = $res->fetch_assoc()) { + $new_quantity = $row['quantity'] + $delta; + if ($new_quantity > 0) { + $stmt_update = $conn->prepare("UPDATE packing_list_items SET quantity = ? WHERE id = ?"); + $stmt_update->bind_param("ii", $new_quantity, $row['id']); + $stmt_update->execute(); + $stmt_update->close(); + } else { + $stmt_del = $conn->prepare("DELETE FROM packing_list_items WHERE id = ?"); + $stmt_del->bind_param("i", $row['id']); + $stmt_del->execute(); + $stmt_del->close(); + } + } else { + if ($delta > 0) { + $idx_res = $conn->query("SELECT MAX(order_index) as max_idx FROM packing_list_items WHERE packing_list_id = $packing_list_id"); + $next_idx = ($idx_res->fetch_assoc()['max_idx'] ?? 0) + 1; + $stmt_insert = $conn->prepare("INSERT INTO packing_list_items (packing_list_id, article_id, quantity, order_index) VALUES (?, ?, ?, ?)"); + $stmt_insert->bind_param("iiii", $packing_list_id, $art_id, $delta, $next_idx); + $stmt_insert->execute(); + $stmt_insert->close(); + } + } + $stmt_find->close(); + } + + adjust_single($conn, $packing_list_id, $article_id, $delta); + + if ($include_children && $delta > 0) { + $stmt_children = $conn->prepare("SELECT id FROM articles WHERE parent_article_id = ?"); + $stmt_children->bind_param("i", $article_id); + $stmt_children->execute(); + $res_child = $stmt_children->get_result(); + while($child = $res_child->fetch_assoc()) { + adjust_single($conn, $packing_list_id, $child['id'], $delta); + } + $stmt_children->close(); + } + break; + case 'update_quantity': $item_id = intval($data['item_id']); $quantity = intval($data['quantity']); if ($quantity > 0) { $stmt = $conn->prepare("UPDATE packing_list_items SET quantity = ? WHERE id = ?"); $stmt->bind_param("ii", $quantity, $item_id); $stmt->execute(); $stmt->close(); - $conn->commit(); echo json_encode(['success' => true]); exit; + $conn->commit(); echo json_encode(get_all_items($conn, $packing_list_id)); exit; } else { throw new Exception('Ungültige Mengenangabe.'); } break; + + case 'get_items': + // Just returns the current state (handled at the end of script) + break; + default: throw new Exception('Unbekannte Aktion angefordert.', 400); } diff --git a/src/manage_packing_list_items.php b/src/manage_packing_list_items.php index d575563..f0c85bf 100644 --- a/src/manage_packing_list_items.php +++ b/src/manage_packing_list_items.php @@ -1,6 +1,6 @@ get_result()->fetch_all(MYSQLI_ASSOC); $stmt_items->close(); $carriers_data = []; -// KORREKTUR: Nur Träger anzeigen, die dieser Liste zugewiesen sind $stmt_carriers = $conn->prepare("SELECT u.id, u.username FROM users u JOIN packing_list_carriers plc ON u.id = plc.user_id WHERE plc.packing_list_id = ? ORDER BY u.username"); $stmt_carriers->bind_param("i", $packing_list_id); $stmt_carriers->execute(); $carriers_result = $stmt_carriers->get_result(); while ($row = $carriers_result->fetch_assoc()) { $carriers_data[] = $row; } $stmt_carriers->close(); -$carriers_data[] = ['id' => null, 'username' => 'Sonstiges']; $categories = array_unique(array_filter(array_column($all_articles_raw, 'category_name'))); sort($categories); @@ -109,37 +113,131 @@ sort($manufacturers); $conn->close(); ?> - -
+ + +
-

Packliste bearbeiten:

- Zur Ansicht -
-
-
-
-
-
Verfügbare Artikel
-
-
-
-
-
-
-
-
-
-
Gepackte Artikel
-
-
+

+ +
+
+ +
+ +
+
+
+
Lagerbestand
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
Auf dem Tisch
+
+
+ +
+
+
+ + +
+
+
+
Rucksäcke
+
+
- @@ -162,88 +260,22 @@ $conn->close();
Änderungen gespeichert!
- -