Make blog cards clickable - wrap in anchor tags matching gallery pattern
This commit is contained in:
@@ -1,13 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
$headerStyle = 'light';
|
|
||||||
$rootPath = dirname(dirname(__DIR__));
|
$rootPath = dirname(dirname(__DIR__));
|
||||||
include_once($rootPath . '/header.php');
|
require_once($rootPath . "/src/config/env.php");
|
||||||
|
require_once($rootPath . "/src/config/connection.php");
|
||||||
|
require_once($rootPath . "/src/config/functions.php");
|
||||||
|
require_once($rootPath . "/header.php");
|
||||||
checkAdmin();
|
checkAdmin();
|
||||||
|
checkUserSession();
|
||||||
|
|
||||||
|
$pageTitle = 'Manage Events';
|
||||||
|
$breadcrumbs = [['Home' => 'index']];
|
||||||
|
require_once($rootPath . '/components/banner.php');
|
||||||
|
|
||||||
// Fetch all events
|
// Fetch all events
|
||||||
$events_query = "
|
$events_query = "
|
||||||
SELECT
|
SELECT
|
||||||
event_id, name, type, location, date, published
|
event_id, name, type, location, date, image, published
|
||||||
FROM events
|
FROM events
|
||||||
ORDER BY date DESC
|
ORDER BY date DESC
|
||||||
";
|
";
|
||||||
@@ -22,340 +29,202 @@ if ($result && $result->num_rows > 0) {
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
table {
|
.image {
|
||||||
|
width: 300px;
|
||||||
|
/* Set your desired width */
|
||||||
|
height: 250px;
|
||||||
|
/* Set your desired height */
|
||||||
|
overflow: hidden;
|
||||||
|
/* Hide any overflow */
|
||||||
|
display: block;
|
||||||
|
/* Ensure proper block behavior */
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: separate;
|
/* Image scales to fill the container */
|
||||||
border-spacing: 0;
|
height: 100%;
|
||||||
margin: 10px 0;
|
/* Image scales to fill the container */
|
||||||
}
|
object-fit: cover;
|
||||||
|
/* Fills the container while maintaining aspect ratio */
|
||||||
thead th {
|
object-position: center;
|
||||||
cursor: pointer;
|
/* Aligns the center of the image with the center of the container */
|
||||||
text-align: left;
|
display: block;
|
||||||
padding: 10px;
|
/* Prevents inline whitespace issues */
|
||||||
font-weight: bold;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead th::after {
|
|
||||||
content: '\25B2';
|
|
||||||
/* Up arrow */
|
|
||||||
font-size: 0.8em;
|
|
||||||
position: absolute;
|
|
||||||
right: 10px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead th.asc::after {
|
|
||||||
content: '\25B2';
|
|
||||||
/* Up arrow */
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead th.desc::after {
|
|
||||||
content: '\25BC';
|
|
||||||
/* Down arrow */
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(odd) {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(even) {
|
|
||||||
background-color: rgb(255, 255, 255);
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody td {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(even) td:first-child {
|
|
||||||
border-top-left-radius: 10px;
|
|
||||||
border-bottom-left-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(even) td:last-child {
|
|
||||||
border-top-right-radius: 10px;
|
|
||||||
border-bottom-right-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-input {
|
|
||||||
width: 100%;
|
|
||||||
padding: 10px;
|
|
||||||
font-size: 16px;
|
|
||||||
background-color: rgb(255, 255, 255);
|
|
||||||
border-radius: 25px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 6px 12px;
|
|
||||||
margin: 2px;
|
|
||||||
font-size: 14px;
|
|
||||||
border-radius: 5px;
|
|
||||||
text-decoration: none;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-sm {
|
|
||||||
padding: 4px 8px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: #007bff;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: #0056b3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-success {
|
|
||||||
background-color: #28a745;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-success:hover {
|
|
||||||
background-color: #218838;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-warning {
|
|
||||||
background-color: #ffc107;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-warning:hover {
|
|
||||||
background-color: #e0a800;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-danger {
|
|
||||||
background-color: #dc3545;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-danger:hover {
|
|
||||||
background-color: #c82333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 4px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-success {
|
|
||||||
background-color: #28a745;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-warning {
|
|
||||||
background-color: #ffc107;
|
|
||||||
color: black;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
// Sorting functionality
|
|
||||||
const table = document.querySelector('table');
|
|
||||||
if (table) {
|
|
||||||
const headers = table.querySelectorAll('thead th');
|
|
||||||
const rows = Array.from(table.querySelectorAll('tbody tr'));
|
|
||||||
|
|
||||||
headers.forEach((header, index) => {
|
|
||||||
header.addEventListener('click', () => {
|
|
||||||
const sortedRows = rows.sort((a, b) => {
|
|
||||||
const aText = a.cells[index].textContent.trim().toLowerCase();
|
|
||||||
const bText = b.cells[index].textContent.trim().toLowerCase();
|
|
||||||
|
|
||||||
if (aText < bText) return -1;
|
|
||||||
if (aText > bText) return 1;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (header.classList.contains('asc')) {
|
|
||||||
header.classList.remove('asc');
|
|
||||||
header.classList.add('desc');
|
|
||||||
sortedRows.reverse();
|
|
||||||
} else {
|
|
||||||
headers.forEach(h => h.classList.remove('asc', 'desc'));
|
|
||||||
header.classList.add('asc');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tbody = table.querySelector('tbody');
|
|
||||||
tbody.innerHTML = '';
|
|
||||||
sortedRows.forEach(row => tbody.appendChild(row));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Filter functionality
|
|
||||||
const filterInput = document.querySelector('.filter-input');
|
const filterInput = document.querySelector('.filter-input');
|
||||||
if (filterInput) {
|
const cards = document.querySelectorAll('.destination-item');
|
||||||
filterInput.addEventListener('input', function() {
|
|
||||||
|
if (cards.length === 0 && filterInput) {
|
||||||
|
filterInput.style.display = "none";
|
||||||
|
} else if (filterInput) {
|
||||||
|
filterInput.addEventListener("input", function() {
|
||||||
const filterValue = filterInput.value.trim().toLowerCase();
|
const filterValue = filterInput.value.trim().toLowerCase();
|
||||||
rows.forEach(row => {
|
cards.forEach(card => {
|
||||||
const rowText = row.textContent.trim().toLowerCase();
|
const cardText = card.textContent.trim().toLowerCase();
|
||||||
row.style.display = rowText.includes(filterValue) ? '' : 'none';
|
card.style.display = cardText.includes(filterValue) ? "" : "none";
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Publish/Unpublish toggle
|
|
||||||
$('.toggle-publish').on('click', function() {
|
|
||||||
var eventId = $(this).data('event-id');
|
|
||||||
var button = $(this);
|
|
||||||
var row = button.closest('tr');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: 'toggle_event_published',
|
|
||||||
type: 'POST',
|
|
||||||
data: {
|
|
||||||
event_id: eventId
|
|
||||||
},
|
|
||||||
dataType: 'json',
|
|
||||||
complete: function(xhr, status) {
|
|
||||||
// Handle all response codes
|
|
||||||
try {
|
|
||||||
var response = JSON.parse(xhr.responseText);
|
|
||||||
|
|
||||||
if (response.status === 'success') {
|
|
||||||
if (response.published == 1) {
|
|
||||||
button.removeClass('btn-success').addClass('btn-warning');
|
|
||||||
button.find('i').removeClass('fa-eye').addClass('fa-eye-slash');
|
|
||||||
button.attr('title', 'Unpublish');
|
|
||||||
row.find('td:nth-child(5)').html('<span class="badge bg-success">Published</span>');
|
|
||||||
} else {
|
|
||||||
button.removeClass('btn-warning').addClass('btn-success');
|
|
||||||
button.find('i').removeClass('fa-eye-slash').addClass('fa-eye');
|
|
||||||
button.attr('title', 'Publish');
|
|
||||||
row.find('td:nth-child(5)').html('<span class="badge bg-warning">Draft</span>');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert('Error: ' + response.message);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
alert('Error updating event status. Response: ' + xhr.responseText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete event
|
|
||||||
$('.delete-event').on('click', function() {
|
|
||||||
if (!confirm('Are you sure you want to delete this event? This action cannot be undone.')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var eventId = $(this).data('event-id');
|
|
||||||
var button = $(this);
|
|
||||||
var row = button.closest('tr');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: 'delete_event',
|
|
||||||
type: 'POST',
|
|
||||||
data: {
|
|
||||||
event_id: eventId
|
|
||||||
},
|
|
||||||
dataType: 'json',
|
|
||||||
success: function(response) {
|
|
||||||
if (response.status === 'success') {
|
|
||||||
row.fadeOut(300, function() {
|
|
||||||
$(this).remove();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
alert('Error: ' + response.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
alert('Error deleting event');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$pageTitle = 'Manage Events';
|
$pageTitle = 'Manage Events';
|
||||||
$breadcrumbs = [['Home' => 'index'], [$pageTitle => '']];
|
$breadcrumbs = [['Home' => 'index']];
|
||||||
require_once($rootPath . '/components/banner.php');
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$pageTitle = 'Manage Events';
|
|
||||||
$breadcrumbs = [['Home' => 'index'], [$pageTitle => '']];
|
|
||||||
require_once($rootPath . '/components/banner.php');
|
require_once($rootPath . '/components/banner.php');
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<!-- Events Management Area start -->
|
<!-- Events Management Area start -->
|
||||||
<section class="events-management-area py-100 rel z-1">
|
<section class="blog-list-page py-100 rel z-1">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-30">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<a href="manage_events" class="theme-btn style-two">+ Create New Event</a>
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px;">
|
||||||
</div>
|
<h2 style="margin: 0;">Manage Events</h2>
|
||||||
</div>
|
<a href="manage_events" class="theme-btn create-album-btn">
|
||||||
|
<i class="far fa-plus"></i> New Event
|
||||||
<?php
|
|
||||||
if (!empty($events)) {
|
|
||||||
echo '<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="form-group mb-20">
|
|
||||||
<input type="text" class="filter-input" placeholder="Search events...">
|
|
||||||
</div>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Event Name</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Location</th>
|
|
||||||
<th>Date</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>';
|
|
||||||
foreach ($events as $event) {
|
|
||||||
$publishButtonText = $event['published'] == 1 ? 'Unpublish' : 'Publish';
|
|
||||||
$publishButtonClass = $event['published'] == 1 ? 'btn-warning' : 'btn-success';
|
|
||||||
echo '<tr>
|
|
||||||
<td><strong>' . htmlspecialchars($event['name']) . '</strong></td>
|
|
||||||
<td>' . htmlspecialchars($event['type']) . '</td>
|
|
||||||
<td>' . htmlspecialchars($event['location']) . '</td>
|
|
||||||
<td>' . convertDate($event['date']) . '</td>
|
|
||||||
<td>' . ($event['published'] == 1 ? '<span class="badge bg-success">Published</span>' : '<span class="badge bg-warning">Draft</span>') . '</td>
|
|
||||||
<td>
|
|
||||||
<a href="manage_events?event_id=' . $event['event_id'] . '" class="btn btn-sm btn-primary" title="Edit">
|
|
||||||
<i class="far fa-edit"></i>
|
|
||||||
</a>
|
</a>
|
||||||
<button class="btn btn-sm ' . $publishButtonClass . ' toggle-publish" data-event-id="' . $event['event_id'] . '" title="' . $publishButtonText . '">
|
</div>
|
||||||
<i class="far fa-' . ($event['published'] == 1 ? 'eye-slash' : 'eye') . '"></i>
|
<?php if (isset($_SESSION['message'])): ?>
|
||||||
</button>
|
<div class="alert alert-warning message-box">
|
||||||
<button class="btn btn-sm btn-danger delete-event" data-event-id="' . $event['event_id'] . '" title="Delete">
|
<?php echo $_SESSION['message']; ?>
|
||||||
<i class="far fa-trash"></i>
|
<span class="close-btn" onclick="this.parentElement.style.display='none'">×</span>
|
||||||
</button>
|
</div>
|
||||||
</td>
|
<?php unset($_SESSION['message']);
|
||||||
</tr>';
|
endif;
|
||||||
|
|
||||||
|
if (count($events) > 0) {
|
||||||
|
echo '<input type="text" class="filter-input" placeholder="Filter events...">';
|
||||||
|
echo '<div class="events-container" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">';
|
||||||
|
|
||||||
|
foreach ($events as $event) {
|
||||||
|
$eventImagePath = $event['image'] ? htmlspecialchars($event['image']) : 'assets/images/placeholder.jpg';
|
||||||
|
$publishStatusBadge = $event['published'] == 1 ? 'PUBLISHED' : 'DRAFT';
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<div class="destination-item style-three bgc-lighter booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<div class="image" style="width:300px;height:250px;">
|
||||||
|
<img src="' . $eventImagePath . '" alt="' . htmlspecialchars($event['name']) . '">
|
||||||
|
</div>
|
||||||
|
<div class="content" style="width:100%;">
|
||||||
|
<div class="destination-header d-flex align-items-start gap-3">
|
||||||
|
<div>
|
||||||
|
<span class="badge bg-dark mb-1">' . strtoupper($publishStatusBadge) . '</span>
|
||||||
|
<h5 class="mb-0">' . htmlspecialchars($event['name']) . '</h5>
|
||||||
|
<small class="text-muted">📍 ' . htmlspecialchars($event['location']) . '</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p style="margin: 10px 0;">
|
||||||
|
<strong>Type:</strong> ' . htmlspecialchars($event['type']) . '<br>
|
||||||
|
<strong>Date:</strong> ' . convertDate($event['date']) . '
|
||||||
|
</p>
|
||||||
|
<div class="destination-footer">
|
||||||
|
<div class="btn-group" style="display:flex; justify-content:flex-end; gap:10px;">
|
||||||
|
<a href="manage_events?event_id=' . $event['event_id'] . '" data-bs-toggle="tooltip" data-bs-placement="top" title="Edit"><span class="material-icons">edit</span></a>
|
||||||
|
<button type="button" class="toggle-publish" data-event-id="' . $event['event_id'] . '" data-bs-toggle="tooltip" data-bs-placement="top" title="' . ($event['published'] == 1 ? 'Unpublish' : 'Publish') . '" style="background:none; border:none; cursor:pointer; color:inherit;"><span class="material-icons">' . ($event['published'] == 1 ? 'cloud_off' : 'cloud_upload') . '</span></button>
|
||||||
|
<button type="button" class="delete-event" data-event-id="' . $event['event_id'] . '" data-bs-toggle="tooltip" data-bs-placement="top" title="Delete" style="background:none; border:none; cursor:pointer; color:inherit;"><span class="material-icons">delete</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
';
|
||||||
}
|
}
|
||||||
echo '</tbody></table>';
|
|
||||||
echo '</div>';
|
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
} else {
|
} else {
|
||||||
echo '<p>No events found. <a href="manage_events">Create one</a></p>';
|
echo '<div class="no-events">
|
||||||
|
<p>No events found. <a href="manage_events">Create one</a></p>
|
||||||
|
</div>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<!-- Events Management Area end -->
|
<!-- Events Management Area end -->
|
||||||
|
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||||
|
<script>
|
||||||
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||||
|
tooltipTriggerList.forEach(el => new bootstrap.Tooltip(el));
|
||||||
|
|
||||||
|
// Handle publish/unpublish button clicks
|
||||||
|
document.querySelectorAll('.toggle-publish').forEach(btn => {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
const eventId = this.dataset.eventId;
|
||||||
|
const currentIcon = this.querySelector('.material-icons').textContent;
|
||||||
|
const isPublished = currentIcon === 'cloud_off';
|
||||||
|
const action = isPublished ? 'Unpublish' : 'Publish';
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('event_id', eventId);
|
||||||
|
|
||||||
|
fetch('toggle_event_published', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.status === 'success') {
|
||||||
|
alert(action + ' successful!');
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
alert(action + ' failed: ' + data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Error:', err);
|
||||||
|
alert(action + ' failed due to network error.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle delete button clicks
|
||||||
|
document.querySelectorAll('.delete-event').forEach(btn => {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
if (!confirm('Are you sure you want to delete this event? This action cannot be undone.')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventId = this.dataset.eventId;
|
||||||
|
const card = this.closest('.destination-item');
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('event_id', eventId);
|
||||||
|
|
||||||
|
fetch('delete_event', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.status === 'success') {
|
||||||
|
card.style.animation = 'fadeOut 0.3s ease-out';
|
||||||
|
setTimeout(() => {
|
||||||
|
card.remove();
|
||||||
|
if (document.querySelectorAll('.destination-item').length === 0) {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
} else {
|
||||||
|
alert('Error: ' + data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Error:', err);
|
||||||
|
alert('Delete failed due to network error.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
$headerStyle = 'light';
|
|
||||||
$rootPath = dirname(dirname(__DIR__));
|
$rootPath = dirname(dirname(__DIR__));
|
||||||
include_once($rootPath . '/header.php');
|
require_once($rootPath . "/src/config/env.php");
|
||||||
|
require_once($rootPath . "/src/config/connection.php");
|
||||||
|
require_once($rootPath . "/src/config/functions.php");
|
||||||
|
require_once($rootPath . "/header.php");
|
||||||
checkAdmin();
|
checkAdmin();
|
||||||
|
checkUserSession();
|
||||||
|
|
||||||
|
$pageTitle = 'Manage Trips';
|
||||||
|
$breadcrumbs = [['Home' => 'index']];
|
||||||
|
require_once($rootPath . '/components/banner.php');
|
||||||
|
|
||||||
// Fetch all trips with booking status
|
// Fetch all trips with booking status
|
||||||
$trips_query = "
|
$trips_query = "
|
||||||
SELECT
|
SELECT
|
||||||
trip_id, trip_name, location, start_date, end_date,
|
trip_id, trip_name, location, start_date, end_date,
|
||||||
vehicle_capacity, places_booked, cost_members, published
|
vehicle_capacity, places_booked, cost_members, cost_nonmembers,
|
||||||
|
cost_pensioner_member, cost_pensioner, published
|
||||||
FROM trips
|
FROM trips
|
||||||
ORDER BY start_date DESC
|
ORDER BY start_date DESC
|
||||||
";
|
";
|
||||||
@@ -23,295 +31,210 @@ if ($result && $result->num_rows > 0) {
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
table {
|
.image {
|
||||||
|
width: 200px;
|
||||||
|
/* Set your desired width */
|
||||||
|
height: 200px;
|
||||||
|
/* Set your desired height */
|
||||||
|
overflow: hidden;
|
||||||
|
/* Hide any overflow */
|
||||||
|
display: block;
|
||||||
|
/* Ensure proper block behavior */
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: separate;
|
/* Image scales to fill the container */
|
||||||
border-spacing: 0;
|
height: 100%;
|
||||||
margin: 10px 0;
|
/* Image scales to fill the container */
|
||||||
}
|
object-fit: cover;
|
||||||
|
/* Fills the container while maintaining aspect ratio */
|
||||||
thead th {
|
object-position: center;
|
||||||
cursor: pointer;
|
/* Aligns the center of the image with the center of the container */
|
||||||
text-align: left;
|
display: block;
|
||||||
padding: 10px;
|
/* Prevents inline whitespace issues */
|
||||||
font-weight: bold;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead th::after {
|
|
||||||
content: '\25B2';
|
|
||||||
/* Up arrow */
|
|
||||||
font-size: 0.8em;
|
|
||||||
position: absolute;
|
|
||||||
right: 10px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead th.asc::after {
|
|
||||||
content: '\25B2';
|
|
||||||
/* Up arrow */
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead th.desc::after {
|
|
||||||
content: '\25BC';
|
|
||||||
/* Down arrow */
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(odd) {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(even) {
|
|
||||||
background-color: rgb(255, 255, 255);
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody td {
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(even) td:first-child {
|
|
||||||
border-top-left-radius: 10px;
|
|
||||||
border-bottom-left-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(even) td:last-child {
|
|
||||||
border-top-right-radius: 10px;
|
|
||||||
border-bottom-right-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-input {
|
|
||||||
width: 100%;
|
|
||||||
padding: 5px;
|
|
||||||
font-size: 16px;
|
|
||||||
background-color: rgb(255, 255, 255);
|
|
||||||
border-radius: 25px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.trips-section {
|
|
||||||
color: #484848;
|
|
||||||
background: #f9f9f7;
|
|
||||||
border: 1px solid #d8d8d8;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin-top: 15px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
const tables = document.querySelectorAll("table");
|
const filterInput = document.querySelector('.filter-input');
|
||||||
tables.forEach((table) => {
|
const cards = document.querySelectorAll('.destination-item');
|
||||||
const headers = table.querySelectorAll("thead th");
|
|
||||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
|
||||||
const filterInput = table.previousElementSibling;
|
|
||||||
|
|
||||||
headers.forEach((header, index) => {
|
if (cards.length === 0 && filterInput) {
|
||||||
header.addEventListener("click", () => {
|
|
||||||
const sortedRows = rows.sort((a, b) => {
|
|
||||||
const aText = a.cells[index].textContent.trim().toLowerCase();
|
|
||||||
const bText = b.cells[index].textContent.trim().toLowerCase();
|
|
||||||
|
|
||||||
if (aText < bText) return -1;
|
|
||||||
if (aText > bText) return 1;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (header.classList.contains("asc")) {
|
|
||||||
header.classList.remove("asc");
|
|
||||||
header.classList.add("desc");
|
|
||||||
sortedRows.reverse();
|
|
||||||
} else {
|
|
||||||
headers.forEach(h => h.classList.remove("asc", "desc"));
|
|
||||||
header.classList.add("asc");
|
|
||||||
}
|
|
||||||
|
|
||||||
const tbody = table.querySelector("tbody");
|
|
||||||
tbody.innerHTML = "";
|
|
||||||
sortedRows.forEach(row => tbody.appendChild(row));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (rows.length === 0) {
|
|
||||||
filterInput.style.display = "none";
|
filterInput.style.display = "none";
|
||||||
} else {
|
} else if (filterInput) {
|
||||||
filterInput.addEventListener("input", function() {
|
filterInput.addEventListener("input", function() {
|
||||||
const filterValue = filterInput.value.trim().toLowerCase();
|
const filterValue = filterInput.value.trim().toLowerCase();
|
||||||
rows.forEach(row => {
|
cards.forEach(card => {
|
||||||
const rowText = row.textContent.trim().toLowerCase();
|
const cardText = card.textContent.trim().toLowerCase();
|
||||||
row.style.display = rowText.includes(filterValue) ? "" : "none";
|
card.style.display = cardText.includes(filterValue) ? "" : "none";
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$bannerFolder = 'assets/images/banners/';
|
$bannerFolder = 'assets/images/banners/';
|
||||||
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
||||||
|
|
||||||
$randomBanner = 'assets/images/base4/camping.jpg'; // default fallback
|
|
||||||
if (!empty($bannerImages)) {
|
|
||||||
$randomBanner = $bannerImages[array_rand($bannerImages)];
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
<section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
|
|
||||||
<div class="banner-overlay"></div>
|
|
||||||
<div class="container">
|
|
||||||
<div class="banner-inner text-white mb-50">
|
|
||||||
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">Manage Trips</h2>
|
|
||||||
<nav aria-label="breadcrumb">
|
|
||||||
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50">
|
|
||||||
<li class="breadcrumb-item"><a href="index">Home</a></li>
|
|
||||||
<li class="breadcrumb-item active">Manage Trips</li>
|
|
||||||
</ol>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Trips Management Area start -->
|
<!-- Trips Management Area start -->
|
||||||
<section class="tour-list-page py-100 rel z-1">
|
<section class="blog-list-page py-100 rel z-1">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div style="margin-bottom: 20px;">
|
<div class="row">
|
||||||
<a href="manage_trips" class="theme-btn">
|
<div class="col-lg-12">
|
||||||
<i class="far fa-plus"></i> Create New Trip
|
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px;">
|
||||||
|
<h2 style="margin: 0;">Manage Trips</h2>
|
||||||
|
<a href="manage_trips" class="theme-btn create-album-btn">
|
||||||
|
<i class="far fa-plus"></i> New Event
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<?php if (isset($_SESSION['message'])): ?>
|
||||||
<?php
|
<div class="alert alert-warning message-box">
|
||||||
|
<?php echo $_SESSION['message']; ?>
|
||||||
|
<span class="close-btn" onclick="this.parentElement.style.display='none'">×</span>
|
||||||
|
</div>
|
||||||
|
<?php unset($_SESSION['message']);
|
||||||
|
endif;
|
||||||
if (count($trips) > 0) {
|
if (count($trips) > 0) {
|
||||||
echo '<input type="text" class="filter-input" placeholder="Filter trips...">';
|
echo '<input type="text" class="filter-input" placeholder="Filter trips...">';
|
||||||
echo '<div class="trips-section" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">';
|
echo '<div class="trips-container" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">';
|
||||||
echo '<div style="padding:10px;">';
|
|
||||||
echo '<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Trip Name</th>
|
|
||||||
<th>Location</th>
|
|
||||||
<th>Start Date</th>
|
|
||||||
<th>End Date</th>
|
|
||||||
<th>Capacity</th>
|
|
||||||
<th>Booked</th>
|
|
||||||
<th>Cost (Member)</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>';
|
|
||||||
foreach ($trips as $trip) {
|
foreach ($trips as $trip) {
|
||||||
$publishButtonText = $trip['published'] == 1 ? 'Unpublish' : 'Publish';
|
$available = $trip['vehicle_capacity'] - $trip['places_booked'];
|
||||||
$publishButtonClass = $trip['published'] == 1 ? 'btn-warning' : 'btn-success';
|
$publishStatus = $trip['published'] == 1 ? 'published' : 'draft';
|
||||||
echo '<tr>
|
$publishStatusBadge = $trip['published'] == 1 ? 'PUBLISHED' : 'DRAFT';
|
||||||
<td><strong>' . htmlspecialchars($trip['trip_name']) . '</strong></td>
|
|
||||||
<td>' . htmlspecialchars($trip['location']) . '</td>
|
// Get trip image - look for assets/images/trips/$trip_id_{number}.jpg
|
||||||
<td>' . date('M d, Y', strtotime($trip['start_date'])) . '</td>
|
$tripImagePath = '';
|
||||||
<td>' . date('M d, Y', strtotime($trip['end_date'])) . '</td>
|
$tripImagesGlob = glob($rootPath . '/assets/images/trips/' . $trip['trip_id'] . '_*.jpg');
|
||||||
<td>' . $trip['vehicle_capacity'] . '</td>
|
if (!empty($tripImagesGlob)) {
|
||||||
<td><span class="badge bg-info">' . $trip['places_booked'] . ' / ' . $trip['vehicle_capacity'] . '</span></td>
|
$tripImagePath = str_replace($rootPath, '', $tripImagesGlob[0]);
|
||||||
<td>R ' . number_format($trip['cost_members'], 2) . '</td>
|
} else {
|
||||||
<td>' . ($trip['published'] == 1 ? '<span class="badge bg-success">Published</span>' : '<span class="badge bg-warning">Draft</span>') . '</td>
|
// Fallback to placeholder icon if no image found
|
||||||
<td>
|
$tripImagePath = 'assets/images/placeholder.jpg';
|
||||||
<a href="manage_trips?trip_id=' . $trip['trip_id'] . '" class="btn btn-sm btn-primary" title="Edit">
|
|
||||||
<i class="far fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<button class="btn btn-sm ' . $publishButtonClass . ' toggle-publish" data-trip-id="' . $trip['trip_id'] . '" title="' . $publishButtonText . '">
|
|
||||||
<i class="far fa-' . ($trip['published'] == 1 ? 'eye-slash' : 'eye') . '"></i>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-sm btn-danger delete-trip" data-trip-id="' . $trip['trip_id'] . '" title="Delete">
|
|
||||||
<i class="far fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>';
|
|
||||||
}
|
}
|
||||||
echo '</tbody></table>';
|
|
||||||
echo '</div>';
|
echo '
|
||||||
|
<div class="destination-item style-three bgc-lighter booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<div class="image" style="width:300px;height:250px;">
|
||||||
|
<img src="' . htmlspecialchars($tripImagePath) . '" alt="' . htmlspecialchars($trip['trip_name']) . '">
|
||||||
|
</div>
|
||||||
|
<div class="content" style="width:100%;">
|
||||||
|
<div class="destination-header d-flex align-items-start gap-3">
|
||||||
|
<div>
|
||||||
|
<span class="badge bg-dark mb-1">' . strtoupper($publishStatusBadge) . '</span>
|
||||||
|
<h5 class="mb-0">' . htmlspecialchars($trip['trip_name']) . '</h5>
|
||||||
|
<small class="text-muted">📍 ' . htmlspecialchars($trip['location']) . '</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p style="margin: 10px 0;">
|
||||||
|
<strong>Dates:</strong> ' . date('M d', strtotime($trip['start_date'])) . ' - ' . date('M d, Y', strtotime($trip['end_date'])) . '<br>
|
||||||
|
<strong>Capacity:</strong> ' . $trip['places_booked'] . ' / ' . $trip['vehicle_capacity'] . '<br>
|
||||||
|
<strong>Costs:</strong> Members: R ' . number_format($trip['cost_members'], 2) . ' | Non-Members: R ' . number_format($trip['cost_nonmembers'], 2) . ' | Pensioner Members: R ' . number_format($trip['cost_pensioner_member'], 2) . ' | Pensioners: R ' . number_format($trip['cost_pensioner'], 2) . '
|
||||||
|
</p>
|
||||||
|
<div class="destination-footer">
|
||||||
|
<div class="btn-group" style="display:flex; justify-content:flex-end; gap:10px;">
|
||||||
|
<a href="manage_trips?trip_id=' . $trip['trip_id'] . '" data-bs-toggle="tooltip" data-bs-placement="top" title="Edit"><span class="material-icons">edit</span></a>
|
||||||
|
<button type="button" class="toggle-publish" data-trip-id="' . $trip['trip_id'] . '" data-bs-toggle="tooltip" data-bs-placement="top" title="' . ($trip['published'] == 1 ? 'Unpublish' : 'Publish') . '" style="background:none; border:none; cursor:pointer; color:inherit;"><span class="material-icons">' . ($trip['published'] == 1 ? 'cloud_off' : 'cloud_upload') . '</span></button>
|
||||||
|
<button type="button" class="delete-trip" data-trip-id="' . $trip['trip_id'] . '" data-bs-toggle="tooltip" data-bs-placement="top" title="Delete" style="background:none; border:none; cursor:pointer; color:inherit;"><span class="material-icons">delete</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
';
|
||||||
|
}
|
||||||
|
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
} else {
|
} else {
|
||||||
echo '<p>No trips found. <a href="manage_trips">Create one</a></p>';
|
echo '<div class="no-trips">
|
||||||
|
<p>No trips found. <a href="manage_trips">Create one</a></p>
|
||||||
|
</div>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<!-- Trips Management Area end -->
|
<!-- Trips Management Area end -->
|
||||||
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||||
$('.toggle-publish').on('click', function() {
|
tooltipTriggerList.forEach(el => new bootstrap.Tooltip(el));
|
||||||
var tripId = $(this).data('trip-id');
|
|
||||||
var button = $(this);
|
|
||||||
var row = button.closest('tr');
|
|
||||||
|
|
||||||
$.ajax({
|
// Handle publish/unpublish button clicks
|
||||||
url: 'toggle_trip_published',
|
document.querySelectorAll('.toggle-publish').forEach(btn => {
|
||||||
type: 'POST',
|
btn.addEventListener('click', function() {
|
||||||
data: {
|
const tripId = this.dataset.tripId;
|
||||||
trip_id: tripId
|
const currentIcon = this.querySelector('.material-icons').textContent;
|
||||||
},
|
const isPublished = currentIcon === 'cloud_off';
|
||||||
dataType: 'json',
|
const action = isPublished ? 'Unpublish' : 'Publish';
|
||||||
success: function(response) {
|
|
||||||
if (response.status === 'success') {
|
const formData = new FormData();
|
||||||
// Update button appearance
|
formData.append('trip_id', tripId);
|
||||||
if (response.published == 1) {
|
|
||||||
button.removeClass('btn-success').addClass('btn-warning');
|
fetch('toggle_trip_published', {
|
||||||
button.find('i').removeClass('fa-eye').addClass('fa-eye-slash');
|
method: 'POST',
|
||||||
button.attr('title', 'Unpublish');
|
body: formData
|
||||||
// Update status badge
|
})
|
||||||
row.find('td:nth-child(8)').html('<span class="badge bg-success">Published</span>');
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.status === 'success') {
|
||||||
|
alert(action + ' successful!');
|
||||||
|
location.reload();
|
||||||
} else {
|
} else {
|
||||||
button.removeClass('btn-warning').addClass('btn-success');
|
alert(action + ' failed: ' + data.message);
|
||||||
button.find('i').removeClass('fa-eye-slash').addClass('fa-eye');
|
|
||||||
button.attr('title', 'Publish');
|
|
||||||
// Update status badge
|
|
||||||
row.find('td:nth-child(8)').html('<span class="badge bg-warning">Draft</span>');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert('Error: ' + response.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
alert('Error updating trip status');
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Error:', err);
|
||||||
|
alert(action + ' failed due to network error.');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.delete-trip').on('click', function() {
|
// Handle delete button clicks
|
||||||
|
document.querySelectorAll('.delete-trip').forEach(btn => {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
if (!confirm('Are you sure you want to delete this trip? This action cannot be undone.')) {
|
if (!confirm('Are you sure you want to delete this trip? This action cannot be undone.')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tripId = $(this).data('trip-id');
|
const tripId = this.dataset.tripId;
|
||||||
var button = $(this);
|
const card = this.closest('.destination-item');
|
||||||
var row = button.closest('tr');
|
|
||||||
|
|
||||||
$.ajax({
|
const formData = new FormData();
|
||||||
url: 'delete_trip',
|
formData.append('trip_id', tripId);
|
||||||
type: 'POST',
|
|
||||||
data: {
|
fetch('delete_trip', {
|
||||||
trip_id: tripId
|
method: 'POST',
|
||||||
},
|
body: formData
|
||||||
dataType: 'json',
|
})
|
||||||
success: function(response) {
|
.then(response => response.json())
|
||||||
if (response.status === 'success') {
|
.then(data => {
|
||||||
row.fadeOut(function() {
|
if (data.status === 'success') {
|
||||||
$(this).remove();
|
card.style.animation = 'fadeOut 0.3s ease-out';
|
||||||
if ($('table tbody tr').length === 0) {
|
setTimeout(() => {
|
||||||
|
card.remove();
|
||||||
|
if (document.querySelectorAll('.destination-item').length === 0) {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
});
|
}, 300);
|
||||||
} else {
|
} else {
|
||||||
alert('Error: ' + response.message);
|
alert('Error: ' + data.message);
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
alert('Error deleting trip');
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Error:', err);
|
||||||
|
alert('Delete failed due to network error.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ include_once($rootPath . '/header.php');
|
|||||||
|
|
||||||
// Output the HTML structure with dynamic data
|
// Output the HTML structure with dynamic data
|
||||||
echo '
|
echo '
|
||||||
|
<a href="' . $blog_link . '" style="text-decoration: none; color: inherit;">
|
||||||
<div class="blog-item style-three" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
<div class="blog-item style-three" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||||
<div class="image" style="border-radius:20px; width:300px;height: 250px;margin-right:0px;">
|
<div class="image" style="border-radius:20px; width:300px;height: 250px;margin-right:0px;">
|
||||||
<img src="' . htmlspecialchars($blog_image) . '" alt="' . htmlspecialchars($post["title"]) . '">
|
<img src="' . htmlspecialchars($blog_image) . '" alt="' . htmlspecialchars($post["title"]) . '">
|
||||||
@@ -117,6 +118,7 @@ include_once($rootPath . '/header.php');
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
';
|
';
|
||||||
endwhile;
|
endwhile;
|
||||||
|
|||||||
@@ -46,32 +46,27 @@ $posts = $result->get_result();
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$bannerFolder = 'assets/images/banners/';
|
|
||||||
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<!-- Blog List Area start -->
|
<!-- Blog List Area start -->
|
||||||
<section class="blog-list-page py-100 rel z-1">
|
<section class="blog-list-page py-100 rel z-1">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
|
|
||||||
<h2>My Posts</h2>
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px;">
|
||||||
|
<h2 style="margin: 0;">My Blog Posts</h2>
|
||||||
|
<a href="blog_create" class="theme-btn create-album-btn">
|
||||||
|
<i class="far fa-plus"></i> Create New Post
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<?php if (isset($_SESSION['message'])): ?>
|
<?php if (isset($_SESSION['message'])): ?>
|
||||||
<div class="alert alert-warning message-box">
|
<div class="alert alert-warning message-box">
|
||||||
<?php echo $_SESSION['message']; ?>
|
<?php echo $_SESSION['message']; ?>
|
||||||
<span class="close-btn" onclick="this.parentElement.style.display='none'">×</span>
|
<span class="close-btn" onclick="this.parentElement.style.display='none'">×</span>
|
||||||
</div>
|
</div>
|
||||||
<?php unset($_SESSION['message']); ?>
|
<?php unset($_SESSION['message']);
|
||||||
<?php endif; ?>
|
endif;
|
||||||
<a href="blog_create.php">+ New Post</a>
|
|
||||||
|
|
||||||
<?php while ($post = $posts->fetch_assoc()):
|
while ($post = $posts->fetch_assoc()):
|
||||||
// Determine cover image - use provided image or fallback placeholder
|
// Determine cover image - use provided image or fallback placeholder
|
||||||
$coverImage = $post["image"] ? $post["image"] : 'assets/images/placeholder.jpg';
|
$coverImage = $post["image"] ? $post["image"] : 'assets/images/placeholder.jpg';
|
||||||
// Output the HTML structure with dynamic data
|
// Output the HTML structure with dynamic data
|
||||||
|
|||||||
@@ -70,24 +70,7 @@ include_once($rootPath . '/header.php');
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="shop-shorter rel z-3 mb-20">
|
|
||||||
<!-- <ul class="grid-list mb-15 me-2">
|
|
||||||
<li><a href="#"><i class="fal fa-border-all"></i></a></li>
|
|
||||||
<li><a href="#"><i class="far fa-list"></i></a></li>
|
|
||||||
</ul>
|
|
||||||
<div class="sort-text mb-15 me-4 me-xl-auto">
|
|
||||||
</div> -->
|
|
||||||
<div class="sort-text mb-15 me-4">
|
|
||||||
Sort By
|
|
||||||
</div>
|
|
||||||
<select>
|
|
||||||
<option value="default" selected="">Sort By</option>
|
|
||||||
<option value="new">Newness</option>
|
|
||||||
<option value="old">Oldest</option>
|
|
||||||
<option value="hight-to-low">High To Low</option>
|
|
||||||
<option value="low-to-high">Low To High</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
// Query to retrieve upcoming published events only
|
// Query to retrieve upcoming published events only
|
||||||
|
|||||||
@@ -58,20 +58,13 @@ $conn->close();
|
|||||||
}
|
}
|
||||||
|
|
||||||
.album-card {
|
.album-card {
|
||||||
position: relative;
|
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: white;
|
background: white;
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
border: 1px solid #e0e0e0;
|
||||||
|
|
||||||
.album-card:hover {
|
|
||||||
transform: translateY(-8px);
|
|
||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-image-wrapper {
|
.album-image-wrapper {
|
||||||
@@ -86,11 +79,6 @@ $conn->close();
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-card:hover .album-image-wrapper img {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-image-wrapper .no-image {
|
.album-image-wrapper .no-image {
|
||||||
@@ -163,49 +151,21 @@ $conn->close();
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-view-btn {
|
.album-edit-icon {
|
||||||
flex: 1;
|
background: none;
|
||||||
padding: 8px 12px;
|
|
||||||
background: #667eea;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 30px;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 0.3s;
|
color: inherit;
|
||||||
text-decoration: none;
|
padding: 0;
|
||||||
text-align: center;
|
font-size: 1.2rem;
|
||||||
display: block;
|
transition: color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-view-btn:hover {
|
.album-edit-icon:hover {
|
||||||
background: #764ba2;
|
|
||||||
text-decoration: none;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-edit-btn {
|
|
||||||
padding: 8px 12px;
|
|
||||||
background: white;
|
|
||||||
color: #667eea;
|
color: #667eea;
|
||||||
border: 1px solid #667eea;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
text-decoration: none;
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.album-edit-btn:hover {
|
|
||||||
background: #667eea;
|
|
||||||
color: white;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-album-btn {
|
.create-album-btn {
|
||||||
@@ -260,6 +220,7 @@ require_once($rootPath . '/components/banner.php');
|
|||||||
<?php if (count($albums) > 0): ?>
|
<?php if (count($albums) > 0): ?>
|
||||||
<div class="gallery-grid">
|
<div class="gallery-grid">
|
||||||
<?php foreach ($albums as $album): ?>
|
<?php foreach ($albums as $album): ?>
|
||||||
|
<a href="view_album?id=<?php echo $album['album_id']; ?>" style="text-decoration: none; color: inherit;">
|
||||||
<div class="album-card">
|
<div class="album-card">
|
||||||
<div class="album-image-wrapper">
|
<div class="album-image-wrapper">
|
||||||
<?php if ($album['cover_image']): ?>
|
<?php if ($album['cover_image']): ?>
|
||||||
@@ -289,17 +250,15 @@ require_once($rootPath . '/components/banner.php');
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="album-actions">
|
<div class="album-actions">
|
||||||
<a href="view_album?id=<?php echo $album['album_id']; ?>" class="album-view-btn">
|
|
||||||
View
|
|
||||||
</a>
|
|
||||||
<?php if ($album['user_id'] == $current_user_id): ?>
|
<?php if ($album['user_id'] == $current_user_id): ?>
|
||||||
<a href="edit_album?id=<?php echo $album['album_id']; ?>" class="album-edit-btn">
|
<a href="edit_album?id=<?php echo $album['album_id']; ?>" class="album-edit-icon" title="Edit">
|
||||||
<i class="far fa-edit"></i>
|
<i class="far fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user