From c0088d5ce26af856398228a0d2282289fc29d3d9 Mon Sep 17 00:00:00 2001 From: Gemini Date: Wed, 13 May 2026 19:33:48 +0000 Subject: [PATCH] UI: Finales ToDo-Listen Redesign und Layout-Fixes --- src/add_packing_list.php | 4 +- src/edit_packing_list_details.php | 4 +- src/manage_packing_list_items.php | 2 +- src/packing_list_detail.php | 632 ------------------------------ src/packing_lists.php | 4 +- src/public_list.php | 2 +- src/todo_lists.php | 181 ++++----- 7 files changed, 101 insertions(+), 728 deletions(-) diff --git a/src/add_packing_list.php b/src/add_packing_list.php index 0520048..afde30b 100644 --- a/src/add_packing_list.php +++ b/src/add_packing_list.php @@ -47,10 +47,10 @@ $stmt_templates->close(); // Fetch Users for Backpack Assignment UI $available_users = []; if ($household_id_for_user) { - $stmt_u = $conn->prepare("SELECT id, username FROM users WHERE household_id = ?"); + $stmt_u = $conn->prepare("SELECT id, COALESCE(NULLIF(display_name, ''), username) AS username FROM users WHERE household_id = ?"); $stmt_u->bind_param("i", $household_id_for_user); } else { - $stmt_u = $conn->prepare("SELECT id, COALESCE(display_name, username) AS username FROM users WHERE id = ?"); + $stmt_u = $conn->prepare("SELECT id, COALESCE(NULLIF(display_name, ''), username) AS username FROM users WHERE id = ?"); $stmt_u->bind_param("i", $current_user_id); } $stmt_u->execute(); diff --git a/src/edit_packing_list_details.php b/src/edit_packing_list_details.php index ff8c013..00719f4 100644 --- a/src/edit_packing_list_details.php +++ b/src/edit_packing_list_details.php @@ -58,10 +58,10 @@ $available_todo_lists = []; if ($can_edit) { // Owners: Creator + Household Members (if shared) if ($packing_list['household_id']) { - $stmt = $conn->prepare("SELECT id, username FROM users WHERE household_id = ?"); + $stmt = $conn->prepare("SELECT id, COALESCE(NULLIF(display_name, ''), username) AS username FROM users WHERE household_id = ?"); $stmt->bind_param("i", $packing_list['household_id']); } else { - $stmt = $conn->prepare("SELECT id, COALESCE(display_name, username) AS username FROM users WHERE id = ?"); + $stmt = $conn->prepare("SELECT id, COALESCE(NULLIF(display_name, ''), username) AS username FROM users WHERE id = ?"); $stmt->bind_param("i", $packing_list['user_id']); } $stmt->execute(); diff --git a/src/manage_packing_list_items.php b/src/manage_packing_list_items.php index 696c4e9..42590a4 100644 --- a/src/manage_packing_list_items.php +++ b/src/manage_packing_list_items.php @@ -99,7 +99,7 @@ $packed_items_raw = $stmt_items->get_result()->fetch_all(MYSQLI_ASSOC); $stmt_items->close(); $carriers_data = []; -$stmt_carriers = $conn->prepare("SELECT u.id, COALESCE(u.display_name, u.username) AS username FROM users u JOIN packing_list_carriers plc ON u.id = plc.user_id WHERE plc.packing_list_id = ? ORDER BY username"); +$stmt_carriers = $conn->prepare("SELECT u.id, COALESCE(NULLIF(u.display_name, ''), u.username) AS username FROM users u JOIN packing_list_carriers plc ON u.id = plc.user_id WHERE plc.packing_list_id = ? ORDER BY username"); $stmt_carriers->bind_param("i", $packing_list_id); $stmt_carriers->execute(); $carriers_result = $stmt_carriers->get_result(); diff --git a/src/packing_list_detail.php b/src/packing_list_detail.php index 8b9b2ea..e69de29 100644 --- a/src/packing_list_detail.php +++ b/src/packing_list_detail.php @@ -1,632 +0,0 @@ -prepare("UPDATE todo_items SET is_completed = ? WHERE id = ?"); - $stmt->bind_param("ii", $status, $item_id); - $stmt->execute(); - $stmt->close(); - // Redirect to avoid form resubmission - header("Location: packing_list_detail.php?id=" . $packing_list_id); - exit; -} - -require_once 'header.php'; - -$packing_list = null; -$total_weight_grams = 0; -$total_consumable_weight = 0; -$weight_by_category = []; -$weight_by_carrier = []; -$weight_by_carrier_non_consumable = []; - -// Array for Carrier Detailed Stats (Modal) -$carrier_stats_details = []; - -if ($packing_list_id <= 0) { - die("Keine Packlisten-ID angegeben."); -} - -// Erweiterte Berechtigungsprüfung für Haushalte -$stmt_current_user = $conn->prepare("SELECT household_id FROM users WHERE id = ?"); -$stmt_current_user->bind_param("i", $current_user_id); -$stmt_current_user->execute(); -$current_user_household_id = $stmt_current_user->get_result()->fetch_assoc()['household_id']; -$stmt_current_user->close(); - -$stmt_list_owner = $conn->prepare( - "SELECT pl.*, u.household_id as owner_household_id - FROM packing_lists pl - JOIN users u ON pl.user_id = u.id - WHERE pl.id = ?" -); -$stmt_list_owner->bind_param("i", $packing_list_id); -$stmt_list_owner->execute(); -$result = $stmt_list_owner->get_result(); -if ($result->num_rows > 0) { - $packing_list = $result->fetch_assoc(); - $is_owner = ($packing_list['user_id'] == $current_user_id); - $is_household_list = !empty($packing_list['household_id']); - $is_in_same_household = ($is_household_list && $packing_list['household_id'] == $current_user_household_id); - - if (!$is_owner && !$is_in_same_household) { - die("Packliste nicht gefunden oder Zugriff verweigert."); - } -} else { - die("Packliste nicht gefunden oder Zugriff verweigert."); -} -$stmt_list_owner->close(); - -$todo_items = []; -$todo_list_name = ''; -if (!empty($packing_list['todo_list_id'])) { - $stmt_tl = $conn->prepare("SELECT name FROM todo_lists WHERE id = ?"); - $stmt_tl->bind_param("i", $packing_list['todo_list_id']); - $stmt_tl->execute(); - $res_tl = $stmt_tl->get_result(); - if ($row = $res_tl->fetch_assoc()) $todo_list_name = $row['name']; - $stmt_tl->close(); - - $stmt_td = $conn->prepare("SELECT * FROM todo_items WHERE todo_list_id = ? ORDER BY is_completed ASC, id ASC"); - $stmt_td->bind_param("i", $packing_list['todo_list_id']); - $stmt_td->execute(); - $todo_items = $stmt_td->get_result()->fetch_all(MYSQLI_ASSOC); - $stmt_td->close(); -} - -// Check for items on the table -$stmt_table = $conn->prepare("SELECT COUNT(*) as table_count FROM packing_list_items WHERE packing_list_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"); -$stmt_table->bind_param("i", $packing_list_id); -$stmt_table->execute(); -$table_items_count = $stmt_table->get_result()->fetch_assoc()['table_count']; -$stmt_table->close(); - -$page_title = "Packliste: " . htmlspecialchars($packing_list['name']); - -// FIX: Join Categories also for Backpacks -$sql = "SELECT - pli.id, pli.quantity, pli.parent_packing_list_item_id, pli.carrier_user_id, - pli.backpack_id, pli.backpack_compartment_id, - COALESCE(a.name, pli.name, bp.name, bpc.name, 'Unbekanntes Item') AS article_name, - COALESCE(a.weight_grams, bp.weight_grams, 0) as weight_grams, - a.image_url, a.product_designation, a.consumable, - COALESCE(c.name, c_bp.name, 'Sonstiges') AS category_name, - m.name AS manufacturer_name, - COALESCE(u.display_name, u.username) AS carrier_name, - u.id AS carrier_id - FROM packing_list_items AS pli - LEFT JOIN articles AS a ON pli.article_id = a.id - LEFT JOIN backpacks AS bp ON pli.backpack_id = bp.id - LEFT JOIN backpack_compartments AS bpc ON pli.backpack_compartment_id = bpc.id - LEFT JOIN categories AS c ON a.category_id = c.id - LEFT JOIN categories AS c_bp ON bp.category_id = c_bp.id - LEFT JOIN manufacturers AS m ON a.manufacturer_id = m.id - LEFT JOIN users AS u ON pli.carrier_user_id = u.id - WHERE pli.packing_list_id = ? - AND NOT (pli.carrier_user_id IS NULL AND pli.backpack_id IS NULL AND pli.backpack_compartment_id IS NULL AND pli.parent_packing_list_item_id IS NULL) - ORDER BY pli.order_index ASC"; - -$stmt = $conn->prepare($sql); -$stmt->bind_param("i", $packing_list_id); -$stmt->execute(); -$result = $stmt->get_result(); - -$items_by_id = []; -$items_by_parent = []; - -while ($row = $result->fetch_assoc()) { - $items_by_id[$row['id']] = $row; - $parent_id = $row['parent_packing_list_item_id'] ?: 0; - if (!isset($items_by_parent[$parent_id])) { - $items_by_parent[$parent_id] = []; - } - $items_by_parent[$parent_id][] = $row; - - // Stats - $item_weight = $row['quantity'] * $row['weight_grams']; - $total_weight_grams += $item_weight; - - $carrier_name = $row['carrier_name'] ?: 'Sonstiges'; - $carrier_id = $row['carrier_id'] ?: 0; - - // Init stats arrays - if (!isset($weight_by_carrier[$carrier_name])) $weight_by_carrier[$carrier_name] = 0; - $weight_by_carrier[$carrier_name] += $item_weight; - - $cat_name = $row['category_name'] ?: 'Sonstiges'; - if (!isset($weight_by_category[$cat_name])) $weight_by_category[$cat_name] = 0; - $weight_by_category[$cat_name] += $item_weight; - - if ($row['consumable']) { - $total_consumable_weight += $item_weight; - } else { - if (!isset($weight_by_carrier_non_consumable[$carrier_name])) $weight_by_carrier_non_consumable[$carrier_name] = 0; - $weight_by_carrier_non_consumable[$carrier_name] += $item_weight; - } - - // Prepare Detailed Stats per Carrier for Modal - if (!isset($carrier_stats_details[$carrier_name])) { - $carrier_stats_details[$carrier_name] = [ - 'total_weight' => 0, - 'base_weight' => 0, - 'consumable_weight' => 0, - 'categories' => [] - ]; - } - $carrier_stats_details[$carrier_name]['total_weight'] += $item_weight; - if ($row['consumable']) { - $carrier_stats_details[$carrier_name]['consumable_weight'] += $item_weight; - } else { - $carrier_stats_details[$carrier_name]['base_weight'] += $item_weight; - } - if (!isset($carrier_stats_details[$carrier_name]['categories'][$cat_name])) { - $carrier_stats_details[$carrier_name]['categories'][$cat_name] = 0; - } - $carrier_stats_details[$carrier_name]['categories'][$cat_name] += $item_weight; -} -$stmt->close(); -$conn->close(); - -$total_weight_without_consumables = $total_weight_grams - $total_consumable_weight; - -// Helper functions (same as before) -function get_recursive_quantity($parent_id, $items_by_parent) { - $count = 0; - if (isset($items_by_parent[$parent_id])) { - foreach ($items_by_parent[$parent_id] as $child) { - $count += $child['quantity']; - $count += get_recursive_quantity($child['id'], $items_by_parent); - } - } - return $count; -} - -function get_recursive_weight($parent_id, $items_by_parent) { - $weight = 0; - if (isset($items_by_parent[$parent_id])) { - foreach ($items_by_parent[$parent_id] as $child) { - $weight += ($child['quantity'] * $child['weight_grams']); - $weight += get_recursive_weight($child['id'], $items_by_parent); - } - } - return $weight; -} - -function render_item_row($item, $level, $items_by_parent) { - $has_children = isset($items_by_parent[$item['id']]); - $is_backpack = !empty($item['backpack_id']); - $is_compartment = !empty($item['backpack_compartment_id']); - - $bg_class = ""; - $text_class = ""; - $icon = ""; - - if ($is_backpack) { - $bg_class = "table-success"; - $text_class = "fw-bold text-uppercase"; - $icon = ''; - } elseif ($is_compartment) { - $bg_class = "table-light"; - $text_class = "fw-bold fst-italic text-muted"; - // Check if linked article (image present) - if (!empty($item['image_url'])) { - $img_src = htmlspecialchars($item['image_url']); - $icon = ''; - } else { - $icon = ''; - } - } else { - $img_src = !empty($item['image_url']) ? htmlspecialchars($item['image_url']) : 'assets/images/keinbild.png'; - $icon = ''; - } - - $indent_px = $level * 25; - $weight_display = $item['weight_grams'] > 0 ? number_format($item['weight_grams'], 0, ',', '.') . ' g' : '-'; - - $total_weight_val = 0; - if ($is_backpack || $is_compartment) { - $children_weight = get_recursive_weight($item['id'], $items_by_parent); - $own_weight = $item['quantity'] * $item['weight_grams']; - $total_weight_val = $own_weight + $children_weight; - } else { - $total_weight_val = $item['weight_grams'] * $item['quantity']; - } - - $total_weight_display = ($total_weight_val > 0) ? number_format($total_weight_val, 0, ',', '.') . ' g' : '-'; - - echo ''; - - echo ''; - echo '
'; - - if ($has_children) { - echo ''; - } else { - echo ''; - } - - echo $icon; - echo '' . htmlspecialchars($item['article_name']) . ''; - echo '
'; - echo ''; - - echo '' . ($item['consumable'] ? '' : '') . ''; - echo '' . htmlspecialchars($item['manufacturer_name'] ?: '') . ''; - echo '' . htmlspecialchars($item['product_designation'] ?: '') . ''; - echo '' . htmlspecialchars($item['category_name'] ?: '') . ''; - - echo ''; - if ($is_backpack) { - echo ''; - } elseif ($is_compartment) { - $total_items = get_recursive_quantity($item['id'], $items_by_parent); - if ($total_items > 0) { - echo '' . $total_items . ''; - } - } else { - echo '' . $item['quantity'] . 'x'; - } - echo ''; - - echo '' . $weight_display . ''; - echo '' . $total_weight_display . ''; - - echo ''; - - if ($has_children) { - foreach ($items_by_parent[$item['id']] as $child) { - render_item_row($child, $level + 1, $items_by_parent); - } - } -} -?> - - - -
-
-
-

