Fix: Gewichtsberechnung Zusatztaschen, UI-Konsistenz bei Editieren, Icons
All checks were successful
Docker Build & Push / build-and-push (push) Successful in 23s
All checks were successful
Docker Build & Push / build-and-push (push) Successful in 23s
This commit is contained in:
@@ -12,7 +12,7 @@ if (!isset($_SESSION['user_id'])) {
|
||||
|
||||
require_once 'db_connect.php';
|
||||
require_once 'household_actions.php';
|
||||
require_once 'backpack_utils.php'; // Fix: Include utils
|
||||
require_once 'backpack_utils.php';
|
||||
require_once 'header.php';
|
||||
|
||||
$current_user_id = $_SESSION['user_id'];
|
||||
@@ -91,55 +91,59 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && $can_edit) {
|
||||
$packing_list['name'] = $name;
|
||||
$packing_list['description'] = $description;
|
||||
|
||||
// Handle Backpack Assignments
|
||||
if (isset($_POST['backpacks'])) {
|
||||
foreach ($_POST['backpacks'] as $uid => $bid) {
|
||||
$uid = intval($uid);
|
||||
$bid = intval($bid);
|
||||
// Handle Participation & Backpacks
|
||||
// Get all potential users to check if they were unchecked
|
||||
$participate_map = $_POST['participate'] ?? []; // Array of UserID => "1" if checked
|
||||
|
||||
foreach ($available_users as $user) {
|
||||
$uid = $user['id'];
|
||||
$is_checked = isset($participate_map[$uid]);
|
||||
$was_participating = array_key_exists($uid, $current_assignments);
|
||||
|
||||
if ($is_checked) {
|
||||
// User participates -> Update/Insert Backpack
|
||||
$bid = isset($_POST['backpacks'][$uid]) ? intval($_POST['backpacks'][$uid]) : 0;
|
||||
$bid = ($bid > 0) ? $bid : NULL;
|
||||
|
||||
// Update Carrier Table
|
||||
// Check if exists
|
||||
$old_backpack_id = 0;
|
||||
$stmt_chk = $conn->prepare("SELECT id, backpack_id FROM packing_list_carriers WHERE packing_list_id = ? AND user_id = ?");
|
||||
$stmt_chk->bind_param("ii", $packing_list_id, $uid);
|
||||
$stmt_chk->execute();
|
||||
$res_chk = $stmt_chk->get_result();
|
||||
if ($row_chk = $res_chk->fetch_assoc()) {
|
||||
$old_backpack_id = $row_chk['backpack_id'];
|
||||
$stmt_up = $conn->prepare("UPDATE packing_list_carriers SET backpack_id = ? WHERE packing_list_id = ? AND user_id = ?");
|
||||
$stmt_up->bind_param("iii", $bid, $packing_list_id, $uid);
|
||||
$stmt_up->execute();
|
||||
|
||||
if ($was_participating) {
|
||||
$old_bid = $current_assignments[$uid];
|
||||
// Update if changed
|
||||
if ($old_bid != $bid) {
|
||||
$stmt_up = $conn->prepare("UPDATE packing_list_carriers SET backpack_id = ? WHERE packing_list_id = ? AND user_id = ?");
|
||||
$stmt_up->bind_param("iii", $bid, $packing_list_id, $uid);
|
||||
$stmt_up->execute();
|
||||
|
||||
// Cleanup Old Containers
|
||||
cleanup_old_backpack_containers($conn, $packing_list_id, $uid);
|
||||
|
||||
// Sync New
|
||||
if ($bid) {
|
||||
sync_backpack_items($conn, $packing_list_id, $uid, $bid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// New Participant
|
||||
$stmt_in = $conn->prepare("INSERT INTO packing_list_carriers (packing_list_id, user_id, backpack_id) VALUES (?, ?, ?)");
|
||||
$stmt_in->bind_param("iii", $packing_list_id, $uid, $bid);
|
||||
$stmt_in->execute();
|
||||
}
|
||||
|
||||
// CLEANUP LOGIC: If backpack changed or removed
|
||||
if ($old_backpack_id != $bid) {
|
||||
// 1. Unparent all items that are inside the old containers (so they don't get deleted)
|
||||
// Find all container items for this user
|
||||
$stmt_find_containers = $conn->prepare("SELECT id FROM packing_list_items WHERE packing_list_id = ? AND carrier_user_id = ? AND (backpack_id IS NOT NULL OR backpack_compartment_id IS NOT NULL)");
|
||||
$stmt_find_containers->bind_param("ii", $packing_list_id, $uid);
|
||||
$stmt_find_containers->execute();
|
||||
$res_cont = $stmt_find_containers->get_result();
|
||||
$container_ids = [];
|
||||
while ($r = $res_cont->fetch_assoc()) $container_ids[] = $r['id'];
|
||||
|
||||
if (!empty($container_ids)) {
|
||||
$ids_str = implode(',', $container_ids);
|
||||
// Set parent to NULL for children of these containers
|
||||
$conn->query("UPDATE packing_list_items SET parent_packing_list_item_id = NULL WHERE packing_list_id = $packing_list_id AND parent_packing_list_item_id IN ($ids_str)");
|
||||
|
||||
// 2. Delete the containers
|
||||
$conn->query("DELETE FROM packing_list_items WHERE id IN ($ids_str)");
|
||||
if ($bid) {
|
||||
sync_backpack_items($conn, $packing_list_id, $uid, $bid);
|
||||
}
|
||||
}
|
||||
|
||||
// SYNC LOGIC (Only if new backpack assigned)
|
||||
if ($bid && $old_backpack_id != $bid) {
|
||||
sync_backpack_items($conn, $packing_list_id, $uid, $bid);
|
||||
} else {
|
||||
// User NOT checked -> Remove if existed
|
||||
if ($was_participating) {
|
||||
$conn->query("DELETE FROM packing_list_carriers WHERE packing_list_id = $packing_list_id AND user_id = $uid");
|
||||
// Cleanup Items: Delete all items carried by this user?
|
||||
// Or move to unassigned? Let's move to unassigned (NULL) to be safe against data loss.
|
||||
// But Containers (Backpacks) should be deleted.
|
||||
|
||||
// 1. Delete Containers
|
||||
cleanup_old_backpack_containers($conn, $packing_list_id, $uid);
|
||||
|
||||
// 2. Move remaining items (loose items) to unassigned?
|
||||
$conn->query("UPDATE packing_list_items SET carrier_user_id = NULL WHERE packing_list_id = $packing_list_id AND carrier_user_id = $uid");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,6 +158,26 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && $can_edit) {
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup_old_backpack_containers($conn, $list_id, $user_id) {
|
||||
// Find all container items for this user (backpacks or compartments)
|
||||
$stmt = $conn->prepare("SELECT id FROM packing_list_items WHERE packing_list_id = ? AND carrier_user_id = ? AND (backpack_id IS NOT NULL OR backpack_compartment_id IS NOT NULL)");
|
||||
$stmt->bind_param("ii", $list_id, $user_id);
|
||||
$stmt->execute();
|
||||
$res = $stmt->get_result();
|
||||
$container_ids = [];
|
||||
while ($r = $res->fetch_assoc()) $container_ids[] = $r['id'];
|
||||
|
||||
if (!empty($container_ids)) {
|
||||
$ids_str = implode(',', $container_ids);
|
||||
// Unparent children so they don't get deleted (or keep them and they get deleted? No, save content)
|
||||
// Set parent to NULL for children of these containers
|
||||
$conn->query("UPDATE packing_list_items SET parent_packing_list_item_id = NULL WHERE packing_list_id = $list_id AND parent_packing_list_item_id IN ($ids_str)");
|
||||
|
||||
// Delete containers
|
||||
$conn->query("DELETE FROM packing_list_items WHERE id IN ($ids_str)");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="card">
|
||||
@@ -165,7 +189,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && $can_edit) {
|
||||
<?php echo $message; ?>
|
||||
|
||||
<?php if ($packing_list): ?>
|
||||
<form method="post">
|
||||
<form method="post" id="editListForm">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h5 class="mb-3">Basisdaten</h5>
|
||||
@@ -180,35 +204,41 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && $can_edit) {
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<h5 class="mb-3">Rucksack-Zuweisung</h5>
|
||||
<h5 class="mb-3">Teilnehmer & Rucksäcke</h5>
|
||||
<div class="card bg-light border-0">
|
||||
<div class="card-body">
|
||||
<p class="small text-muted">Wähle hier, wer welchen Rucksack trägt. Bereits vergebene Rucksäcke werden ausgeblendet.</p>
|
||||
<p class="small text-muted">Wähle hier, wer mitkommt und welchen Rucksack er trägt.</p>
|
||||
|
||||
<div id="backpack-warning" class="alert alert-warning d-none small p-2 mb-2">
|
||||
<i class="fas fa-exclamation-triangle me-1"></i> Ein Rucksack wurde mehrfach ausgewählt!
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// Calculate used backpacks
|
||||
$all_assigned_backpack_ids = array_values($current_assignments);
|
||||
|
||||
// Prepare data for JS (still needed for the render helper)
|
||||
$user_backpacks_json = [];
|
||||
|
||||
foreach ($available_users as $user):
|
||||
$user_backpacks = get_available_backpacks_for_user($conn, $user['id'], $packing_list['household_id']);
|
||||
$is_participating = array_key_exists($user['id'], $current_assignments);
|
||||
$my_current_bp_id = $current_assignments[$user['id']] ?? 0;
|
||||
|
||||
// Store for JS
|
||||
$user_backpacks_json[$user['id']] = [
|
||||
'current_id' => $my_current_bp_id,
|
||||
'backpacks' => $user_backpacks
|
||||
];
|
||||
|
||||
// Use helper to render the widget
|
||||
echo '<div class="mb-4 border-bottom pb-3">';
|
||||
echo '<label class="form-label fw-bold mb-2">' . htmlspecialchars($user['username']) . '</label>';
|
||||
echo render_backpack_card_selector($user, $my_current_bp_id, $user_backpacks);
|
||||
echo '</div>';
|
||||
endforeach;
|
||||
?>
|
||||
<div class="mb-4 border-bottom pb-3">
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input participation-check" type="checkbox" name="participate[<?php echo $user['id']; ?>]" value="1" <?php echo $is_participating ? 'checked' : ''; ?> id="part_<?php echo $user['id']; ?>">
|
||||
<label class="form-check-label fw-bold" for="part_<?php echo $user['id']; ?>">
|
||||
<?php echo htmlspecialchars($user['username']); ?>
|
||||
</label>
|
||||
</div>
|
||||
<div class="ms-4 backpack-selector-wrapper" style="<?php echo $is_participating ? '' : 'opacity: 0.5; pointer-events: none;'; ?>">
|
||||
<?php echo render_backpack_card_selector($user, $my_current_bp_id, $user_backpacks); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -218,7 +248,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && $can_edit) {
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="manage_packing_list_items.php?id=<?php echo $packing_list_id; ?>" class="btn btn-info text-white"><i class="fas fa-boxes me-2"></i>Inhalt bearbeiten</a>
|
||||
<button type="submit" class="btn btn-primary"><i class="fas fa-save me-2"></i>Speichern & Synchronisieren</button>
|
||||
<button type="submit" class="btn btn-primary" id="submitBtn"><i class="fas fa-save me-2"></i>Speichern & Synchronisieren</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
@@ -228,4 +258,63 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && $can_edit) {
|
||||
<!-- Render Modal JS -->
|
||||
<?php echo render_backpack_modal_script($user_backpacks_json, $all_assigned_backpack_ids); ?>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const submitBtn = document.getElementById('submitBtn');
|
||||
const warning = document.getElementById('backpack-warning');
|
||||
|
||||
// Toggle Opacity logic
|
||||
document.querySelectorAll('.participation-check').forEach(chk => {
|
||||
chk.addEventListener('change', function() {
|
||||
const wrapper = this.closest('.mb-4').querySelector('.backpack-selector-wrapper');
|
||||
if (this.checked) {
|
||||
wrapper.style.opacity = '1';
|
||||
wrapper.style.pointerEvents = 'auto';
|
||||
} else {
|
||||
wrapper.style.opacity = '0.5';
|
||||
wrapper.style.pointerEvents = 'none';
|
||||
}
|
||||
validateBackpacks();
|
||||
});
|
||||
});
|
||||
|
||||
// Validation Logic (Copied from add_packing_list.php)
|
||||
function validateBackpacks() {
|
||||
const selected = [];
|
||||
let hasDuplicate = false;
|
||||
|
||||
const inputs = document.querySelectorAll('input[name^="backpacks["]');
|
||||
|
||||
inputs.forEach(input => {
|
||||
const userIdMatch = input.name.match(/backpacks\[(\d+)\]/);
|
||||
if (userIdMatch) {
|
||||
const userId = userIdMatch[1];
|
||||
const partCheck = document.getElementById('part_' + userId);
|
||||
|
||||
if (partCheck && partCheck.checked) {
|
||||
const val = parseInt(input.value);
|
||||
if (val > 0) {
|
||||
if (selected.includes(val)) {
|
||||
hasDuplicate = true;
|
||||
}
|
||||
selected.push(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (hasDuplicate) {
|
||||
warning.classList.remove('d-none');
|
||||
submitBtn.disabled = true;
|
||||
} else {
|
||||
warning.classList.add('d-none');
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
document.body.addEventListener('hidden.bs.modal', validateBackpacks);
|
||||
validateBackpacks();
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once 'footer.php'; ?>
|
||||
Reference in New Issue
Block a user