Add shop management functionality with shopAdder page

This commit is contained in:
Fabian Schieder 2026-04-06 21:13:30 +02:00
parent b967e060c8
commit b3410a378f
3 changed files with 282 additions and 5 deletions

View File

@ -234,6 +234,9 @@ include 'header.php';
<a href="offerAdder.php" class="auth__submit account__action-link" style="margin-top: 10px; background-color: #f59e0b;"> <a href="offerAdder.php" class="auth__submit account__action-link" style="margin-top: 10px; background-color: #f59e0b;">
Angebot hinzufügen Angebot hinzufügen
</a> </a>
<a href="shopAdder.php" class="auth__submit account__action-link" style="margin-top: 10px; background-color: #10b981;">
Shop hinzufügen
</a>
<a href="admin_users.php" class="auth__submit account__action-link" style="margin-top: 10px; background-color: #3b82f6;"> <a href="admin_users.php" class="auth__submit account__action-link" style="margin-top: 10px; background-color: #3b82f6;">
Benutzerverwaltung Benutzerverwaltung
</a> </a>

View File

@ -81,14 +81,23 @@ if ($shopsResult) {
} }
} }
// Get existing offers to manage $filterProductID = isset($_GET['filter_product_id']) ? (int)$_GET['filter_product_id'] : 0;
$offersResult = $conn->query("
$offersQuery = "
SELECT o.offerID, p.model AS productName, s.name AS shopName, o.price SELECT o.offerID, p.model AS productName, s.name AS shopName, o.price
FROM offers o FROM offers o
JOIN products p ON o.productID = p.productID JOIN products p ON o.productID = p.productID
JOIN shops s ON o.shopID = s.shopID JOIN shops s ON o.shopID = s.shopID
ORDER BY o.offerID DESC ";
");
if ($filterProductID > 0) {
$offersQuery .= " WHERE o.productID = " . $filterProductID;
}
$offersQuery .= " ORDER BY o.offerID DESC";
// Get existing offers to manage
$offersResult = $conn->query($offersQuery);
$existingOffers = []; $existingOffers = [];
if ($offersResult) { if ($offersResult) {
while ($row = $offersResult->fetch_assoc()) { while ($row = $offersResult->fetch_assoc()) {
@ -170,6 +179,23 @@ include 'header.php';
<h2 class="auth__title">Bestehende Angebote verwalten</h2> <h2 class="auth__title">Bestehende Angebote verwalten</h2>
</header> </header>
<form method="GET" action="offerAdder.php" style="margin-bottom: 1.5rem; display: flex; gap: 1rem; align-items: flex-end;">
<div class="auth__select__wrap" style="flex: 1;">
<label class="auth__select__label" for="filter_product_id">Nach Produkt filtern</label>
<select id="filter_product_id" name="filter_product_id" class="auth__select" onchange="this.form.submit()">
<option value="">-- Alle Produkte anzeigen --</option>
<?php foreach ($products as $product): ?>
<option value="<?php echo htmlspecialchars($product['productID']); ?>" <?php echo ($filterProductID == $product['productID']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($product['model']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php if ($filterProductID > 0): ?>
<a href="offerAdder.php" style="color: var(--primary-color); text-decoration: none; font-weight: 500; font-size: 0.9rem; padding-bottom: 0.75rem;">Filter zurücksetzen</a>
<?php endif; ?>
</form>
<?php if (count($existingOffers) > 0): ?> <?php if (count($existingOffers) > 0): ?>
<div style="overflow-x: auto; margin-top: 1rem;"> <div style="overflow-x: auto; margin-top: 1rem;">
<table style="width: 100%; border-collapse: collapse; min-width: 500px;"> <table style="width: 100%; border-collapse: collapse; min-width: 500px;">
@ -188,7 +214,7 @@ include 'header.php';
<td style="padding: 1rem 0.5rem; vertical-align: middle;"><?php echo htmlspecialchars($offer['shopName']); ?></td> <td style="padding: 1rem 0.5rem; vertical-align: middle;"><?php echo htmlspecialchars($offer['shopName']); ?></td>
<td style="padding: 1rem 0.5rem; vertical-align: middle; font-weight: 600;"><?php echo number_format($offer['price'], 2, ',', '.'); ?></td> <td style="padding: 1rem 0.5rem; vertical-align: middle; font-weight: 600;"><?php echo number_format($offer['price'], 2, ',', '.'); ?></td>
<td style="padding: 1rem 0.5rem; text-align: right; vertical-align: middle;"> <td style="padding: 1rem 0.5rem; text-align: right; vertical-align: middle;">
<form method="POST" action="offerAdder.php" onsubmit="return confirm('Möchtest du dieses Angebot wirklich löschen?');" style="display: inline-block; margin: 0;"> <form method="POST" action="offerAdder.php<?php echo $filterProductID > 0 ? '?filter_product_id=' . $filterProductID : ''; ?>" onsubmit="return confirm('Möchtest du dieses Angebot wirklich löschen?');" style="display: inline-block; margin: 0;">
<input type="hidden" name="action" value="delete_offer"> <input type="hidden" name="action" value="delete_offer">
<input type="hidden" name="offer_id" value="<?php echo $offer['offerID']; ?>"> <input type="hidden" name="offer_id" value="<?php echo $offer['offerID']; ?>">
<button type="submit" style="background: none; border: none; color: #ef4444; cursor: pointer; display: flex; align-items: center; justify-content: flex-end; padding: 0.5rem; border-radius: 4px;" title="Angebot löschen" onmouseover="this.style.backgroundColor='#fee2e2';" onmouseout="this.style.backgroundColor='transparent';"> <button type="submit" style="background: none; border: none; color: #ef4444; cursor: pointer; display: flex; align-items: center; justify-content: flex-end; padding: 0.5rem; border-radius: 4px;" title="Angebot löschen" onmouseover="this.style.backgroundColor='#fee2e2';" onmouseout="this.style.backgroundColor='transparent';">

248
shopAdder.php Normal file
View File

@ -0,0 +1,248 @@
<?php
/**
* @file shopAdder.php
* @brief Shop hinzufügen
*/
require_once __DIR__ . '/lib/bootstrap.php';
// Only ADMIN
if (empty($_SESSION['user_id']) || empty($_SESSION['user_roles']) || !in_array('ADMIN', $_SESSION['user_roles'], true)) {
http_response_code(403);
include 'header.php';
echo '<main class="auth"><section class="auth__grid"><div class="auth__card">';
echo '<h2 class="auth__title">Zugriff verweigert</h2>';
echo '<p>Du hast keine Berechtigung, Shops hinzuzufügen.</p>';
echo '</div></section></main>';
include 'footer.php';
exit;
}
$conn = db_connect();
$message = '';
$messageType = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'add_shop') {
$name = trim($_POST['name']);
$website = trim($_POST['website']);
$shippingTime = trim($_POST['shipping_time']);
$logoPath = null;
// Handle logo upload
if (isset($_FILES['logo']) && $_FILES['logo']['error'] === UPLOAD_ERR_OK) {
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
$fileInfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($fileInfo, $_FILES['logo']['tmp_name']);
finfo_close($fileInfo);
if (in_array($mimeType, $allowedTypes)) {
$uploadDir = __DIR__ . '/assets/images/shopLogo/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
$extension = pathinfo($_FILES['logo']['name'], PATHINFO_EXTENSION);
$fileName = preg_replace('/[^a-zA-Z0-9_-]/', '_', $name) . '_' . time() . '.' . $extension;
$targetFile = $uploadDir . $fileName;
if (move_uploaded_file($_FILES['logo']['tmp_name'], $targetFile)) {
$logoPath = 'assets/images/shopLogo/' . $fileName;
} else {
$message = 'Fehler beim Hochladen des Logos.';
$messageType = 'error';
}
} else {
$message = 'Ungültiges Dateiformat für das Logo. Erlaubt sind JPG, PNG, GIF und WEBP.';
$messageType = 'error';
}
} elseif (isset($_POST['logo_url']) && trim($_POST['logo_url']) !== '') {
$logoPath = trim($_POST['logo_url']);
}
if (empty($message) && $name !== '') {
$stmt = $conn->prepare("INSERT INTO shops (name, website, logoPath, shippingTime) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssss", $name, $website, $logoPath, $shippingTime);
if ($stmt->execute()) {
$message = 'Shop erfolgreich hinzugefügt!';
$messageType = 'success';
} else {
$message = 'Fehler beim Hinzufügen des Shops.';
$messageType = 'error';
}
$stmt->close();
} elseif (empty($message)) {
$message = 'Bitte mindestens den Shop-Namen angeben.';
$messageType = 'error';
}
} elseif ($_POST['action'] === 'delete_shop') {
$shopID = (int)$_POST['shop_id'];
if ($shopID > 0) {
// First check if the shop has associated offers
$checkStmt = $conn->prepare("SELECT COUNT(*) AS offerCount FROM offers WHERE shopID = ?");
$checkStmt->bind_param("i", $shopID);
$checkStmt->execute();
$result = $checkStmt->get_result();
$row = $result->fetch_assoc();
$offerCount = (int)$row['offerCount'];
$checkStmt->close();
if ($offerCount > 0) {
$message = "Der Shop kann nicht gelöscht werden, da er noch $offerCount verknüpfte Angebote hat.";
$messageType = 'error';
} else {
$stmt = $conn->prepare("DELETE FROM shops WHERE shopID = ?");
$stmt->bind_param("i", $shopID);
if ($stmt->execute()) {
$message = 'Shop erfolgreich gelöscht!';
$messageType = 'success';
} else {
$message = 'Fehler beim Löschen des Shops.';
$messageType = 'error';
}
$stmt->close();
}
}
}
}
// Get existing shops to manage
$shopsResult = $conn->query("
SELECT s.shopID, s.name, s.website, s.logoPath, s.shippingTime, COUNT(o.offerID) AS offerCount
FROM shops s
LEFT JOIN offers o ON s.shopID = o.shopID
GROUP BY s.shopID, s.name, s.website, s.logoPath, s.shippingTime
ORDER BY s.name ASC
");
$existingShops = [];
if ($shopsResult) {
while ($row = $shopsResult->fetch_assoc()) {
$existingShops[] = $row;
}
}
include 'header.php';
?>
<main class="auth">
<section class="auth__grid" style="grid-template-columns: 1fr;">
<div class="auth__card">
<header class="auth__header">
<h2 class="auth__title">Shop hinzufügen</h2>
</header>
<?php if ($message): ?>
<p class="<?php echo $messageType === 'success' ? 'auth__alert__sucess' : 'auth__alert__error'; ?>" style="margin-bottom: 1rem;">
<?php echo htmlspecialchars($message); ?>
</p>
<?php endif; ?>
<form method="POST" action="shopAdder.php" class="auth__form" enctype="multipart/form-data">
<input type="hidden" name="action" value="add_shop">
<div>
<label for="name" style="display: block; margin-bottom: 0.5rem; font-weight: 500; color: var(--text-muted);">Shop Name *</label>
<input type="text" id="name" name="name" class="auth__input" required>
</div>
<div style="margin-top: 1rem;">
<label for="website" style="display: block; margin-bottom: 0.5rem; font-weight: 500; color: var(--text-muted);">Website URL</label>
<input type="url" id="website" name="website" class="auth__input" placeholder="https://">
</div>
<div style="margin-top: 1rem;">
<label for="shipping_time" style="display: block; margin-bottom: 0.5rem; font-weight: 500; color: var(--text-muted);">Versanddauer (z.B. "1-3 Werktage")</label>
<input type="text" id="shipping_time" name="shipping_time" class="auth__input">
</div>
<div style="margin-top: 1rem;">
<label style="display: block; margin-bottom: 0.5rem; font-weight: 500; color: var(--text-muted);">Shop Logo</label>
<div style="display: flex; flex-direction: column; gap: 0.8rem; background: var(--bg-alt); padding: 1rem; border-radius: 6px; border: 1px solid var(--border-light);">
<div>
<label for="logo" style="display: block; margin-bottom: 0.3rem; font-size: 0.9em;">Bild hochladen:</label>
<input type="file" id="logo" name="logo" accept="image/*" class="auth__input" style="padding: 0.5rem;">
</div>
<div style="text-align: center; color: var(--text-muted); font-size: 0.9em; margin: 0.2rem 0;">- ODER -</div>
<div>
<label for="logo_url" style="display: block; margin-bottom: 0.3rem; font-size: 0.9em;">Bild-URL:</label>
<input type="url" id="logo_url" name="logo_url" class="auth__input" placeholder="https://...">
</div>
</div>
</div>
<div class="auth__actions" style="margin-top: 1.5rem;">
<button type="submit" class="auth__submit">Shop hinzufügen</button>
</div>
</form>
</div>
<div class="auth__card" style="margin-top: 2rem;">
<header class="auth__header">
<h2 class="auth__title">Bestehende Shops verwalten</h2>
</header>
<?php if (count($existingShops) > 0): ?>
<div style="overflow-x: auto; margin-top: 1rem;">
<table style="width: 100%; border-collapse: collapse; min-width: 600px;">
<thead>
<tr style="border-bottom: 2px solid var(--border-color); text-align: left;">
<th style="padding: 0.75rem 0.5rem; color: var(--text-muted); font-weight: 600;">Logo</th>
<th style="padding: 0.75rem 0.5rem; color: var(--text-muted); font-weight: 600;">Name</th>
<th style="padding: 0.75rem 0.5rem; color: var(--text-muted); font-weight: 600;">Website</th>
<th style="padding: 0.75rem 0.5rem; color: var(--text-muted); font-weight: 600;">Angebote</th>
<th style="padding: 0.75rem 0.5rem; text-align: right; color: var(--text-muted); font-weight: 600;">Aktion</th>
</tr>
</thead>
<tbody>
<?php foreach ($existingShops as $shop): ?>
<tr style="border-bottom: 1px solid var(--border-light);">
<td style="padding: 1rem 0.5rem; vertical-align: middle;">
<?php if ($shop['logoPath']): ?>
<img src="<?php echo htmlspecialchars($shop['logoPath']); ?>" alt="Logo" style="max-height: 40px; max-width: 100px; object-fit: contain;">
<?php else: ?>
<span style="color: var(--text-muted); font-size: 0.8em; font-style: italic;">Kein Logo</span>
<?php endif; ?>
</td>
<td style="padding: 1rem 0.5rem; vertical-align: middle; font-weight: 500;"><?php echo htmlspecialchars($shop['name']); ?></td>
<td style="padding: 1rem 0.5rem; vertical-align: middle;">
<?php if ($shop['website']): ?>
<a href="<?php echo htmlspecialchars($shop['website']); ?>" target="_blank" rel="noopener noreferrer" style="color: var(--primary-color); text-decoration: none; font-size: 0.9em;">Link &nearr;</a>
<?php endif; ?>
</td>
<td style="padding: 1rem 0.5rem; vertical-align: middle;">
<span style="background: var(--bg-alt); padding: 0.2rem 0.6rem; border-radius: 12px; font-size: 0.85em; font-weight: 600;">
<?php echo $shop['offerCount']; ?>
</span>
</td>
<td style="padding: 1rem 0.5rem; text-align: right; vertical-align: middle;">
<?php if ($shop['offerCount'] > 0): ?>
<button disabled style="background: none; border: none; color: #ccc; cursor: not-allowed; display: inline-flex; align-items: center; justify-content: flex-end; padding: 0.5rem;" title="Shop kann nicht gelöscht werden, da er noch Angebote hat">
<svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24">
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6V20a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</button>
<?php else: ?>
<form method="POST" action="shopAdder.php" onsubmit="return confirm('Möchtest du diesen Shop wirklich löschen?');" style="display: inline-block; margin: 0;">
<input type="hidden" name="action" value="delete_shop">
<input type="hidden" name="shop_id" value="<?php echo $shop['shopID']; ?>">
<button type="submit" style="background: none; border: none; color: #ef4444; cursor: pointer; display: inline-flex; align-items: center; justify-content: flex-end; padding: 0.5rem; border-radius: 4px;" title="Shop löschen" onmouseover="this.style.backgroundColor='#fee2e2';" onmouseout="this.style.backgroundColor='transparent';">
<svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24">
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6V20a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</button>
</form>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else: ?>
<p style="margin-top: 1rem; color: var(--text-muted); text-align: center; padding: 2rem 0;">Keine Shops vorhanden.</p>
<?php endif; ?>
</div>
</section>
</main>
<?php include 'footer.php'; ?>