Update: Add publish/unpublish button to admin trips table and improve table styling

This commit is contained in:
twotalesanimation
2025-12-04 18:35:36 +02:00
parent d81d74a7c7
commit fdeaf85bf0
12 changed files with 350 additions and 134 deletions

View File

@@ -174,7 +174,7 @@ if (!empty($bannerImages)) {
// Fetch bookings for the current trip
$bookingsSql = "SELECT b.user_id, b.num_vehicles, b.num_adults, b.num_children, b.num_pensioners, b.radio, b.status,
u.first_name, u.last_name,
u.first_name, u.last_name, u.profile_pic,
(b.total_amount - b.discount_amount) AS paid
FROM bookings b
INNER JOIN users u ON b.user_id = u.user_id

View File

@@ -22,88 +22,220 @@ if ($result && $result->num_rows > 0) {
}
?>
<style>
table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
margin: 10px 0;
}
thead th {
cursor: pointer;
text-align: left;
padding: 10px;
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>
<script>
document.addEventListener("DOMContentLoaded", function() {
const tables = document.querySelectorAll("table");
tables.forEach((table) => {
const headers = table.querySelectorAll("thead th");
const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = table.previousElementSibling;
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));
});
});
if (rows.length === 0) {
filterInput.style.display = "none";
} else {
filterInput.addEventListener("input", function() {
const filterValue = filterInput.value.trim().toLowerCase();
rows.forEach(row => {
const rowText = row.textContent.trim().toLowerCase();
row.style.display = rowText.includes(filterValue) ? "" : "none";
});
});
}
});
});
</script>
<?php
$pageTitle = 'Manage Trips';
$breadcrumbs = [['Home' => 'index'], ['Admin' => 'admin'], [$pageTitle => '']];
require_once($rootPath . '/components/banner.php');
$bannerFolder = 'assets/images/banners/';
$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 -->
<section class="trips-management-area py-100 rel z-1">
<section class="tour-list-page py-100 rel z-1">
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="section-title mb-50">
<h2>Manage Trips</h2>
<a href="manage_trips" class="theme-btn">
<i class="far fa-plus"></i> Create New Trip
</a>
</div>
<div class="table-responsive">
<table class="table table-striped">
<thead class="table-dark">
<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>
<?php if (count($trips) > 0): ?>
<?php foreach ($trips as $trip): ?>
<tr>
<td>
<strong><?php echo htmlspecialchars($trip['trip_name']); ?></strong>
</td>
<td><?php echo htmlspecialchars($trip['location']); ?></td>
<td><?php echo date('M d, Y', strtotime($trip['start_date'])); ?></td>
<td><?php echo date('M d, Y', strtotime($trip['end_date'])); ?></td>
<td><?php echo $trip['vehicle_capacity']; ?></td>
<td>
<span class="badge bg-info">
<?php echo $trip['places_booked'] . ' / ' . $trip['vehicle_capacity']; ?>
</span>
</td>
<td>R <?php echo number_format($trip['cost_members'], 2); ?></td>
<td>
<?php if ($trip['published'] == 1): ?>
<span class="badge bg-success">Published</span>
<?php else: ?>
<span class="badge bg-warning">Draft</span>
<?php endif; ?>
</td>
<td>
<a href="manage_trips?trip_id=<?php echo $trip['trip_id']; ?>"
class="btn btn-sm btn-primary" title="Edit">
<i class="far fa-edit"></i>
</a>
<button class="btn btn-sm btn-danger delete-trip"
data-trip-id="<?php echo $trip['trip_id']; ?>"
title="Delete">
<i class="far fa-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="9" class="text-center py-4">
<p class="text-muted">No trips found. <a href="manage_trips">Create one</a></p>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<div style="margin-bottom: 20px;">
<a href="manage_trips" class="theme-btn">
<i class="far fa-plus"></i> Create New Trip
</a>
</div>
<?php
if (count($trips) > 0) {
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 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) {
$publishButtonText = $trip['published'] == 1 ? 'Unpublish' : 'Publish';
$publishButtonClass = $trip['published'] == 1 ? 'btn-warning' : 'btn-success';
echo '<tr>
<td><strong>' . htmlspecialchars($trip['trip_name']) . '</strong></td>
<td>' . htmlspecialchars($trip['location']) . '</td>
<td>' . date('M d, Y', strtotime($trip['start_date'])) . '</td>
<td>' . date('M d, Y', strtotime($trip['end_date'])) . '</td>
<td>' . $trip['vehicle_capacity'] . '</td>
<td><span class="badge bg-info">' . $trip['places_booked'] . ' / ' . $trip['vehicle_capacity'] . '</span></td>
<td>R ' . number_format($trip['cost_members'], 2) . '</td>
<td>' . ($trip['published'] == 1 ? '<span class="badge bg-success">Published</span>' : '<span class="badge bg-warning">Draft</span>') . '</td>
<td>
<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>';
} else {
echo '<p>No trips found. <a href="manage_trips">Create one</a></p>';
}
?>
</div>
</section>
<!-- Trips Management Area end -->
@@ -111,6 +243,44 @@ if ($result && $result->num_rows > 0) {
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('.toggle-publish').on('click', function() {
var tripId = $(this).data('trip-id');
var button = $(this);
var row = button.closest('tr');
$.ajax({
url: 'toggle_trip_published',
type: 'POST',
data: {
trip_id: tripId
},
dataType: 'json',
success: function(response) {
if (response.status === 'success') {
// Update button appearance
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');
// Update status badge
row.find('td:nth-child(8)').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');
// 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');
}
});
});
$('.delete-trip').on('click', function() {
if (!confirm('Are you sure you want to delete this trip? This action cannot be undone.')) {
return false;

View File

@@ -137,7 +137,7 @@ if ($trip_id) {
<div class="col-md-12 mt-20">
<div class="form-group">
<label>Trip Images</label>
<p class="text-muted">Upload images for this trip. Primary image will be named {trip_id}_01.jpg</p>
<p class="text-muted">Upload images for this trip. Ideally 5 different images will be required</p>
<input type="file" name="trip_images[]" class="form-control" accept="image/*" multiple>
<?php if ($trip): ?>
<small class="text-info">Images will be saved to: assets/images/trips/<?php echo $trip_id; ?>_{number}.jpg</small>