38682-vm/admin/ads.php
2026-02-27 01:20:05 +00:00

291 lines
14 KiB
PHP

<?php
require_once __DIR__ . "/../includes/functions.php";
require_once __DIR__ . "/../db/config.php";
require_permission("ads");
require_once __DIR__ . '/../db/config.php';
$pdo = db();
$message = '';
// Handle Add/Edit Promo
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$action = $_POST['action'];
$title = trim($_POST['title']);
$sort_order = (int)$_POST['sort_order'];
$is_active = isset($_POST['is_active']) ? 1 : 0;
$display_layout = $_POST['display_layout'] ?? 'both';
$id = isset($_POST['id']) ? (int)$_POST['id'] : null;
$image_path = null;
if ($id) {
$stmt = $pdo->prepare("SELECT image_path FROM ads_images WHERE id = ?");
$stmt->execute([$id]);
$image_path = $stmt->fetchColumn();
}
if (isset($_FILES['image']) && $_FILES['image']['error'] !== UPLOAD_ERR_NO_FILE) {
if ($_FILES['image']['error'] === UPLOAD_ERR_OK) {
$uploadDir = __DIR__ . '/../assets/images/ads/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
$file_ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION));
if (in_array($file_ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
$new_file_name = uniqid('promo_') . '.' . $file_ext;
if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadDir . $new_file_name)) {
$image_path = 'assets/images/ads/' . $new_file_name;
} else {
$message = '<div class="alert alert-danger">Failed to move uploaded file.</div>';
}
} else {
$message = '<div class="alert alert-danger">Invalid file type.</div>';
}
} else {
$message = '<div class="alert alert-danger">File upload error.</div>';
}
}
if (empty($image_path) && $action === 'add_promo' && empty($message)) {
$message = '<div class="alert alert-danger">Image is required for new advertisements.</div>';
}
if (empty($message)) {
try {
if ($action === 'edit_promo' && $id) {
if (!has_permission('ads')) {
$message = '<div class="alert alert-danger">Access Denied.</div>';
} else {
$stmt = $pdo->prepare("UPDATE ads_images SET title = ?, sort_order = ?, is_active = ?, display_layout = ?, image_path = ? WHERE id = ?");
$stmt->execute([$title, $sort_order, $is_active, $display_layout, $image_path, $id]);
$message = '<div class="alert alert-success">Advertisement updated successfully!</div>';
}
} elseif ($action === 'add_promo') {
if (!has_permission('ads')) {
$message = '<div class="alert alert-danger">Access Denied.</div>';
} else {
$stmt = $pdo->prepare("INSERT INTO ads_images (title, sort_order, is_active, display_layout, image_path) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$title, $sort_order, $is_active, $display_layout, $image_path]);
$message = '<div class="alert alert-success">Advertisement created successfully!</div>';
}
}
} catch (PDOException $e) {
$message = '<div class="alert alert-danger">Database error: ' . $e->getMessage() . '</div>';
}
}
}
if (isset($_GET['delete'])) {
if (!has_permission('ads')) {
$message = '<div class="alert alert-danger">Access Denied.</div>';
} else {
try {
$id = $_GET['delete'];
$stmt = $pdo->prepare("SELECT image_path FROM ads_images WHERE id = ?");
$stmt->execute([$id]);
$promo = $stmt->fetch();
if ($promo) {
$fullPath = __DIR__ . '/../' . $promo['image_path'];
if (file_exists($fullPath) && is_file($fullPath)) unlink($fullPath);
$pdo->prepare("DELETE FROM ads_images WHERE id = ?")->execute([$id]);
}
header("Location: ads.php?deleted=1");
exit;
} catch (PDOException $e) {
$message = '<div class="alert alert-danger">Error deleting advertisement: ' . $e->getMessage() . '</div>';
}
}
}
if (isset($_GET['deleted'])) {
$message = '<div class="alert alert-success">Advertisement deleted successfully!</div>';
}
$query = "SELECT * FROM ads_images ORDER BY sort_order ASC, created_at DESC";
$promos_pagination = paginate_query($pdo, $query);
$promos = $promos_pagination['data'];
include 'includes/header.php';
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h2 class="fw-bold mb-0 text-dark">Advertisement Slider</h2>
<p class="text-muted mb-0">Manage pictures for the public display page.</p>
</div>
<?php if (has_permission('ads')): ?>
<button class="btn btn-primary btn-lg shadow-sm px-4" data-bs-toggle="modal" data-bs-target="#promoModal" onclick="preparePromoAddForm()" style="border-radius: 10px;">
<i class="bi bi-plus-lg me-1"></i> Add Image
</button>
<?php endif; ?>
</div>
<?= $message ?>
<div class="card border-0 shadow-sm rounded-4 overflow-hidden">
<div class="card-body p-0">
<div class="p-3 border-bottom bg-light d-flex justify-content-between align-items-center">
<h6 class="mb-0 fw-bold">Items List</h6>
<?php render_pagination_controls($promos_pagination); ?>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">Order</th>
<th style="width: 150px;">Preview</th>
<th>Title / Caption</th>
<th>Layout</th>
<th>Status</th>
<th class="text-end pe-4">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($promos as $promo): ?>
<tr>
<td class="ps-4 fw-medium text-dark"><?= $promo['sort_order'] ?></td>
<td>
<?php if (!empty($promo['image_path'])): ?>
<img src="../<?= htmlspecialchars($promo['image_path']) ?>"
class="rounded object-fit-cover border shadow-sm"
width="120" height="70">
<?php else: ?>
<div class="bg-light rounded border d-flex align-items-center justify-content-center text-muted" style="width: 120px; height: 70px;">No Image</div>
<?php endif; ?>
</td>
<td>
<div class="fw-bold text-dark"><?= htmlspecialchars($promo['title'] ?: 'No title') ?></div>
</td>
<td>
<?php
$layoutLabel = 'Both';
$layoutClass = 'bg-primary-subtle text-primary';
if (isset($promo['display_layout'])) {
if ($promo['display_layout'] === 'split') {
$layoutLabel = 'Split Only';
$layoutClass = 'bg-info-subtle text-info';
} elseif ($promo['display_layout'] === 'fullscreen') {
$layoutLabel = 'Fullscreen Only';
$layoutClass = 'bg-warning-subtle text-warning';
}
}
?>
<span class="badge <?= $layoutClass ?> px-3"><?= $layoutLabel ?></span>
</td>
<td>
<?php if (isset($promo['is_active']) && $promo['is_active']): ?>
<span class="badge bg-success-subtle text-success px-3">Active</span>
<?php else: ?>
<span class="badge bg-secondary-subtle text-secondary px-3">Inactive</span>
<?php endif; ?>
</td>
<td class="text-end pe-4">
<?php if (has_permission('ads')): ?>
<button type="button" class="btn btn-sm btn-outline-primary rounded-pill px-3 me-1"
data-bs-toggle="modal" data-bs-target="#promoModal"
onclick='preparePromoEditForm(<?= htmlspecialchars(json_encode($promo), ENT_QUOTES, "UTF-8") ?>)'>
<i class="bi bi-pencil me-1"></i> Edit
</button>
<a href="?delete=<?= $promo['id'] ?>" class="btn btn-sm btn-outline-danger rounded-pill px-3" onclick="return confirm('Are you sure?')"><i class="bi bi-trash me-1"></i> Delete</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="p-3 border-top bg-light">
<?php render_pagination_controls($promos_pagination); ?>
</div>
</div>
</div>
<!-- Promo Modal -->
<?php if (has_permission('ads')): ?>
<div class="modal fade" id="promoModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-0 shadow-lg rounded-4">
<div class="modal-header bg-primary text-white border-0">
<h5 class="modal-title fw-bold" id="promoModalTitle">Add New Item</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST" id="promoForm" enctype="multipart/form-data">
<div class="modal-body p-4">
<input type="hidden" name="action" id="promoAction" value="add_promo">
<input type="hidden" name="id" id="promoId">
<div class="mb-4 text-center" id="promoImagePreviewContainer" style="display: none;">
<img src="" id="promoImagePreview" class="img-fluid rounded shadow-sm border" style="max-height: 200px;">
</div>
<div class="mb-3">
<label class="form-label small fw-bold text-muted">TITLE / CAPTION</label>
<input type="text" name="title" id="promoTitle" class="form-control" placeholder="e.g. Special Offer">
</div>
<div class="row g-3 mb-3">
<div class="col-6">
<label class="form-label small fw-bold text-muted">SORT ORDER</label>
<input type="number" name="sort_order" id="promoSortOrder" class="form-control" value="0">
</div>
<div class="col-6">
<label class="form-label small fw-bold text-muted">DISPLAY LAYOUT</label>
<select name="display_layout" id="promoDisplayLayout" class="form-select">
<option value="both">Both Layouts</option>
<option value="split">Split Only</option>
<option value="fullscreen">Fullscreen</option>
</select>
</div>
</div>
<div class="mb-3">
<label class="form-label small fw-bold text-muted">IMAGE FILE</label>
<input type="file" name="image" id="promoImageFile" class="form-control" accept="image/*">
<small class="text-muted mt-1 d-block" id="promoImageHint">Required for new images.</small>
</div>
<div class="mb-0 form-check form-switch">
<input class="form-check-input" type="checkbox" name="is_active" id="promoIsActive" value="1" checked>
<label class="form-check-label fw-medium text-dark" for="promoIsActive">Active (Show in Slider)</label>
</div>
</div>
<div class="modal-footer border-0 p-4 pt-0">
<button type="button" class="btn btn-light rounded-pill px-4" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary rounded-pill px-4 fw-bold shadow-sm">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
<script>
function preparePromoAddForm() {
document.getElementById('promoModalTitle').innerText = 'Add New Item';
document.getElementById('promoAction').value = 'add_promo';
document.getElementById('promoForm').reset();
document.getElementById('promoId').value = '';
document.getElementById('promoImagePreviewContainer').style.display = 'none';
document.getElementById('promoImageHint').innerText = 'Required for new images.';
document.getElementById('promoImageFile').required = true;
}
function preparePromoEditForm(data) {
if (!data) return;
document.getElementById('promoModalTitle').innerText = 'Edit Item';
document.getElementById('promoAction').value = 'edit_promo';
document.getElementById('promoId').value = data.id;
document.getElementById('promoTitle').value = data.title || '';
document.getElementById('promoSortOrder').value = data.sort_order || 0;
document.getElementById('promoDisplayLayout').value = data.display_layout || 'both';
document.getElementById('promoIsActive').checked = data.is_active == 1;
document.getElementById('promoImageHint').innerText = 'Leave empty to keep current image.';
document.getElementById('promoImageFile').required = false;
if (data.image_path) {
const preview = document.getElementById('promoImagePreview');
preview.src = '../' + data.image_path;
document.getElementById('promoImagePreviewContainer').style.display = 'block';
} else {
document.getElementById('promoImagePreviewContainer').style.display = 'none';
}
}
</script>
<?php endif; ?>
<?php include 'includes/footer.php'; ?>