UI: Finales ToDo-Listen Redesign und Layout-Fixes
All checks were successful
Docker Build & Push / build-and-push (push) Successful in 37s
All checks were successful
Docker Build & Push / build-and-push (push) Successful in 37s
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,632 +0,0 @@
|
||||
<?php
|
||||
// packing_list_detail.php - Detailansicht einer Packliste
|
||||
// FINALE, STABILE VERSION: Mit modernem Tree-View, Toggle-Funktion, Grünen Charts & Träger-Modal
|
||||
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
require_once 'db_connect.php';
|
||||
|
||||
$current_user_id = $_SESSION['user_id'];
|
||||
$packing_list_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
||||
|
||||
// Handle Todo Toggle
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['toggle_todo_item'])) {
|
||||
$item_id = intval($_POST['item_id']);
|
||||
$status = isset($_POST['status']) ? intval($_POST['status']) : 0;
|
||||
$stmt = $conn->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 = '<i class="fas fa-hiking me-2 text-success"></i>';
|
||||
} 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 = '<img src="' . $img_src . '" class="item-image me-2 article-image-trigger" data-preview-url="' . $img_src . '">';
|
||||
} else {
|
||||
$icon = '<i class="fas fa-folder-open me-2 text-warning"></i>';
|
||||
}
|
||||
} else {
|
||||
$img_src = !empty($item['image_url']) ? htmlspecialchars($item['image_url']) : 'assets/images/keinbild.png';
|
||||
$icon = '<img src="' . $img_src . '" class="item-image me-2 article-image-trigger" data-preview-url="' . $img_src . '">';
|
||||
}
|
||||
|
||||
$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 '<tr class="' . $bg_class . '" data-id="' . $item['id'] . '" data-parent-id="' . ($item['parent_packing_list_item_id'] ?: 0) . '">';
|
||||
|
||||
echo '<td>';
|
||||
echo '<div style="padding-left: ' . $indent_px . 'px; display: flex; align-items: center;">';
|
||||
|
||||
if ($has_children) {
|
||||
echo '<button type="button" class="btn btn-sm p-0 me-2 border-0 bg-transparent text-primary toggle-tree-btn" data-target-id="' . $item['id'] . '" style="width:20px; cursor:pointer;"><i class="fas fa-chevron-down"></i></button>';
|
||||
} else {
|
||||
echo '<span style="width: 20px; display: inline-block; margin-right: 0.5rem;"></span>';
|
||||
}
|
||||
|
||||
echo $icon;
|
||||
echo '<span class="' . $text_class . '">' . htmlspecialchars($item['article_name']) . '</span>';
|
||||
echo '</div>';
|
||||
echo '</td>';
|
||||
|
||||
echo '<td class="text-center">' . ($item['consumable'] ? '<i class="fas fa-cookie-bite text-warning" title="Verbrauch"></i>' : '') . '</td>';
|
||||
echo '<td>' . htmlspecialchars($item['manufacturer_name'] ?: '') . '</td>';
|
||||
echo '<td>' . htmlspecialchars($item['product_designation'] ?: '') . '</td>';
|
||||
echo '<td>' . htmlspecialchars($item['category_name'] ?: '') . '</td>';
|
||||
|
||||
echo '<td class="text-center">';
|
||||
if ($is_backpack) {
|
||||
echo '';
|
||||
} elseif ($is_compartment) {
|
||||
$total_items = get_recursive_quantity($item['id'], $items_by_parent);
|
||||
if ($total_items > 0) {
|
||||
echo '<span class="badge bg-success text-white border border-success" title="Enthält ' . $total_items . ' Artikel">' . $total_items . '</span>';
|
||||
}
|
||||
} else {
|
||||
echo '<span class="badge bg-white text-dark border">' . $item['quantity'] . 'x</span>';
|
||||
}
|
||||
echo '</td>';
|
||||
|
||||
echo '<td class="text-end text-muted">' . $weight_display . '</td>';
|
||||
echo '<td class="text-end fw-bold">' . $total_weight_display . '</td>';
|
||||
|
||||
echo '</tr>';
|
||||
|
||||
if ($has_children) {
|
||||
foreach ($items_by_parent[$item['id']] as $child) {
|
||||
render_item_row($child, $level + 1, $items_by_parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script>
|
||||
|
||||
<div class="screen-view">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h1 class="h4 mb-0"><i class="fas fa-clipboard-list me-2"></i>Packliste: <?php echo htmlspecialchars($packing_list['name']); ?></h1>
|
||||
<div class="print-hide">
|
||||
<?php if ($packing_list['user_id'] == $current_user_id || (!empty($packing_list['household_id']) && $packing_list['household_id'] == $current_user_household_id)): ?>
|
||||
<a href="manage_packing_list_items.php?id=<?php echo $packing_list_id; ?>" class="btn btn-outline-light btn-sm"><i class="fas fa-edit me-2"></i>Bearbeiten</a>
|
||||
<?php endif; ?>
|
||||
<a href="packing_lists.php" class="btn btn-outline-light btn-sm ms-2"><i class="fas fa-arrow-left me-2"></i>Zur Übersicht</a>
|
||||
<a href="print_packing_list.php?id=<?php echo $packing_list_id; ?>" target="_blank" class="btn btn-outline-light btn-sm ms-2"><i class="fas fa-print me-2"></i>Drucken</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($table_items_count > 0): ?>
|
||||
<div class="alert alert-warning print-hide">
|
||||
<i class="fas fa-exclamation-triangle me-2"></i><strong>Achtung:</strong> Auf dem Tisch liegen noch Artikel, die keinem Rucksack und keinem Träger zugewiesen sind! Diese fließen nicht in die Statistik oder den Druck ein.
|
||||
<?php if ($packing_list['user_id'] == $current_user_id || (!empty($packing_list['household_id']) && $packing_list['household_id'] == $current_user_household_id)): ?>
|
||||
<a href="manage_packing_list_items.php?id=<?php echo $packing_list_id; ?>&phase=2" class="alert-link ms-2">Jetzt zuweisen <i class="fas fa-arrow-right"></i></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mb-4 mb-lg-0 d-flex flex-column">
|
||||
<div class="card flex-grow-1">
|
||||
<div class="card-header"><h5 class="mb-0"><i class="fas fa-box-open me-2"></i>Gepackte Artikel</h5></div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-sm mb-0 align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Artikel / Struktur</th>
|
||||
<th class="text-center" style="width: 30px;"><i class="fas fa-cookie-bite"></i></th>
|
||||
<th>Hersteller</th>
|
||||
<th>Modell</th>
|
||||
<th>Kategorie</th>
|
||||
<th class="text-center">Anz.</th>
|
||||
<th class="text-end">Gewicht</th>
|
||||
<th class="text-end">Gesamt</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($items_by_parent[0])): ?>
|
||||
<tr><td colspan="8" class="text-center p-4 text-muted">Liste ist leer.</td></tr>
|
||||
<?php else: ?>
|
||||
<?php
|
||||
$items_by_carrier = [];
|
||||
foreach ($items_by_parent[0] as $root) {
|
||||
$c = $root['carrier_name'] ?: 'Sonstiges';
|
||||
$items_by_carrier[$c][] = $root;
|
||||
}
|
||||
|
||||
foreach ($items_by_carrier as $carrier => $roots): ?>
|
||||
<tr class="table-secondary border-bottom border-white">
|
||||
<td colspan="8" class="fw-bold text-uppercase ps-3 py-2">
|
||||
<i class="fas fa-user-circle me-2"></i>
|
||||
<a href="#" class="text-dark text-decoration-none carrier-stats-link" data-carrier="<?php echo htmlspecialchars($carrier); ?>">
|
||||
<?php echo htmlspecialchars($carrier); ?>
|
||||
<small class="text-muted ms-2 font-weight-normal">(Klicken für Statistik)</small>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php foreach ($roots as $root_item):
|
||||
render_item_row($root_item, 0, $items_by_parent);
|
||||
endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<?php if (!empty($packing_list['todo_list_id'])): ?>
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center"><h5 class="mb-0"><i class="fas fa-list-check me-2"></i>ToDo: <?php echo htmlspecialchars($todo_list_name); ?></h5></div>
|
||||
<div class="card-body p-0">
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php foreach ($todo_items as $item): ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center py-2 px-3">
|
||||
<form method="post" style="display:inline; margin:0;" class="flex-grow-1">
|
||||
<input type="hidden" name="item_id" value="<?php echo $item['id']; ?>">
|
||||
<div class="form-check d-flex align-items-center">
|
||||
<input class="form-check-input me-2" type="checkbox" onChange="this.form.submit()" name="status" value="<?php echo $item['is_completed'] ? '0' : '1'; ?>" <?php echo $item['is_completed'] ? 'checked' : ''; ?> style="width:1.3em; height:1.3em; cursor:pointer;">
|
||||
<input type="hidden" name="toggle_todo_item" value="1">
|
||||
<label class="form-check-label ms-2 <?php echo $item['is_completed'] ? 'text-decoration-line-through text-muted' : ''; ?>" style="cursor:pointer; width:100%; margin-top:2px;">
|
||||
<?php echo htmlspecialchars($item['title']); ?>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($todo_items)): ?>
|
||||
<li class="list-group-item text-muted text-center py-3">Keine Einträge in dieser Liste.</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card h-100">
|
||||
<div class="card-header card-header-stats"><h5 class="mb-0"><i class="fas fa-chart-bar me-2"></i>Statistiken</h5></div>
|
||||
<div class="card-body">
|
||||
<div class="stats-table-container mb-4">
|
||||
<h6>Gewicht pro Träger</h6>
|
||||
<ul class="list-group list-group-flush bg-transparent">
|
||||
<?php foreach ($weight_by_carrier as $carrier => $weight): ?>
|
||||
<li class="list-group-item px-1 py-2 bg-transparent">
|
||||
<strong><?php echo htmlspecialchars($carrier); ?></strong>
|
||||
<div class="d-flex justify-content-between align-items-center text-muted small mt-1">
|
||||
Gesamt:<span class="badge bg-success rounded-pill"><?php echo number_format($weight, 0, ',', '.'); ?> g</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center text-muted small">
|
||||
Basis (o. Verbr.):<span class="badge bg-secondary rounded-pill"><?php echo number_format($weight_by_carrier_non_consumable[$carrier] ?? 0, 0, ',', '.'); ?> g</span>
|
||||
</div>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6"><h6 class="text-center small">nach Kategorie</h6><div class="chart-container"><canvas id="categoryWeightChart"></canvas></div></div>
|
||||
<div class="col-6"><h6 class="text-center small">nach Träger</h6><div class="chart-container"><canvas id="carrierWeightChart"></canvas></div></div>
|
||||
</div>
|
||||
|
||||
<div class="stats-table-container mt-4">
|
||||
<h6>Gewicht nach Kategorie</h6>
|
||||
<div class="table-responsive">
|
||||
<table id="category-weight-table" class="table table-sm table-hover mb-0">
|
||||
<tbody>
|
||||
<?php
|
||||
arsort($weight_by_category);
|
||||
foreach($weight_by_category as $cat => $w):
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($cat); ?></td>
|
||||
<td class="text-end"><?php echo number_format($w, 0, ',', '.'); ?> g</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal for Carrier Statistics -->
|
||||
<div class="modal fade" id="carrierStatsModal" tabindex="-1" aria-labelledby="carrierStatsModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="carrierStatsModalLabel">Statistik für Träger</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Schließen"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="carrier-stats-content">
|
||||
<!-- Populated via JS -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="image-preview-tooltip"></div>
|
||||
|
||||
<script>
|
||||
// Pass PHP Data to JS
|
||||
const carrierStatsData = <?php echo json_encode($carrier_stats_details); ?>;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Tooltip logic with EVENT DELEGATION
|
||||
const tooltip = document.getElementById('image-preview-tooltip');
|
||||
if (tooltip) {
|
||||
document.body.addEventListener('mouseover', function(e) {
|
||||
if (e.target.classList.contains('article-image-trigger')) {
|
||||
const url = e.target.getAttribute('data-preview-url');
|
||||
if (url && !url.endsWith('assets/images/keinbild.png')) {
|
||||
tooltip.style.backgroundImage = `url('${url}')`;
|
||||
tooltip.style.display = 'block';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.body.addEventListener('mousemove', function(e) {
|
||||
if (tooltip.style.display === 'block') {
|
||||
tooltip.style.left = e.pageX + 15 + 'px';
|
||||
tooltip.style.top = e.pageY + 15 + 'px';
|
||||
}
|
||||
});
|
||||
|
||||
document.body.addEventListener('mouseout', function(e) {
|
||||
if (e.target.classList.contains('article-image-trigger')) {
|
||||
tooltip.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl) });
|
||||
|
||||
// Chart logic (PURE GREEN TONES - High Contrast)
|
||||
Chart.register(ChartDataLabels);
|
||||
|
||||
const greenColors = [
|
||||
'#2e7d32', // Dark Forest Green
|
||||
'#4caf50', // Standard Green
|
||||
'#81c784', // Light Pastel Green
|
||||
'#a5d6a7', // Very Light Green
|
||||
'#1b5e20', // Deep Dark Green
|
||||
'#66bb6a', // Medium Green
|
||||
'#00e676', // Neon Green (Accent)
|
||||
'#c8e6c9', // White-Green
|
||||
'#00c853', // Vibrant Green
|
||||
'#69f0ae', // Soft Neon
|
||||
'#388e3c' // Solid Green
|
||||
];
|
||||
|
||||
const chartOptions = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
layout: {
|
||||
padding: 20 // Add padding to prevent cutting off hover
|
||||
},
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
datalabels: { display: false }
|
||||
}
|
||||
};
|
||||
|
||||
const catCtx = document.getElementById('categoryWeightChart');
|
||||
if (catCtx) {
|
||||
new Chart(catCtx, { type: 'doughnut', data: { labels: <?php echo json_encode(array_keys($weight_by_category)); ?>, datasets: [{ data: <?php echo json_encode(array_values($weight_by_category)); ?>, backgroundColor: greenColors, borderWidth: 0, hoverOffset: 20 }] }, options: chartOptions });
|
||||
}
|
||||
|
||||
const carrierCtx = document.getElementById('carrierWeightChart');
|
||||
if (carrierCtx) {
|
||||
new Chart(carrierCtx, { type: 'doughnut', data: { labels: <?php echo json_encode(array_keys($weight_by_carrier)); ?>, datasets: [{ data: <?php echo json_encode(array_values($weight_by_carrier)); ?>, backgroundColor: greenColors, borderWidth: 0, hoverOffset: 20 }] }, options: chartOptions });
|
||||
}
|
||||
|
||||
// Collapsible Tree Logic
|
||||
document.querySelectorAll('.toggle-tree-btn').forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const parentId = this.getAttribute('data-target-id');
|
||||
const icon = this.querySelector('i');
|
||||
const isExpanded = icon.classList.contains('fa-chevron-down');
|
||||
|
||||
icon.classList.toggle('fa-chevron-down');
|
||||
icon.classList.toggle('fa-chevron-right');
|
||||
|
||||
toggleChildren(parentId, !isExpanded);
|
||||
});
|
||||
});
|
||||
|
||||
function toggleChildren(parentId, show) {
|
||||
const directChildren = document.querySelectorAll(`tr[data-parent-id="${parentId}"]`);
|
||||
directChildren.forEach(row => {
|
||||
row.style.display = show ? '' : 'none';
|
||||
const rowId = row.getAttribute('data-id');
|
||||
if (!show) {
|
||||
toggleChildren(rowId, false);
|
||||
} else {
|
||||
const btn = row.querySelector('.toggle-tree-btn');
|
||||
if (btn) {
|
||||
const isExpanded = btn.querySelector('i').classList.contains('fa-chevron-down');
|
||||
if (isExpanded) {
|
||||
toggleChildren(rowId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Carrier Stats Modal Logic
|
||||
const statsModal = new bootstrap.Modal(document.getElementById('carrierStatsModal'));
|
||||
document.querySelectorAll('.carrier-stats-link').forEach(link => {
|
||||
link.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const carrierName = this.getAttribute('data-carrier');
|
||||
const data = carrierStatsData[carrierName];
|
||||
|
||||
if (data) {
|
||||
document.getElementById('carrierStatsModalLabel').innerText = 'Statistik für ' + carrierName;
|
||||
|
||||
// Format Numbers
|
||||
const fmt = (n) => new Intl.NumberFormat('de-DE').format(n) + ' g';
|
||||
|
||||
let catRows = '';
|
||||
// Sort categories by weight desc
|
||||
const sortedCats = Object.entries(data.categories).sort((a, b) => b[1] - a[1]);
|
||||
|
||||
sortedCats.forEach(([cat, w]) => {
|
||||
catRows += `<tr><td>${cat}</td><td class="text-end">${fmt(w)}</td></tr>`;
|
||||
});
|
||||
|
||||
const content = `
|
||||
<div class="row mb-3">
|
||||
<div class="col-6">
|
||||
<div class="card text-center bg-light h-100">
|
||||
<div class="card-body py-2">
|
||||
<small class="text-muted">Gesamtgewicht</small>
|
||||
<h5 class="card-title mb-0 text-primary">${fmt(data.total_weight)}</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="card text-center bg-light h-100">
|
||||
<div class="card-body py-2">
|
||||
<small class="text-muted">Basisgewicht (o. Verb.)</small>
|
||||
<h5 class="card-title mb-0 text-success">${fmt(data.base_weight)}</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h6 class="border-bottom pb-2">Kategorien</h6>
|
||||
<table class="table table-sm table-striped">
|
||||
<tbody>${catRows}</tbody>
|
||||
</table>
|
||||
`;
|
||||
|
||||
document.getElementById('carrier-stats-content').innerHTML = content;
|
||||
statsModal.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once 'footer.php'; ?>hp require_once 'footer.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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
?>
|
||||
<div class="container-fluid p-0">
|
||||
<h1 class="h3 mb-4 text-gray-800"><i class="fas fa-list-check me-2"></i>ToDo-Listen</h1>
|
||||
|
||||
<?php if ($message) echo "<div class='alert alert-info'>" . htmlspecialchars($message) . "</div>"; ?>
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2 class="h4 mb-0"><i class="fas fa-list-check me-2"></i>ToDo-Listen</h2>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<?php if ($message) echo "<div class='alert alert-info'>" . htmlspecialchars($message) . "</div>"; ?>
|
||||
|
||||
<div class="row">
|
||||
<!-- List Selection -->
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="fas fa-list me-2"></i>Meine Listen</h5>
|
||||
</div>
|
||||
<div class="list-group list-group-flush">
|
||||
<?php foreach ($todo_lists as $list): ?>
|
||||
<a href="?list_id=<?php echo $list['id']; ?>" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center <?php echo $active_list_id == $list['id'] ? 'list-group-item-secondary fw-bold border-start border-4 border-dark' : ''; ?>">
|
||||
<?php echo htmlspecialchars($list['name']); ?>
|
||||
<form method="post" style="display:inline;" onsubmit="return confirm('Liste wirklich löschen?');">
|
||||
<input type="hidden" name="list_id" value="<?php echo $list['id']; ?>">
|
||||
<button type="submit" name="delete_list" class="btn btn-sm btn-link text-danger p-0"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($todo_lists)): ?>
|
||||
<div class="list-group-item text-muted">Keine Listen vorhanden.</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="card-body bg-light">
|
||||
<form method="post">
|
||||
<div class="input-group">
|
||||
<input type="text" name="list_name" class="form-control" placeholder="Neue Liste erstellen..." required>
|
||||
<button type="submit" name="create_list" class="btn btn-dark"><i class="fas fa-plus"></i></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- List Items -->
|
||||
<div class="col-md-8 mb-4">
|
||||
<?php if ($active_list_id > 0): ?>
|
||||
<?php
|
||||
$stmt = $conn->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'];
|
||||
?>
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0"><i class="fas fa-tasks me-2"></i><?php echo htmlspecialchars($active_list_name); ?></h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="list-group list-group-flush mb-3">
|
||||
<?php foreach ($items as $item): ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center px-0">
|
||||
<form method="post" style="display:inline; margin:0;" class="flex-grow-1">
|
||||
<input type="hidden" name="item_id" value="<?php echo $item['id']; ?>">
|
||||
<input type="hidden" name="list_id" value="<?php echo $active_list_id; ?>">
|
||||
<div class="form-check d-flex align-items-center">
|
||||
<input class="form-check-input me-2" type="checkbox" onChange="this.form.submit()" name="status" value="<?php echo $item['is_completed'] ? '0' : '1'; ?>" <?php echo $item['is_completed'] ? 'checked' : ''; ?> style="width:1.5em; height:1.5em; cursor:pointer;">
|
||||
<input type="hidden" name="toggle_item" value="1">
|
||||
<label class="form-check-label ms-2 <?php echo $item['is_completed'] ? 'text-decoration-line-through text-muted' : ''; ?>" style="cursor:pointer; font-size:1.1em; width:100%; margin-top:3px;">
|
||||
<?php echo htmlspecialchars($item['title']); ?>
|
||||
</label>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- List Selection -->
|
||||
<div class="col-md-4 mb-4 mb-md-0">
|
||||
<div class="card h-100 bg-light border-0">
|
||||
<div class="card-body p-3">
|
||||
<h5 class="mb-3"><i class="fas fa-list me-2"></i>Meine Listen</h5>
|
||||
<div class="list-group mb-3 shadow-sm">
|
||||
<?php foreach ($todo_lists as $list): ?>
|
||||
<a href="?list_id=<?php echo $list['id']; ?>" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center <?php echo $active_list_id == $list['id'] ? 'list-group-item-secondary fw-bold border-start border-4 border-dark' : ''; ?>">
|
||||
<?php echo htmlspecialchars($list['name']); ?>
|
||||
<form method="post" style="display:inline;" onsubmit="return confirm('Liste wirklich löschen?');">
|
||||
<input type="hidden" name="list_id" value="<?php echo $list['id']; ?>">
|
||||
<button type="submit" name="delete_list" class="btn btn-sm btn-link text-danger p-0" title="Löschen"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
<form method="post" style="display:inline;">
|
||||
<input type="hidden" name="item_id" value="<?php echo $item['id']; ?>">
|
||||
<input type="hidden" name="list_id" value="<?php echo $active_list_id; ?>">
|
||||
<button type="submit" name="delete_item" class="btn btn-sm btn-outline-danger"><i class="fas fa-times"></i></button>
|
||||
</form>
|
||||
</li>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($items)): ?>
|
||||
<li class="list-group-item text-muted px-0">Noch keine Punkte auf dieser Liste.</li>
|
||||
<?php if (empty($todo_lists)): ?>
|
||||
<div class="list-group-item text-muted">Keine Listen vorhanden.</div>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<form method="post">
|
||||
<input type="hidden" name="list_id" value="<?php echo $active_list_id; ?>">
|
||||
<div class="input-group">
|
||||
<input type="text" name="item_title" class="form-control" placeholder="Neuer Punkt..." required>
|
||||
<button type="submit" name="add_item" class="btn btn-success"><i class="fas fa-plus me-2"></i>Hinzufügen</button>
|
||||
<div class="input-group shadow-sm">
|
||||
<input type="text" name="list_name" class="form-control" placeholder="Neue Liste..." required>
|
||||
<button type="submit" name="create_list" class="btn btn-dark"><i class="fas fa-plus"></i></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-secondary">Wähle links eine Liste aus oder erstelle eine neue.</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- List Items -->
|
||||
<div class="col-md-8">
|
||||
<?php if ($active_list_id > 0): ?>
|
||||
<?php
|
||||
$stmt = $conn->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'];
|
||||
?>
|
||||
<div class="card h-100 border-0 shadow-sm">
|
||||
<div class="card-header bg-white border-bottom">
|
||||
<h5 class="mb-0 py-2"><i class="fas fa-tasks me-2 text-muted"></i><?php echo htmlspecialchars($active_list_name); ?></h5>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<ul class="list-group list-group-flush mb-4">
|
||||
<?php foreach ($items as $item): ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center py-3 px-2 border-bottom">
|
||||
<form method="post" style="display:inline; margin:0;" class="flex-grow-1">
|
||||
<input type="hidden" name="item_id" value="<?php echo $item['id']; ?>">
|
||||
<input type="hidden" name="list_id" value="<?php echo $active_list_id; ?>">
|
||||
<div class="form-check d-flex align-items-center mb-0">
|
||||
<input class="form-check-input me-3" type="checkbox" onChange="this.form.submit()" name="status" value="<?php echo $item['is_completed'] ? '0' : '1'; ?>" <?php echo $item['is_completed'] ? 'checked' : ''; ?> style="width:1.5em; height:1.5em; cursor:pointer;">
|
||||
<input type="hidden" name="toggle_item" value="1">
|
||||
<label class="form-check-label <?php echo $item['is_completed'] ? 'text-decoration-line-through text-muted' : ''; ?>" style="cursor:pointer; font-size:1.1em; width:100%; margin-top:2px;">
|
||||
<?php echo htmlspecialchars($item['title']); ?>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<form method="post" style="display:inline;" class="ms-3">
|
||||
<input type="hidden" name="item_id" value="<?php echo $item['id']; ?>">
|
||||
<input type="hidden" name="list_id" value="<?php echo $active_list_id; ?>">
|
||||
<button type="submit" name="delete_item" class="btn btn-sm btn-outline-danger" title="Punkt entfernen"><i class="fas fa-times"></i></button>
|
||||
</form>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($items)): ?>
|
||||
<li class="list-group-item text-muted text-center py-5 border-bottom-0">Noch keine Punkte auf dieser Liste. Füge unten einen hinzu!</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
|
||||
<form method="post" class="mt-auto">
|
||||
<input type="hidden" name="list_id" value="<?php echo $active_list_id; ?>">
|
||||
<div class="input-group shadow-sm">
|
||||
<input type="text" name="item_title" class="form-control" placeholder="Neuen Punkt hinzufügen..." required>
|
||||
<button type="submit" name="add_item" class="btn btn-success px-4"><i class="fas fa-plus me-2"></i>Hinzufügen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-secondary d-flex align-items-center h-100 m-0">
|
||||
<div>
|
||||
<h5 class="alert-heading">Keine Liste ausgewählt</h5>
|
||||
<p class="mb-0">Wähle links eine Liste aus oder erstelle eine neue Liste, um Aufgaben hinzuzufügen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once 'footer.php';
|
||||
if (isset($conn) && $conn instanceof mysqli) $conn->close();
|
||||
?>se();
|
||||
?>e();
|
||||
?>nn->close();
|
||||
if (isset($conn) && $conn instanceof mysqli) {
|
||||
$conn->close();
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user