Feature: Kategoriefarben, Card Heights angepasst
All checks were successful
Docker Build & Push / build-and-push (push) Successful in 38s

This commit is contained in:
Gemini
2026-05-14 20:36:04 +00:00
parent e2463f704a
commit 2637f4213b
6 changed files with 37 additions and 19 deletions

View File

@@ -83,7 +83,7 @@ $types = str_repeat('i', count($household_member_ids));
$sql = "SELECT
a.id, a.name, a.weight_grams, a.quantity_owned, a.product_url, a.consumable, a.image_url, a.user_id, a.parent_article_id,
u.username as creator_name, a.household_id, a.product_designation,
c.id AS category_id, c.name AS category_name,
c.id AS category_id, c.name AS category_name, c.color AS category_color,
m.id AS manufacturer_id, m.name AS manufacturer_name,
l2.name AS location_level2_name, l1.name AS location_level1_name
FROM articles a
@@ -399,15 +399,6 @@ document.addEventListener('DOMContentLoaded', function () {
initializeInteractivity();
}
function getColorForCategory(categoryName) {
let hash = 0;
for (let i = 0; i < categoryName.length; i++) {
hash = categoryName.charCodeAt(i) + ((hash << 5) - hash);
}
const hue = Math.abs(hash % 360);
return `hsl(${hue}, 60%, 85%)`;
}
function generateCardHTML(article) {
const imagePath = article.image_url ? article.image_url : 'assets/images/keinbild.png';
const productLink = article.product_url ? `<a href="${article.product_url}" target="_blank" class="btn btn-sm btn-outline-secondary px-1 py-0" title="Produktseite öffnen"><i class="fas fa-external-link-alt"></i></a>` : '';
@@ -427,7 +418,7 @@ document.addEventListener('DOMContentLoaded', function () {
const metaText = [article.manufacturer_name, article.product_designation].filter(Boolean).join(' - ');
const catName = article.category_name || 'Ohne Kat.';
const catColor = getColorForCategory(catName);
const catColor = article.category_color || '#e2e8f0';
return `
<div class="lager-card article-card" title="${article.name}${metaText ? ' (' + metaText + ')' : ''}">

View File

@@ -116,7 +116,7 @@ elseif (isset($_GET['action']) && $_GET['action'] == 'delete' && isset($_GET['id
$stmt_check->close();
}
$categories_query = $conn->prepare("SELECT c.id, c.name, c.user_id, u.username as creator_name FROM categories c JOIN users u ON c.user_id = u.id WHERE c.user_id IN ($placeholders) ORDER BY c.name ASC");
$categories_query = $conn->prepare("SELECT c.id, c.name, c.color, c.user_id, u.username as creator_name FROM categories c JOIN users u ON c.user_id = u.id WHERE c.user_id IN ($placeholders) ORDER BY c.name ASC");
$categories_query->bind_param($types, ...$household_member_ids);
$categories_query->execute();
$categories_list = $categories_query->get_result()->fetch_all(MYSQLI_ASSOC);
@@ -135,9 +135,13 @@ $conn->close();
<div class="card-body">
<h5 class="card-title mb-3">Neue Kategorie hinzufügen</h5>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post" class="row g-3 align-items-end">
<div class="col-sm-8">
<label for="category_name" class="form-label visually-hidden">Neue Kategorie</label>
<input type="text" class="form-control" id="category_name" name="category_name" placeholder="Name der neuen Kategorie" required>
<div class="col-sm-6">
<label for="category_name" class="form-label">Neue Kategorie</label>
<input type="text" class="form-control" id="category_name" name="category_name" placeholder="Name" required>
</div>
<div class="col-sm-2">
<label for="category_color" class="form-label">Farbe</label>
<input type="color" class="form-control form-control-color w-100" id="category_color" name="category_color" value="#e2e8f0" title="Farbe wählen">
</div>
<div class="col-sm-4">
<button type="submit" name="add_category" class="btn btn-primary w-100"><i class="fas fa-plus-circle me-2"></i>Hinzufügen</button>
@@ -154,7 +158,7 @@ $conn->close();
<?php foreach ($categories_list as $category): ?>
<div class="list-group-item d-flex justify-content-between align-items-center">
<div>
<i class="fas fa-tag text-muted me-2"></i>
<span class="badge border rounded-circle p-2 me-2" style="background-color: <?php echo htmlspecialchars($category['color'] ?? '#e2e8f0'); ?>; width:20px; height:20px; display:inline-block; vertical-align: middle;"></span>
<span class="fw-bold"><?php echo htmlspecialchars($category['name']); ?></span>
<?php if ($category['user_id'] != $current_user_id): ?>
<small class="text-muted ms-2">(von <?php echo htmlspecialchars($category['creator_name']); ?>)</small>
@@ -163,7 +167,7 @@ $conn->close();
<?php if ($category['user_id'] == $current_user_id): ?>
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-primary" title="Bearbeiten" data-bs-toggle="modal" data-bs-target="#editCategoryModal"
data-id="<?php echo htmlspecialchars($category['id']); ?>" data-name="<?php echo htmlspecialchars($category['name']); ?>">
data-id="<?php echo htmlspecialchars($category['id']); ?>" data-name="<?php echo htmlspecialchars($category['name']); ?>" data-color="<?php echo htmlspecialchars($category['color'] ?? '#e2e8f0'); ?>">
<i class="fas fa-edit"></i>
</button>
<a href="categories.php?action=delete&id=<?php echo htmlspecialchars($category['id']); ?>" class="btn btn-sm btn-outline-danger" title="Löschen" onclick="return confirm('Sind Sie sicher, dass Sie diese Kategorie löschen möchten? Artikel, die dieser Kategorie zugewiesen sind, verlieren ihre Zuordnung.')">
@@ -192,6 +196,10 @@ $conn->close();
<label for="edit_category_name" class="form-label">Kategoriename</label>
<input type="text" class="form-control" id="edit_category_name" name="category_name" required>
</div>
<div class="mb-3">
<label for="edit_category_color" class="form-label">Farbe</label>
<input type="color" class="form-control form-control-color w-100" id="edit_category_color" name="category_color" title="Farbe wählen">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
@@ -210,10 +218,13 @@ document.addEventListener('DOMContentLoaded', function() {
var button = event.relatedTarget;
var id = button.getAttribute('data-id');
var name = button.getAttribute('data-name');
var color = button.getAttribute('data-color');
var modalIdInput = editModal.querySelector('#edit_category_id');
var modalNameInput = editModal.querySelector('#edit_category_name');
var modalColorInput = editModal.querySelector('#edit_category_color');
if (modalIdInput) modalIdInput.value = id;
if (modalNameInput) modalNameInput.value = name;
if (modalColorInput) modalColorInput.value = color;
});
}
});

View File

@@ -56,4 +56,10 @@ if ($check_todo_list_id && $check_todo_list_id->num_rows == 0) {
$conn->query("ALTER TABLE packing_lists ADD COLUMN todo_list_id INT DEFAULT NULL");
$conn->query("ALTER TABLE packing_lists ADD CONSTRAINT fk_packing_list_todo FOREIGN KEY (todo_list_id) REFERENCES todo_lists(id) ON DELETE SET NULL");
}
// Ensure color exists in categories
$check_category_color = $conn->query("SHOW COLUMNS FROM categories LIKE 'color'");
if ($check_category_color && $check_category_color->num_rows == 0) {
$conn->query("ALTER TABLE categories ADD COLUMN color VARCHAR(7) DEFAULT '#e2e8f0'");
}
?>

View File

@@ -159,7 +159,7 @@ $conn->close();
border: 1px solid #eee; border-radius: 8px; padding: 6px;
text-align: center; background: #fff; display: flex; flex-direction: column;
transition: transform 0.1s, box-shadow 0.1s;
height: 200px;
height: 205px;
}
.lager-card:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.05); }
.lager-img-wrapper {

View File

@@ -107,6 +107,7 @@ $sql = "SELECT
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,
COALESCE(c.color, c_bp.color, '#e2e8f0') AS category_color,
m.name AS manufacturer_name,
COALESCE(NULLIF(u.display_name, ''), u.username) AS carrier_name,
u.id AS carrier_id
@@ -272,7 +273,14 @@ function render_item_row($item, $level, $items_by_parent) {
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>';
if ($item['category_name'] !== 'Sonstiges' && !empty($item['category_name'])) {
echo '<span class="badge rounded-pill" style="background-color: ' . htmlspecialchars($item['category_color']) . '; color: #333; font-weight: 500;">' . htmlspecialchars($item['category_name']) . '</span>';
} else {
echo '<span class="text-muted">---</span>';
}
echo '</td>';
echo '<td class="text-center">';
if ($is_backpack) {