Packliste:

- -
-
- - 0): ?> - - - -
-
-
-
Gepackte Artikel
-
-
- - - - - - - - - - - - - - - - - - $roots): ?> - - - - - - - -
Artikel / StrukturHerstellerModellKategorieAnz.GewichtGesamt
Liste ist leer.
- - - - (Klicken für Statistik) - -
-
-
-
-
-
- -
-
ToDo:
-
-
    - -
  • -
    - -
    - style="width:1.3em; height:1.3em; cursor:pointer;"> - - -
    -
    -
  • - - -
  • Keine Einträge in dieser Liste.
  • - -
-
-
- - -
-
Statistiken
-
-
-
Gewicht pro Träger
-
    - $weight): ?> -
  • - -
    - Gesamt: g -
    -
    - Basis (o. Verbr.): g -
    -
  • - -
-
-
-
nach Kategorie
-
nach Träger
-
- -
-
Gewicht nach Kategorie
-
- - - $w): - ?> - - - - - - -
g
-
-
-
-
-
-
-
- - - - -
- - - -hp require_once 'footer.php'; ?> \ No newline at end of file diff --git a/src/packing_lists.php b/src/packing_lists.php index dc86885..96846b9 100644 --- a/src/packing_lists.php +++ b/src/packing_lists.php @@ -44,7 +44,7 @@ $is_template_val = $is_template_view ? 1 : 0; $sql = "SELECT pl.id, pl.name, pl.description, pl.user_id, pl.household_id, pl.is_template, - COALESCE(u.display_name, u.username) as creator_name, + COALESCE(NULLIF(u.display_name, ''), u.username) as creator_name, COUNT(DISTINCT pli.carrier_user_id) AS carrier_count, SUM(pli.quantity * a.weight_grams) AS total_weight FROM packing_lists pl @@ -52,7 +52,7 @@ $sql = "SELECT LEFT JOIN packing_list_items pli ON pl.id = pli.packing_list_id LEFT JOIN articles a ON pli.article_id = a.id WHERE (pl.user_id = ? OR pl.household_id = ?) AND pl.is_template = ? - GROUP BY pl.id, pl.name, pl.description, pl.user_id, COALESCE(u.display_name, u.username), pl.household_id, pl.is_template + GROUP BY pl.id, pl.name, pl.description, pl.user_id, COALESCE(NULLIF(u.display_name, ''), u.username), pl.household_id, pl.is_template ORDER BY pl.name ASC"; $stmt = $conn->prepare($sql); diff --git a/src/public_list.php b/src/public_list.php index 84bd961..aa272a1 100644 --- a/src/public_list.php +++ b/src/public_list.php @@ -35,7 +35,7 @@ if ($packing_list) { $packing_list_id = $packing_list['id']; // SQL-Abfrage holt alle relevanten Daten - $sql = "SELECT pli.id, pli.quantity, pli.parent_packing_list_item_id, a.name AS article_name, a.weight_grams, a.image_url, a.product_designation, a.consumable, a.product_url, c.name AS category_name, m.name AS manufacturer_name, COALESCE(u.display_name, u.username) AS carrier_name FROM packing_list_items AS pli JOIN articles AS a ON pli.article_id = a.id LEFT JOIN categories AS c ON a.category_id = c.id LEFT JOIN manufacturers AS m ON a.manufacturer_id = m.id LEFT JOIN users AS u ON pli.carrier_user_id = u.id WHERE pli.packing_list_id = ?"; + $sql = "SELECT pli.id, pli.quantity, pli.parent_packing_list_item_id, a.name AS article_name, a.weight_grams, a.image_url, a.product_designation, a.consumable, a.product_url, c.name AS category_name, m.name AS manufacturer_name, COALESCE(NULLIF(u.display_name, ''), u.username) AS carrier_name FROM packing_list_items AS pli JOIN articles AS a ON pli.article_id = a.id LEFT JOIN categories AS c ON a.category_id = c.id LEFT JOIN manufacturers AS m ON a.manufacturer_id = m.id LEFT JOIN users AS u ON pli.carrier_user_id = u.id WHERE pli.packing_list_id = ?"; $stmt_items = $conn->prepare($sql); $stmt_items->bind_param("i", $packing_list_id); $stmt_items->execute(); diff --git a/src/todo_lists.php b/src/todo_lists.php index 330e37a..0d461be 100644 --- a/src/todo_lists.php +++ b/src/todo_lists.php @@ -80,107 +80,112 @@ $stmt->close(); $active_list_id = isset($_GET['list_id']) ? intval($_GET['list_id']) : (!empty($todo_lists) ? $todo_lists[0]['id'] : 0); ?> -
-

