Files
2026-05-22 12:52:44 +00:00

282 lines
12 KiB
PHP

<?php
ob_start();
/**
* Tom's Java Jive - Admin Reviews
*/
$pageTitle = 'Reviews';
require_once __DIR__ . '/includes/header.php';
// Handle actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
$reviewId = $_POST['review_id'] ?? '';
if ($action === 'approve' && $reviewId) {
db()->update('reviews', ['is_approved' => 1], 'review_id = :id', ['id' => $reviewId]);
setFlash('success', 'Review approved');
}
if ($action === 'reject' && $reviewId) {
db()->update('reviews', ['is_approved' => 0], 'review_id = :id', ['id' => $reviewId]);
setFlash('success', 'Review rejected');
}
if ($action === 'update' && $reviewId) {
$rating = max(1, min(5, intval($_POST['rating'] ?? 5)));
$title = trim($_POST['title'] ?? '');
$comment = trim($_POST['comment'] ?? '');
db()->update('reviews', [
'rating' => $rating,
'title' => $title ?: null,
'comment' => $comment ?: null,
], 'review_id = :id', ['id' => $reviewId]);
setFlash('success', 'Review updated');
}
if ($action === 'delete' && $reviewId) {
db()->delete('reviews', 'review_id = :id', ['id' => $reviewId]);
setFlash('success', 'Review deleted');
}
header('Location: /admin/reviews.php');
exit;
}
// Filters
$status = $_GET['status'] ?? '';
$rating = $_GET['rating'] ?? '';
$where = ['1=1'];
$params = [];
if ($status === 'pending') {
$where[] = 'is_approved = 0';
} elseif ($status === 'approved') {
$where[] = 'is_approved = 1';
}
if ($rating) {
$where[] = 'rating = :rating';
$params['rating'] = $rating;
}
$whereClause = implode(' AND ', $where);
$reviews = db()->fetchAll(
"SELECT r.*, p.name as product_name FROM reviews r
LEFT JOIN products p ON r.product_id = p.product_id
WHERE {$whereClause} ORDER BY r.created_at DESC LIMIT 100",
$params
);
// Stats
$totalReviews = db()->count('reviews');
$pendingReviews = db()->count('reviews', 'is_approved = 0');
$avgRating = db()->fetch("SELECT AVG(rating) as avg FROM reviews WHERE is_approved = 1")['avg'] ?? 0;
?>
<div class="page-header">
<h1 class="page-title">Product Reviews</h1>
</div>
<?php if (hasFlash('success')): ?>
<div class="alert alert-success"><i class="fas fa-check-circle"></i> <?= getFlash('success') ?></div>
<?php endif; ?>
<!-- Stats -->
<div class="stats-grid" style="margin-bottom: 1.5rem;">
<div class="stat-card">
<div class="stat-card-icon primary"><i class="fas fa-star"></i></div>
<div>
<div class="stat-card-value"><?= number_format($avgRating, 1) ?></div>
<div class="stat-card-label">Average Rating</div>
</div>
</div>
<div class="stat-card">
<div class="stat-card-icon success"><i class="fas fa-comments"></i></div>
<div>
<div class="stat-card-value"><?= $totalReviews ?></div>
<div class="stat-card-label">Total Reviews</div>
</div>
</div>
<div class="stat-card">
<div class="stat-card-icon <?= $pendingReviews > 0 ? 'warning' : 'success' ?>"><i class="fas fa-clock"></i></div>
<div>
<div class="stat-card-value"><?= $pendingReviews ?></div>
<div class="stat-card-label">Pending Approval</div>
</div>
</div>
</div>
<!-- Filters -->
<div class="admin-card">
<div class="admin-card-body">
<form method="GET" style="display: flex; gap: 1rem; flex-wrap: wrap; align-items: end;">
<div class="form-group mb-0">
<label class="form-label">Status</label>
<select name="status" class="form-select">
<option value="">All</option>
<option value="pending" <?= $status === 'pending' ? 'selected' : '' ?>>Pending</option>
<option value="approved" <?= $status === 'approved' ? 'selected' : '' ?>>Approved</option>
</select>
</div>
<div class="form-group mb-0">
<label class="form-label">Rating</label>
<select name="rating" class="form-select">
<option value="">All Ratings</option>
<?php for ($i = 5; $i >= 1; $i--): ?>
<option value="<?= $i ?>" <?= $rating == $i ? 'selected' : '' ?>><?= $i ?> Star<?= $i > 1 ? 's' : '' ?></option>
<?php endfor; ?>
</select>
</div>
<button type="submit" class="btn btn-secondary"><i class="fas fa-filter"></i> Filter</button>
<?php if ($status || $rating): ?>
<a href="/admin/reviews.php" class="btn btn-secondary">Clear</a>
<?php endif; ?>
</form>
</div>
</div>
<!-- Reviews List -->
<div style="display: flex; flex-direction: column; gap: 1rem;">
<?php if (empty($reviews)): ?>
<div class="admin-card">
<div class="admin-card-body text-center text-muted" style="padding: 3rem;">
No reviews found
</div>
</div>
<?php else: ?>
<?php foreach ($reviews as $review): ?>
<div class="admin-card">
<div class="admin-card-body">
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem;">
<div>
<div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem;">
<strong><?= htmlspecialchars($review['customer_name'] ?? 'Anonymous') ?></strong>
<?php if ($review['is_verified_purchase']): ?>
<span class="badge badge-success">Verified Purchase</span>
<?php endif; ?>
<?php if (!$review['is_approved']): ?>
<span class="badge badge-warning">Pending</span>
<?php endif; ?>
</div>
<div class="text-muted" style="font-size: 0.875rem;">
on <a href="/admin/product-edit.php?id=<?= $review['product_id'] ?>"><?= htmlspecialchars($review['product_name'] ?? 'Unknown Product') ?></a>
• <?= formatDate($review['created_at']) ?>
</div>
</div>
<div style="display: flex; gap: 0.5rem;">
<?php if (!$review['is_approved']): ?>
<form method="POST" style="display: inline;">
<input type="hidden" name="action" value="approve">
<input type="hidden" name="review_id" value="<?= $review['review_id'] ?>">
<button type="submit" class="btn btn-sm btn-success"><i class="fas fa-check"></i> Approve</button>
</form>
<?php else: ?>
<form method="POST" style="display: inline;">
<input type="hidden" name="action" value="reject">
<input type="hidden" name="review_id" value="<?= $review['review_id'] ?>">
<button type="submit" class="btn btn-sm btn-secondary"><i class="fas fa-times"></i> Unapprove</button>
</form>
<?php endif; ?>
<button type="button" class="btn btn-sm btn-secondary" title="Edit"
onclick='openEditReview(<?= json_encode(['review_id' => $review['review_id'], 'rating' => $review['rating'], 'title' => $review['title'], 'comment' => $review['comment']]) ?>)'>
<i class="fas fa-edit"></i>
</button>
<form method="POST" style="display: inline;">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="review_id" value="<?= $review['review_id'] ?>">
<button type="submit" class="btn btn-sm btn-danger" data-confirm="Delete this review?"><i class="fas fa-trash"></i></button>
</form>
</div>
</div>
<div style="margin-bottom: 0.75rem;">
<?php for ($i = 1; $i <= 5; $i++): ?>
<i class="fas fa-star" style="color: <?= $i <= $review['rating'] ? '#F59E0B' : '#E5E7EB' ?>;"></i>
<?php endfor; ?>
</div>
<?php if ($review['title']): ?>
<h4 style="margin-bottom: 0.5rem;"><?= htmlspecialchars($review['title']) ?></h4>
<?php endif; ?>
<p style="margin: 0; color: var(--admin-text);">
<?= nl2br(htmlspecialchars($review['comment'])) ?>
</p>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<!-- Edit Review Modal -->
<div class="modal-overlay" id="editReviewModal">
<div class="modal" style="max-width:560px;width:95vw">
<div class="modal-header">
<h3 class="modal-title">Edit Review</h3>
<button type="button" class="modal-close" onclick="Modal.close('editReviewModal')">&times;</button>
</div>
<form method="POST" id="editReviewForm">
<div class="modal-body">
<input type="hidden" name="action" value="update">
<input type="hidden" name="review_id" id="editReviewId">
<div class="form-group">
<label class="form-label">Rating</label>
<div id="starRating" style="display:flex;gap:.25rem;font-size:1.5rem;cursor:pointer;margin-bottom:.25rem">
<?php for ($s = 1; $s <= 5; $s++): ?>
<i class="fas fa-star" data-star="<?= $s ?>" style="color:#E5E7EB"></i>
<?php endfor; ?>
</div>
<input type="hidden" name="rating" id="editRating" value="5">
</div>
<div class="form-group">
<label class="form-label">Title</label>
<input type="text" name="title" id="editTitle" class="form-input" placeholder="Review title (optional)">
</div>
<div class="form-group mb-0">
<label class="form-label">Comment</label>
<textarea name="comment" id="editComment" class="form-input" rows="5" style="resize:vertical"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="Modal.close('editReviewModal')">Cancel</button>
<button type="submit" class="btn btn-primary"><i class="fas fa-save"></i> Save Changes</button>
</div>
</form>
</div>
</div>
<script>
function openEditReview(review) {
document.getElementById('editReviewId').value = review.review_id;
document.getElementById('editTitle').value = review.title || '';
document.getElementById('editComment').value = review.comment || '';
setStarRating(review.rating || 5);
Modal.open('editReviewModal');
}
function setStarRating(val) {
document.getElementById('editRating').value = val;
document.querySelectorAll('#starRating i').forEach(function(star) {
star.style.color = parseInt(star.dataset.star) <= val ? '#F59E0B' : '#E5E7EB';
});
}
document.querySelectorAll('#starRating i').forEach(function(star) {
star.addEventListener('click', function() { setStarRating(parseInt(this.dataset.star)); });
star.addEventListener('mouseenter', function() {
var val = parseInt(this.dataset.star);
document.querySelectorAll('#starRating i').forEach(function(s) {
s.style.color = parseInt(s.dataset.star) <= val ? '#F59E0B' : '#E5E7EB';
});
});
star.addEventListener('mouseleave', function() {
setStarRating(parseInt(document.getElementById('editRating').value));
});
});
</script>
<?php require_once __DIR__ . '/includes/footer.php'; ?>