Fix: Rucksack-Kategorie (DB/UI/Stats) und Tooltip-Zuverlässigkeit
All checks were successful
Docker Build & Push / build-and-push (push) Successful in 28s
All checks were successful
Docker Build & Push / build-and-push (push) Successful in 28s
This commit is contained in:
@@ -30,6 +30,11 @@ $check_col = $conn->query("SHOW COLUMNS FROM backpacks LIKE 'product_url'");
|
||||
if ($check_col && $check_col->num_rows == 0) {
|
||||
$conn->query("ALTER TABLE backpacks ADD COLUMN product_url VARCHAR(255) DEFAULT NULL AFTER image_url");
|
||||
}
|
||||
$check_col_cat = $conn->query("SHOW COLUMNS FROM backpacks LIKE 'category_id'");
|
||||
if ($check_col_cat && $check_col_cat->num_rows == 0) {
|
||||
$conn->query("ALTER TABLE backpacks ADD COLUMN category_id INT DEFAULT NULL");
|
||||
$conn->query("ALTER TABLE backpacks ADD CONSTRAINT fk_bp_category FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL");
|
||||
}
|
||||
$check_col_c = $conn->query("SHOW COLUMNS FROM backpack_compartments LIKE 'linked_article_id'");
|
||||
if ($check_col_c && $check_col_c->num_rows == 0) {
|
||||
$conn->query("ALTER TABLE backpack_compartments ADD COLUMN linked_article_id INT DEFAULT NULL");
|
||||
@@ -103,14 +108,7 @@ if ($backpack_id > 0) {
|
||||
}
|
||||
}
|
||||
|
||||
// Load Manufacturers
|
||||
$stmt_man_load = $conn->prepare("SELECT id, name FROM manufacturers WHERE user_id = ? ORDER BY name ASC");
|
||||
$stmt_man_load->bind_param("i", $user_id);
|
||||
$stmt_man_load->execute();
|
||||
$manufacturers = $stmt_man_load->get_result()->fetch_all(MYSQLI_ASSOC);
|
||||
$stmt_man_load->close();
|
||||
|
||||
// Load Articles for Linked Compartments
|
||||
// Load Manufacturers & Categories
|
||||
$hh_ids = [$user_id];
|
||||
if ($household_id) {
|
||||
$stmt_hhm = $conn->prepare("SELECT id FROM users WHERE household_id = ?");
|
||||
@@ -121,6 +119,22 @@ if ($household_id) {
|
||||
}
|
||||
$placeholders = implode(',', array_fill(0, count($hh_ids), '?'));
|
||||
$types_hh = str_repeat('i', count($hh_ids));
|
||||
|
||||
// Manufacturers
|
||||
$stmt_man_load = $conn->prepare("SELECT id, name FROM manufacturers WHERE user_id IN ($placeholders) ORDER BY name ASC");
|
||||
$stmt_man_load->bind_param($types_hh, ...$hh_ids);
|
||||
$stmt_man_load->execute();
|
||||
$manufacturers = $stmt_man_load->get_result()->fetch_all(MYSQLI_ASSOC);
|
||||
$stmt_man_load->close();
|
||||
|
||||
// Categories
|
||||
$stmt_cat_load = $conn->prepare("SELECT id, name FROM categories WHERE user_id IN ($placeholders) ORDER BY name ASC");
|
||||
$stmt_cat_load->bind_param($types_hh, ...$hh_ids);
|
||||
$stmt_cat_load->execute();
|
||||
$categories = $stmt_cat_load->get_result()->fetch_all(MYSQLI_ASSOC);
|
||||
$stmt_cat_load->close();
|
||||
|
||||
// Load Articles for Linked Compartments
|
||||
$stmt_arts = $conn->prepare("SELECT id, name, weight_grams, image_url FROM articles WHERE user_id IN ($placeholders) OR household_id = ? ORDER BY name ASC");
|
||||
$params_arts = array_merge($hh_ids, [$household_id ?: 0]);
|
||||
$types_arts = $types_hh . 'i';
|
||||
@@ -134,6 +148,7 @@ $stmt_arts->close();
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$name = trim($_POST['name']);
|
||||
|
||||
// Manufacturer Logic
|
||||
$manufacturer = '';
|
||||
if (isset($_POST['manufacturer_select'])) {
|
||||
if ($_POST['manufacturer_select'] === 'new') {
|
||||
@@ -169,6 +184,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$volume = intval($_POST['volume_liters']);
|
||||
$share_household = isset($_POST['share_household']) ? 1 : 0;
|
||||
$product_url_input = trim($_POST['product_url'] ?? '');
|
||||
$category_id = !empty($_POST['category_id']) ? intval($_POST['category_id']) : NULL;
|
||||
|
||||
$image_url_for_db = $image_url;
|
||||
$pasted_image = $_POST['pasted_image_data'] ?? '';
|
||||
@@ -194,12 +210,12 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$final_household_id = ($share_household && $household_id) ? $household_id : NULL;
|
||||
|
||||
if ($backpack_id > 0) {
|
||||
$stmt = $conn->prepare("UPDATE backpacks SET name=?, manufacturer=?, model=?, weight_grams=?, volume_liters=?, household_id=?, image_url=?, product_url=? WHERE id=? AND user_id=?");
|
||||
$stmt->bind_param("sssiisssii", $name, $manufacturer, $model, $weight, $volume, $final_household_id, $image_url_for_db, $product_url_input, $backpack_id, $user_id);
|
||||
$stmt = $conn->prepare("UPDATE backpacks SET name=?, manufacturer=?, model=?, weight_grams=?, volume_liters=?, household_id=?, image_url=?, product_url=?, category_id=? WHERE id=? AND user_id=?");
|
||||
$stmt->bind_param("sssiisssiii", $name, $manufacturer, $model, $weight, $volume, $final_household_id, $image_url_for_db, $product_url_input, $category_id, $backpack_id, $user_id);
|
||||
$stmt->execute();
|
||||
} else {
|
||||
$stmt = $conn->prepare("INSERT INTO backpacks (user_id, household_id, name, manufacturer, model, weight_grams, volume_liters, image_url, product_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("iisssiiss", $user_id, $final_household_id, $name, $manufacturer, $model, $weight, $volume, $image_url_for_db, $product_url_input);
|
||||
$stmt = $conn->prepare("INSERT INTO backpacks (user_id, household_id, name, manufacturer, model, weight_grams, volume_liters, image_url, product_url, category_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("iisssiissi", $user_id, $final_household_id, $name, $manufacturer, $model, $weight, $volume, $image_url_for_db, $product_url_input, $category_id);
|
||||
$stmt->execute();
|
||||
$backpack_id = $stmt->insert_id;
|
||||
}
|
||||
@@ -309,6 +325,19 @@ require_once 'header.php';
|
||||
<input type="text" name="new_manufacturer_name" class="form-control form-control-sm" placeholder="Name des neuen Herstellers">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Kategorie</label>
|
||||
<select class="form-select" id="category_id" name="category_id">
|
||||
<option value="">-- Keine (Sonstiges) --</option>
|
||||
<?php
|
||||
$current_cat = $backpack['category_id'] ?? 0;
|
||||
foreach ($categories as $cat):
|
||||
$selected = ($cat['id'] == $current_cat) ? 'selected' : '';
|
||||
?>
|
||||
<option value="<?php echo $cat['id']; ?>" <?php echo $selected; ?>><?php echo htmlspecialchars($cat['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Modell</label>
|
||||
<input type="text" name="model" class="form-control" value="<?php echo htmlspecialchars($backpack['model'] ?? ''); ?>">
|
||||
@@ -368,7 +397,7 @@ require_once 'header.php';
|
||||
</select>
|
||||
|
||||
<!-- Text Input -->
|
||||
<input type="text" name="comp_names[]" class="form-control name-input" placeholder="Fachname">
|
||||
<input type="text" name="comp_names[]" class="form-control name-input" value="Hauptfach" placeholder="Fachname">
|
||||
|
||||
<!-- Article Select -->
|
||||
<div class="flex-grow-1 article-select-wrapper" style="display:none;">
|
||||
@@ -456,6 +485,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
manSelect.addEventListener('change', function() { toggleManContainer(this.value); });
|
||||
new TomSelect(manSelect, { create: false, sortField: { field: "text", direction: "asc" }, onChange: function(value) { toggleManContainer(value); } });
|
||||
}
|
||||
|
||||
// New: Category Select
|
||||
if (document.getElementById('category_id')) {
|
||||
new TomSelect('#category_id', { create: false, sortField: { field: "text", direction: "asc" } });
|
||||
}
|
||||
|
||||
const container = document.getElementById('compartments-container');
|
||||
|
||||
@@ -601,4 +635,4 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once 'footer.php'; ?>
|
||||
<?php require_once 'footer.php'; ?>
|
||||
@@ -60,13 +60,14 @@ $stmt_list_owner->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,
|
||||
c.name AS category_name,
|
||||
COALESCE(c.name, c_bp.name, 'Sonstiges') AS category_name,
|
||||
m.name AS manufacturer_name,
|
||||
u.username AS carrier_name,
|
||||
u.id AS carrier_id
|
||||
@@ -75,6 +76,7 @@ $sql = "SELECT
|
||||
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 = ?
|
||||
@@ -394,19 +396,30 @@ function render_item_row($item, $level, $items_by_parent) {
|
||||
const carrierStatsData = <?php echo json_encode($carrier_stats_details); ?>;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Tooltip logic
|
||||
// Tooltip logic with EVENT DELEGATION
|
||||
const tooltip = document.getElementById('image-preview-tooltip');
|
||||
if (tooltip) {
|
||||
document.querySelectorAll('.article-image-trigger').forEach(trigger => {
|
||||
trigger.addEventListener('mouseover', e => {
|
||||
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';
|
||||
}
|
||||
});
|
||||
trigger.addEventListener('mousemove', e => { tooltip.style.left = e.pageX + 15 + 'px'; tooltip.style.top = e.pageY + 15 + 'px'; });
|
||||
trigger.addEventListener('mouseout', () => { tooltip.style.display = 'none'; });
|
||||
}
|
||||
});
|
||||
|
||||
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"]'));
|
||||
|
||||
Reference in New Issue
Block a user