ToDo-Listen

- - " . htmlspecialchars($message) . "
"; ?> +
+
+

ToDo-Listen

+
+
+ " . htmlspecialchars($message) . "
"; ?> -
- -
-
-
-
Meine Listen
-
-
- - - -
- - -
-
- - -
Keine Listen vorhanden.
- -
-
-
-
- - -
-
-
-
-
- - -
- 0): ?> - prepare("SELECT * FROM todo_items WHERE todo_list_id = ? ORDER BY is_completed ASC, id ASC"); - $stmt->bind_param("i", $active_list_id); - $stmt->execute(); - $items = $stmt->get_result()->fetch_all(MYSQLI_ASSOC); - $stmt->close(); - - $active_list_name = ''; - foreach ($todo_lists as $l) if ($l['id'] == $active_list_id) $active_list_name = $l['name']; - ?> -
-
-
-
-
-
    - -
  • -
    - - -
    - style="width:1.5em; height:1.5em; cursor:pointer;"> - - -
    +
    + +
    +
    +
    +
    Meine Listen
    +
  • + - -
  • Noch keine Punkte auf dieser Liste.
  • + +
    Keine Listen vorhanden.
    -
- +
- -
- - +
+ +
- -
Wähle links eine Liste aus oder erstelle eine neue.
- +
+ + +
+ 0): ?> + prepare("SELECT * FROM todo_items WHERE todo_list_id = ? ORDER BY is_completed ASC, id ASC"); + $stmt->bind_param("i", $active_list_id); + $stmt->execute(); + $items = $stmt->get_result()->fetch_all(MYSQLI_ASSOC); + $stmt->close(); + + $active_list_name = ''; + foreach ($todo_lists as $l) if ($l['id'] == $active_list_id) $active_list_name = $l['name']; + ?> +
+
+
+
+
+
    + +
  • +
    + + +
    + style="width:1.5em; height:1.5em; cursor:pointer;"> + + +
    +
    +
    + + + +
    +
  • + + +
  • Noch keine Punkte auf dieser Liste. Füge unten einen hinzu!
  • + +
+ +
+ +
+ + +
+
+
+
+ +
+
+
Keine Liste ausgewählt
+

Wähle links eine Liste aus oder erstelle eine neue Liste, um Aufgaben hinzuzufügen.

+
+
+ +
close(); -?>se(); -?>e(); -?>nn->close(); +if (isset($conn) && $conn instanceof mysqli) { + $conn->close(); +} ?> \ No newline at end of file