503 lines
18 KiB
PHP
503 lines
18 KiB
PHP
<?php
|
|
// productpage.php
|
|
|
|
require_once __DIR__ . '/lib/bootstrap.php';
|
|
|
|
// 1) DB-Verbindung (einmal)
|
|
$conn = db_connect();
|
|
|
|
$productId = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
|
|
|
if ($productId <= 0) {
|
|
include __DIR__ . '/404.php';
|
|
exit;
|
|
}
|
|
|
|
$checkStmt = $conn->prepare("SELECT productID FROM products WHERE productID = ?");
|
|
$checkStmt->bind_param("i", $productId);
|
|
$checkStmt->execute();
|
|
$checkResult = $checkStmt->get_result();
|
|
if ($checkResult->num_rows === 0) {
|
|
include __DIR__ . '/404.php';
|
|
exit;
|
|
}
|
|
?>
|
|
|
|
|
|
|
|
<?php include 'header.php'; ?>
|
|
|
|
<?php
|
|
$stmt = $conn->prepare("
|
|
SELECT
|
|
a.name,
|
|
a.unit,
|
|
a.dataType,
|
|
pa.valueString,
|
|
pa.valueNumber,
|
|
pa.valueBool,
|
|
p.model,
|
|
p.description,
|
|
p.imagePath
|
|
FROM products p
|
|
|
|
INNER JOIN categoryAttributes ca
|
|
ON p.categoryID = ca.categoryID
|
|
|
|
INNER JOIN attributes a
|
|
ON ca.attributeID = a.attributeID
|
|
|
|
LEFT JOIN productAttributes pa
|
|
ON pa.productID = p.productID
|
|
AND pa.attributeID = a.attributeID
|
|
|
|
WHERE p.productID = ?
|
|
|
|
ORDER BY a.attributeID
|
|
");
|
|
|
|
|
|
$stmt->bind_param("i", $productId);
|
|
$stmt->execute();
|
|
|
|
$result = $stmt->get_result();
|
|
$product = $result->fetch_assoc();
|
|
|
|
$alreadyInWishlist = false;
|
|
|
|
if (isset($_SESSION['user_id'])) {
|
|
|
|
$stmtCheck = mysqli_prepare(
|
|
$conn,
|
|
"SELECT 1 FROM userFavorites
|
|
WHERE userID = ? AND productID = ?
|
|
LIMIT 1"
|
|
);
|
|
|
|
if ($stmtCheck) {
|
|
mysqli_stmt_bind_param(
|
|
$stmtCheck,
|
|
"ii",
|
|
$_SESSION['user_id'],
|
|
$productId
|
|
);
|
|
|
|
mysqli_stmt_execute($stmtCheck);
|
|
mysqli_stmt_store_result($stmtCheck);
|
|
|
|
if (mysqli_stmt_num_rows($stmtCheck) > 0) {
|
|
$alreadyInWishlist = true;
|
|
}
|
|
|
|
mysqli_stmt_close($stmtCheck);
|
|
}
|
|
}
|
|
?>
|
|
|
|
<?php
|
|
if (
|
|
$_SERVER['REQUEST_METHOD'] === 'POST' &&
|
|
isset($_POST['add_wishlist']) &&
|
|
isset($_SESSION['user_id'])
|
|
) {
|
|
|
|
if (!$alreadyInWishlist) {
|
|
|
|
$stmtFav = mysqli_prepare(
|
|
$conn,
|
|
"INSERT INTO userFavorites (productID, userID) VALUES (?, ?)"
|
|
);
|
|
|
|
if ($stmtFav) {
|
|
mysqli_stmt_bind_param(
|
|
$stmtFav,
|
|
'ii',
|
|
$productId,
|
|
$_SESSION['user_id']
|
|
);
|
|
|
|
mysqli_stmt_execute($stmtFav);
|
|
mysqli_stmt_close($stmtFav);
|
|
|
|
$alreadyInWishlist = true;
|
|
}
|
|
}
|
|
}
|
|
?>
|
|
|
|
|
|
<?php
|
|
// SQL korrigiert: SUM statt COUNT für die bedingten Zählungen
|
|
$stmtRevOv = mysqli_prepare($conn,
|
|
"SELECT ROUND(AVG(rating), 1) as avgRating,
|
|
COUNT(*) as reviewCount,
|
|
SUM(rating = 5) as fiveStarCount,
|
|
SUM(rating = 4) as fourStarCount,
|
|
SUM(rating = 3) as threeStarCount,
|
|
SUM(rating = 2) as twoStarCount,
|
|
SUM(rating = 1) as oneStarCount
|
|
FROM reviews WHERE productID = ?");
|
|
|
|
$stmtRevOv->bind_param("i", $productId);
|
|
$stmtRevOv->execute();
|
|
$resultRevOv = $stmtRevOv->get_result();
|
|
|
|
$reviewOverview = $resultRevOv->fetch_assoc();
|
|
|
|
// Falls NULL zurückkommt (keine Bewertungen), auf 0 setzen
|
|
if ($reviewOverview['reviewCount'] === null) {
|
|
$reviewOverview['reviewCount'] = 0;
|
|
}
|
|
?>
|
|
|
|
<div class="product-wrapper">
|
|
<div class="product-left">
|
|
<div class="product-image-box">
|
|
<img src="<?= isset($product['imagePath']) ? $product['imagePath'] : 'assets/images/placeholder.png' ?>"
|
|
alt="<?= htmlspecialchars($product['model'] ?? 'Produktbild') ?>">
|
|
</div>
|
|
|
|
<?php if (isset($_SESSION['user_id'])): ?>
|
|
<?php if ($alreadyInWishlist): ?>
|
|
<div class="auth__actions">
|
|
<input class="auth__submit" type="button" value="Bereits in Wunschliste" disabled>
|
|
</div>
|
|
<?php else: ?>
|
|
<form method="POST">
|
|
<input type="hidden" name="product_id" value="<?= (int)$productId ?>">
|
|
<input type="hidden" name="add_wishlist" value="1">
|
|
<div class="auth__actions">
|
|
<input class="auth__submit" type="submit" value="Zur Wunschliste hinzufügen">
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
<?php else: ?>
|
|
<div class="auth__actions">
|
|
<a href="login.php">
|
|
<input class="auth__submit" type="button" value="Zum Hinzufügen einloggen">
|
|
</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="review-overview-box">
|
|
<?php if ($reviewOverview['reviewCount'] > 0): ?>
|
|
<div class="overview-header">
|
|
<div class="overview-avg">
|
|
<?= htmlspecialchars($reviewOverview['avgRating']) ?> <span class="star filled">★</span>
|
|
</div>
|
|
<div class="overview-count">
|
|
basierend auf <?= htmlspecialchars($reviewOverview['reviewCount']) ?> Bewertungen
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overview-breakdown">
|
|
<?php
|
|
// Ein kleines Array für die saubere Ausgabe mit einer Schleife
|
|
$starCounts = [
|
|
5 => (int)$reviewOverview['fiveStarCount'],
|
|
4 => (int)$reviewOverview['fourStarCount'],
|
|
3 => (int)$reviewOverview['threeStarCount'],
|
|
2 => (int)$reviewOverview['twoStarCount'],
|
|
1 => (int)$reviewOverview['oneStarCount']
|
|
];
|
|
|
|
foreach ($starCounts as $stars => $count):
|
|
// Prozentwert für den Balken berechnen
|
|
$percent = ($reviewOverview['reviewCount'] > 0) ? round(($count / $reviewOverview['reviewCount']) * 100) : 0;
|
|
?>
|
|
<div class="breakdown-row">
|
|
<div class="breakdown-stars"><?= $stars ?> Sterne</div>
|
|
<div class="breakdown-bar-bg">
|
|
<div class="breakdown-bar-fill" style="width: <?= $percent ?>%;"></div>
|
|
</div>
|
|
<div class="breakdown-num"><?= $count ?></div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
|
|
<?php else: ?>
|
|
<div class="overview-empty">
|
|
<p>Noch keine Bewertungen vorhanden.</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="product-right">
|
|
<h1 class="product-title">
|
|
<?= htmlspecialchars($product['model'] ?? 'Produkt') ?>
|
|
</h1>
|
|
|
|
<div class="product-specs">
|
|
<div class="product-desc">
|
|
<?= htmlspecialchars($product['description']) ?>
|
|
</div>
|
|
|
|
<?php
|
|
while ($row = $result->fetch_assoc()) {
|
|
echo "<p><strong>{$row['name']}:</strong> ";
|
|
if (!empty($row['valueString'])) echo $row['valueString'];
|
|
if (!empty($row['valueNumber'])) echo $row['valueNumber'] . " " . $row['unit'];
|
|
if (!is_null($row['valueBool'])) echo $row['valueBool'] ? "Ja" : "Nein";
|
|
echo "</p>";
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php
|
|
// Unterschiedliche DB-Stände: URL-Spalte heißt je nach Schema z.B. productURL oder offerURL.
|
|
// Wir ermitteln die existierende Spalte dynamisch, damit die Seite nicht mit "Unknown column" crasht.
|
|
$urlColumn = '';
|
|
$colCheck = mysqli_query($conn, "SHOW COLUMNS FROM offers LIKE 'productURL'");
|
|
if ($colCheck && mysqli_num_rows($colCheck) > 0) {
|
|
$urlColumn = 'productURL';
|
|
} else {
|
|
$colCheck2 = mysqli_query($conn, "SHOW COLUMNS FROM offers LIKE 'offerURL'");
|
|
if ($colCheck2 && mysqli_num_rows($colCheck2) > 0) {
|
|
$urlColumn = 'offerURL';
|
|
}
|
|
}
|
|
|
|
$urlSelect = $urlColumn !== '' ? ("offers." . $urlColumn . " AS offerURL") : "'' AS offerURL";
|
|
|
|
$stmt = mysqli_prepare($conn,
|
|
"SELECT price, shippingCost, inStock, shops.name, $urlSelect, shops.logoPath, shops.shippingTime
|
|
FROM offers
|
|
INNER JOIN shops ON
|
|
offers.shopID = shops.shopID WHERE offers.productID = ? ORDER BY offers.price ASC");
|
|
|
|
$stmt->bind_param("i", $productId);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
|
|
$shopInfo = [];
|
|
|
|
while ($row = $result->fetch_assoc()) {
|
|
$shopInfo[] = $row;
|
|
}
|
|
|
|
?>
|
|
|
|
<div class="shop-offers">
|
|
|
|
<?php if (!empty($shopInfo)): ?>
|
|
|
|
<?php foreach ($shopInfo as $shop): ?>
|
|
|
|
<div class="shop-line">
|
|
|
|
<div class="shop-left">
|
|
<div class="shop-logo">
|
|
<img src="<?= isset($shop['logoPath']) ? $shop['logoPath'] : 'assets/images/placeholder.png' ?>"
|
|
alt ="Kein Logo gefunden" >
|
|
</div>
|
|
<div class="shop-name">
|
|
<a href="<?= htmlspecialchars($shop['offerURL']) ?>" target="_blank">
|
|
<?= htmlspecialchars($shop['name']) ?>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="shop-middle">
|
|
<div class="shop-shipping">
|
|
Versand: <?= htmlspecialchars($shop['shippingCost']) ?> €      
|
|
Lieferzeit: <?= htmlspecialchars($shop['shippingTime']) ?> Werktage
|
|
</div>
|
|
<div class="shop-stock <?= $shop['inStock'] ? 'in-stock' : 'out-stock' ?>">
|
|
<?= $shop['inStock'] ? "Lagernd" : "Nicht lagernd" ?>
|
|
</div>
|
|
<div class="shop-price">
|
|
Preis: <?= htmlspecialchars($shop['price']) ?> € <br>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php endforeach; ?>
|
|
|
|
<?php else: ?>
|
|
<div class="no-shop">
|
|
<p>Keine Shops bieten dieses Produkt an.</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
|
|
<?php $stmt->close(); ?>
|
|
|
|
|
|
<?php
|
|
// HIER ANGEPASST: profilePicture und createdAt zum SELECT hinzugefügt
|
|
$stmt = mysqli_prepare($conn,
|
|
" SELECT rating, comment, users.displayname, users.profilePicture, reviews.createdAt
|
|
FROM reviews
|
|
INNER JOIN users ON reviews.userID = users.userID
|
|
WHERE productID = ? ORDER BY rating DESC");
|
|
|
|
$stmt->bind_param("i", $productId);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
|
|
$reviews = [];
|
|
|
|
while ($row = $result->fetch_assoc()) {
|
|
$reviews[] = $row;
|
|
}
|
|
?>
|
|
|
|
|
|
<div class="reviews">
|
|
|
|
<h2 class="reviews-title">Bewertungen</h2>
|
|
<div class="reviews-all">
|
|
<?php if (!empty($reviews)): ?>
|
|
|
|
<?php foreach ($reviews as $review): ?>
|
|
|
|
<div class="review-card">
|
|
|
|
<div class="review-header">
|
|
|
|
<div class="review-user-info">
|
|
<img class="review-avatar"
|
|
src="<?= !empty($review['profilePicture']) ? htmlspecialchars($review['profilePicture']) : 'assets/images/placeholder.png' ?>"
|
|
alt="Profilbild von <?= htmlspecialchars($review['displayname']) ?>">
|
|
|
|
<div>
|
|
<div class="review-user">
|
|
<?= htmlspecialchars($review['displayname']) ?>
|
|
</div>
|
|
<?php if (isset($review['createdAt'])): ?>
|
|
<div style="font-size: 0.8rem; color: #94a3b8;">
|
|
<?= date('d.m.Y', strtotime($review['createdAt'])) ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="review-rating">
|
|
<?php for ($i = 1; $i <= 5; $i++): ?>
|
|
<span class="star <?= $i <= $review['rating'] ? 'filled' : '' ?>">★</span>
|
|
<?php endfor; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="review-comment">
|
|
<?= nl2br(htmlspecialchars($review['comment'])) ?>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<?php endforeach; ?>
|
|
|
|
<?php else: ?>
|
|
<div class="no-review">
|
|
<p>Es gibt noch keine Bewertungen.</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="review-add">
|
|
<h2 class="reviews-title">Füge deine Bewertung hinzu!</h2>
|
|
|
|
<?php
|
|
$userHasReviewed = false;
|
|
|
|
// 1. Prüfen, ob der eingeloggte Nutzer schon bewertet hat
|
|
if (isset($_SESSION['user_id'])) {
|
|
$stmtCheckRev = mysqli_prepare($conn, "SELECT 1 FROM reviews WHERE userID = ? AND productID = ? LIMIT 1");
|
|
mysqli_stmt_bind_param($stmtCheckRev, "ii", $_SESSION['user_id'], $productId);
|
|
mysqli_stmt_execute($stmtCheckRev);
|
|
mysqli_stmt_store_result($stmtCheckRev);
|
|
|
|
if (mysqli_stmt_num_rows($stmtCheckRev) > 0) {
|
|
$userHasReviewed = true;
|
|
}
|
|
mysqli_stmt_close($stmtCheckRev);
|
|
}
|
|
|
|
// 2. Bewertung speichern (NUR wenn noch keine existiert!)
|
|
if (
|
|
$_SERVER['REQUEST_METHOD'] === 'POST' &&
|
|
isset($_POST['submit_review']) &&
|
|
isset($_SESSION['user_id']) &&
|
|
!$userHasReviewed
|
|
) {
|
|
$rating = (int)$_POST['rating'];
|
|
$comment = trim($_POST['comment']);
|
|
$userID = $_SESSION['user_id'];
|
|
|
|
if ($rating >= 1 && $rating <= 5 && !empty($comment)) {
|
|
|
|
$stmtInsertRev = mysqli_prepare(
|
|
$conn,
|
|
"INSERT INTO reviews (userID, productID, rating, comment) VALUES (?, ?, ?, ?)"
|
|
);
|
|
|
|
if ($stmtInsertRev) {
|
|
mysqli_stmt_bind_param(
|
|
$stmtInsertRev,
|
|
"iiis",
|
|
$userID,
|
|
$productId,
|
|
$rating,
|
|
$comment
|
|
);
|
|
|
|
mysqli_stmt_execute($stmtInsertRev);
|
|
mysqli_stmt_close($stmtInsertRev);
|
|
|
|
// JS Weiterleitung
|
|
echo "<script>window.location.href = 'productpage.php?id=" . $productId . "';</script>";
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
?>
|
|
|
|
<div class="review-card">
|
|
<?php if (!isset($_SESSION['user_id'])): ?>
|
|
<div class="review-login-prompt">
|
|
<p style="color: #cbd5e1; margin-bottom: 1rem;">Du musst eingeloggt sein, um eine Bewertung abzugeben.</p>
|
|
<a href="login.php">
|
|
<input class="auth__submit" type="button" value="Zum Einloggen">
|
|
</a>
|
|
</div>
|
|
|
|
<?php elseif ($userHasReviewed): ?>
|
|
<div class="review-login-prompt">
|
|
<p class="review-login-msg">Du hast dieses Produkt bereits bewertet. Vielen Dank!</p>
|
|
</div>
|
|
|
|
<?php else: ?>
|
|
<form class="review-input-form" method="post" autocomplete="off">
|
|
<input type="hidden" name="submit_review" value="1">
|
|
|
|
<div class="rating-input">
|
|
<input type="radio" id="star5" name="rating" value="5" required />
|
|
<label for="star5" title="5 Sterne">★</label>
|
|
|
|
<input type="radio" id="star4" name="rating" value="4" />
|
|
<label for="star4" title="4 Sterne">★</label>
|
|
|
|
<input type="radio" id="star3" name="rating" value="3" />
|
|
<label for="star3" title="3 Sterne">★</label>
|
|
|
|
<input type="radio" id="star2" name="rating" value="2" />
|
|
<label for="star2" title="2 Sterne">★</label>
|
|
|
|
<input type="radio" id="star1" name="rating" value="1" />
|
|
<label for="star1" title="1 Stern">★</label>
|
|
</div>
|
|
|
|
<textarea class="review-comment-input" name="comment" rows="4"
|
|
placeholder="Teile deine Meinung mit anderen!" required></textarea>
|
|
|
|
<input class="auth__submit" type="submit" value="Senden">
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php include 'footer.php'; ?>
|