291 lines
14 KiB
PHP
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'; ?>
|