Compare commits
1 Commits
feature/ph
...
feature/bl
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d078cb954 |
137
.htaccess
@@ -1,140 +1,3 @@
|
||||
# URL Rewrite Rules - Maps old URLs to new directory structure during migration
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteBase /
|
||||
|
||||
# Don't rewrite existing files or directories
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
|
||||
# === STRIP .PHP EXTENSION ===
|
||||
# Redirect /page.php to /page (301 permanent redirect)
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.+)\.php$ /$1 [R=301,L]
|
||||
# Internally rewrite /page to /page.php if page.php exists
|
||||
RewriteCond %{REQUEST_FILENAME}\.php -f
|
||||
RewriteRule ^(.+)$ $1.php [L]
|
||||
|
||||
# === AUTH PAGES ===
|
||||
RewriteRule ^login$ src/pages/auth/login.php [L]
|
||||
RewriteRule ^register$ src/pages/auth/register.php [L]
|
||||
RewriteRule ^forgot_password$ src/pages/auth/forgot_password.php [L]
|
||||
RewriteRule ^reset_password$ src/pages/auth/reset_password.php [L]
|
||||
RewriteRule ^verify$ src/pages/auth/verify.php [L]
|
||||
RewriteRule ^resend_verification$ src/pages/auth/resend_verification.php [L]
|
||||
RewriteRule ^change_password$ src/pages/auth/change_password.php [L]
|
||||
RewriteRule ^update_password$ src/pages/auth/update_password.php [L]
|
||||
|
||||
# === MEMBERSHIP PAGES ===
|
||||
RewriteRule ^membership$ src/pages/memberships/membership.php [L]
|
||||
RewriteRule ^membership_details$ src/pages/memberships/membership_details.php [L]
|
||||
RewriteRule ^membership_application$ src/pages/memberships/membership_application.php [L]
|
||||
RewriteRule ^membership_payment$ src/pages/memberships/membership_payment.php [L]
|
||||
RewriteRule ^renew_membership$ src/pages/memberships/renew_membership.php [L]
|
||||
RewriteRule ^member_info$ src/pages/memberships/member_info.php [L]
|
||||
|
||||
# === BOOKING PAGES ===
|
||||
RewriteRule ^bookings$ src/pages/bookings/bookings.php [L]
|
||||
RewriteRule ^campsites$ src/pages/bookings/campsites.php [L]
|
||||
RewriteRule ^campsite_booking$ src/pages/bookings/campsite_booking.php [L]
|
||||
RewriteRule ^add_campsite$ src/pages/add_campsite.php [L]
|
||||
RewriteRule ^trips$ src/pages/bookings/trips.php [L]
|
||||
RewriteRule ^trip-details$ src/pages/bookings/trip-details.php [L]
|
||||
RewriteRule ^course_details$ src/pages/bookings/course_details.php [L]
|
||||
RewriteRule ^driver_training$ src/pages/bookings/driver_training.php [L]
|
||||
|
||||
# === SHOP PAGES ===
|
||||
RewriteRule ^view_cart$ src/pages/shop/view_cart.php [L]
|
||||
RewriteRule ^add_to_cart$ src/pages/shop/add_to_cart.php [L]
|
||||
RewriteRule ^bar_tabs$ src/pages/shop/bar_tabs.php [L]
|
||||
RewriteRule ^payment_confirmation$ src/pages/shop/payment_confirmation.php [L]
|
||||
RewriteRule ^confirm$ src/pages/shop/confirm.php [L]
|
||||
RewriteRule ^confirm2$ src/pages/shop/confirm2.php [L]
|
||||
|
||||
# === GALLERY PAGES ===
|
||||
RewriteRule ^gallery$ src/pages/gallery/gallery.php [L]
|
||||
RewriteRule ^create_album$ src/pages/gallery/create_album.php [L]
|
||||
RewriteRule ^edit_album$ src/pages/gallery/create_album.php [L]
|
||||
RewriteRule ^view_album$ src/pages/gallery/view_album.php [L]
|
||||
|
||||
# === EVENTS & BLOG PAGES ===
|
||||
RewriteRule ^events$ src/pages/events/events.php [L]
|
||||
RewriteRule ^blog$ src/pages/events/blog.php [L]
|
||||
RewriteRule ^blog_details$ src/pages/events/blog_details.php [L]
|
||||
RewriteRule ^best_of_the_eastern_cape_2024$ src/pages/events/best_of_the_eastern_cape_2024.php [L]
|
||||
RewriteRule ^2025_agm_minutes$ src/pages/events/2025_agm_minutes.php [L]
|
||||
RewriteRule ^agm_content$ src/pages/events/agm_content.php [L]
|
||||
RewriteRule ^instapage$ src/pages/events/instapage.php [L]
|
||||
|
||||
# === OTHER PAGES ===
|
||||
RewriteRule ^about$ src/pages/other/about.php [L]
|
||||
RewriteRule ^contact$ src/pages/other/contact.php [L]
|
||||
RewriteRule ^privacy_policy$ src/pages/other/privacy_policy.php [L]
|
||||
RewriteRule ^404$ src/pages/other/404.php [L]
|
||||
RewriteRule ^account_settings$ src/pages/other/account_settings.php [L]
|
||||
RewriteRule ^rescue_recovery$ src/pages/other/rescue_recovery.php [L]
|
||||
RewriteRule ^bush_mechanics$ src/pages/other/bush_mechanics.php [L]
|
||||
RewriteRule ^indemnity$ src/pages/other/indemnity.php [L]
|
||||
RewriteRule ^indemnity_waiver$ src/pages/other/indemnity_waiver.php [L]
|
||||
RewriteRule ^basic_indemnity$ src/pages/other/basic_indemnity.php [L]
|
||||
RewriteRule ^view_indemnity$ src/pages/other/view_indemnity.php [L]
|
||||
|
||||
# === ADMIN PAGES ===
|
||||
RewriteRule ^admin_members$ src/admin/admin_members.php [L]
|
||||
RewriteRule ^admin_payments$ src/admin/admin_payments.php [L]
|
||||
RewriteRule ^admin_web_users$ src/admin/admin_web_users.php [L]
|
||||
RewriteRule ^admin_events$ src/admin/admin_events.php [L]
|
||||
RewriteRule ^admin_course_bookings$ src/admin/admin_course_bookings.php [L]
|
||||
RewriteRule ^admin_camp_bookings$ src/admin/admin_camp_bookings.php [L]
|
||||
RewriteRule ^admin_trip_bookings$ src/admin/admin_trip_bookings.php [L]
|
||||
RewriteRule ^admin_visitors$ src/admin/admin_visitors.php [L]
|
||||
RewriteRule ^admin_efts$ src/admin/admin_efts.php [L]
|
||||
RewriteRule ^admin_trips$ src/admin/admin_trips.php [L]
|
||||
RewriteRule ^manage_events$ src/admin/manage_events.php [L]
|
||||
RewriteRule ^manage_trips$ src/admin/manage_trips.php [L]
|
||||
|
||||
# === API/AJAX ENDPOINTS ===
|
||||
RewriteRule ^fetch_users$ src/api/fetch_users.php [L]
|
||||
RewriteRule ^fetch_drinks$ src/api/fetch_drinks.php [L]
|
||||
RewriteRule ^fetch_bar_tabs$ src/api/fetch_bar_tabs.php [L]
|
||||
RewriteRule ^get_campsites$ src/api/get_campsites.php [L]
|
||||
RewriteRule ^get_tab_total$ src/api/get_tab_total.php [L]
|
||||
RewriteRule ^google_validate_login$ src/api/google_validate_login.php [L]
|
||||
|
||||
# === PROCESSORS ===
|
||||
RewriteRule ^validate_login$ src/processors/validate_login.php [L]
|
||||
RewriteRule ^register_user$ src/processors/register_user.php [L]
|
||||
RewriteRule ^process_application$ src/processors/process_application.php [L]
|
||||
RewriteRule ^process_booking$ src/processors/process_booking.php [L]
|
||||
RewriteRule ^process_camp_booking$ src/processors/process_camp_booking.php [L]
|
||||
RewriteRule ^process_course_booking$ src/processors/process_course_booking.php [L]
|
||||
RewriteRule ^process_trip_booking$ src/processors/process_trip_booking.php [L]
|
||||
RewriteRule ^process_membership_payment$ src/processors/process_membership_payment.php [L]
|
||||
RewriteRule ^process_payments$ src/processors/process_payments.php [L]
|
||||
RewriteRule ^process_eft$ src/processors/process_eft.php [L]
|
||||
RewriteRule ^submit_order$ src/processors/submit_order.php [L]
|
||||
RewriteRule ^submit_pop$ src/processors/submit_pop.php [L]
|
||||
RewriteRule ^process_signature$ src/processors/process_signature.php [L]
|
||||
RewriteRule ^create_bar_tab$ src/processors/create_bar_tab.php [L]
|
||||
RewriteRule ^update_application$ src/processors/update_application.php [L]
|
||||
RewriteRule ^update_user$ src/processors/update_user.php [L]
|
||||
RewriteRule ^upload_profile_picture$ src/processors/upload_profile_picture.php [L]
|
||||
RewriteRule ^send_reset_link$ src/processors/send_reset_link.php [L]
|
||||
RewriteRule ^logout$ src/processors/logout.php [L]
|
||||
RewriteRule ^process_trip$ src/processors/process_trip.php [L]
|
||||
RewriteRule ^process_event$ src/admin/process_event.php [L]
|
||||
RewriteRule ^toggle_trip_published$ src/processors/toggle_trip_published.php [L]
|
||||
RewriteRule ^toggle_event_published$ src/admin/toggle_event_published.php [L]
|
||||
RewriteRule ^delete_trip$ src/processors/delete_trip.php [L]
|
||||
RewriteRule ^delete_event$ src/admin/delete_event.php [L]
|
||||
RewriteRule ^save_album$ src/processors/save_album.php [L]
|
||||
RewriteRule ^update_album$ src/processors/update_album.php [L]
|
||||
RewriteRule ^delete_album$ src/processors/delete_album.php [L]
|
||||
RewriteRule ^delete_photo$ src/processors/delete_photo.php [L]
|
||||
RewriteRule ^get_album_photos$ src/processors/get_album_photos.php [L]
|
||||
|
||||
</IfModule>
|
||||
|
||||
php_flag display_errors On
|
||||
# php_value error_reporting -1
|
||||
RedirectMatch 403 ^/\.well-known
|
||||
|
||||
@@ -1,258 +1,268 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(dirname(__DIR__)));
|
||||
include_once($rootPath . '/header.php');
|
||||
$page_id = 'agm_minutes';
|
||||
?>
|
||||
|
||||
<style>
|
||||
.image {
|
||||
width: 400px;
|
||||
/* Set your desired width */
|
||||
height: 350px;
|
||||
/* Set your desired height */
|
||||
overflow: hidden;
|
||||
/* Hide any overflow */
|
||||
display: block;
|
||||
/* Ensure proper block behavior */
|
||||
}
|
||||
|
||||
.image img {
|
||||
width: 100%;
|
||||
/* Image scales to fill the container */
|
||||
height: 100%;
|
||||
/* Image scales to fill the container */
|
||||
object-fit: cover;
|
||||
/* Fills the container while maintaining aspect ratio */
|
||||
object-position: top;
|
||||
/* Aligns the top of the image with the top of the container */
|
||||
display: block;
|
||||
/* Prevents inline whitespace issues */
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
body {
|
||||
/* font-family: Arial, sans-serif; */
|
||||
line-height: 1.6;
|
||||
/* max-width: 800px; */
|
||||
margin: auto;
|
||||
/* padding: 20px; */
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.img-left,
|
||||
.img-right {
|
||||
max-width: 30%;
|
||||
margin: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.img-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.img-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<?php
|
||||
$pageTitle = '2025 AGM Minutes';
|
||||
$breadcrumbs = [['Home' => 'index.php']];
|
||||
require_once($rootPath . '/components/banner.php');
|
||||
?>
|
||||
|
||||
<!-- Blog Detaisl Area start -->
|
||||
<section class="blog-detaisl-page py-100 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div class="blog-details-content" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<a href="blog.html" class="category">Report</a>
|
||||
<ul class="blog-meta mb-30">
|
||||
<li><img src="assets/images/pp/default.png" alt="Admin"> <a href="#">John Runciman</a></li>
|
||||
<li><i class="far fa-calendar-alt"></i> <a href="#">5 April 2025</a></li>
|
||||
<li><i class="far fa-comments"></i> <a href="#">Comments (<?= getCommentCount($page_id);?>)</a></li>
|
||||
</ul>
|
||||
<h2>2025 AGM Minutes & Chairman's Report</h2>
|
||||
<?php include_once('agm_content.php');?>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="mb-45">
|
||||
|
||||
<div class="tag-share mb-50">
|
||||
<div class="item" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h6>Tags </h6>
|
||||
<div class="tag-coulds">
|
||||
<a href="blog">Reports</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="item" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h6>Share </h6>
|
||||
<div class="social-style-one">
|
||||
<a href="#"><i class="fab fa-facebook-f"></i></a>
|
||||
<a href="#"><i class="fab fa-twitter"></i></a>
|
||||
<a href="#"><i class="fab fa-linkedin-in"></i></a>
|
||||
<a href="#"><i class="fab fa-instagram"></i></a>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- <div class="admin-comment bgc-lighter" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="comment-body">
|
||||
<div class="author-thumb">
|
||||
<img src="assets/images/blog/admin-comment.jpg" alt="Author">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h4>Richard M. Fudge</h4>
|
||||
<p>The world is a book, and those who do not travel read only one page. Every journey we undertake is a chapter filled with lessons, experiences, and stories.</p>
|
||||
<div class="social-icons">
|
||||
<a href="contact.html"><i class="fab fa-facebook-f"></i></a>
|
||||
<a href="contact.html"><i class="fab fa-twitter"></i></a>
|
||||
<a href="contact.html"><i class="fab fa-linkedin-in"></i></a>
|
||||
<a href="contact.html"><i class="fab fa-instagram"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- <form id="comment-form" class="comment-form bgc-lighter z-1 rel mt-25" name="review-form" action="#" method="post" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h5>Leave A Comment</h5>
|
||||
<p>Your email address will not be published. Required fields are marked *</p>
|
||||
<div class="row gap-20 mt-30">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<input type="text" id="full-name" name="full-name" class="form-control" placeholder="Name" value="" required="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<input type="email" id="email-address" name="email" class="form-control" placeholder="Email" value="" required="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<textarea name="message" id="message" class="form-control" rows="5" placeholder="Message" required=""></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group mb-0">
|
||||
<ul class="radio-filter mb-25">
|
||||
<li>
|
||||
<input class="form-check-input" type="radio" name="terms-condition" id="terms-condition">
|
||||
<label for="terms-condition">Save my name, email, and website in this browser for the next time I comment.</label>
|
||||
</li>
|
||||
</ul>
|
||||
<button type="submit" class="theme-btn style-two">
|
||||
<span data-hover="Send Comments">Send Comments</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form> -->
|
||||
<?php include_once('comment_box.php'); ?>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-8 col-sm-10 rmt-75">
|
||||
<div class="blog-sidebar">
|
||||
|
||||
<!-- <div class="widget widget-search" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<form action="#" class="default-search-form">
|
||||
<input type="text" placeholder="Search" required="">
|
||||
<button type="submit" class="searchbutton far fa-search"></button>
|
||||
</form>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="widget widget-category" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h5 class="widget-title">Category</h5>
|
||||
<ul class="list-style-three">
|
||||
<li><a href="blog.html">Adventure</a></li>
|
||||
<li><a href="blog.html">Hiking & Trekking</a></li>
|
||||
<li><a href="blog.html">Cycling Tours</a></li>
|
||||
<li><a href="blog.html">Family Tours</a></li>
|
||||
<li><a href="blog.html">Mountain Hiking</a></li>
|
||||
<li><a href="blog.html">Rafting Excursion</a></li>
|
||||
<li><a href="blog.html">Coastal Paragliding</a></li>
|
||||
</ul>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="widget widget-news" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h5 class="widget-title">Recent News</h5>
|
||||
<ul>
|
||||
<li>
|
||||
<div class="image">
|
||||
<img src="assets/images/widgets/news1.jpg" alt="News">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h6><a href="blog-details.html">Unique Destinations an tolded Stories ways</a></h6>
|
||||
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="image">
|
||||
<img src="assets/images/widgets/news2.jpg" alt="News">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h6><a href="blog-details.html">Immersive Experiences from Around Globe</a></h6>
|
||||
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="image">
|
||||
<img src="assets/images/widgets/news3.jpg" alt="News">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h6><a href="blog-details.html">Journey to Inspire Your Next Adventure</a></h6>
|
||||
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
|
||||
<div class="widget widget-gallery" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h5 class="widget-title">Gallery</h5>
|
||||
<div class="gallery">
|
||||
<?php
|
||||
$folder = 'assets/images/blog/2/';
|
||||
$files = glob($folder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
||||
shuffle($files); // Randomize the order
|
||||
|
||||
foreach ($files as $file) {
|
||||
echo '<a href="' . $file . '" style="width: 110px; height: 110px; overflow: hidden; display: inline-block; margin: 2px;">';
|
||||
echo '<img src="' . $file . '" alt="Gallery" style="width: 100%; height: 100%; object-fit: cover; display: block;">';
|
||||
echo '</a>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Blog Detaisl Area end -->
|
||||
|
||||
|
||||
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
$page_id = 'agm_minutes';
|
||||
?>
|
||||
|
||||
<style>
|
||||
.image {
|
||||
width: 400px;
|
||||
/* Set your desired width */
|
||||
height: 350px;
|
||||
/* Set your desired height */
|
||||
overflow: hidden;
|
||||
/* Hide any overflow */
|
||||
display: block;
|
||||
/* Ensure proper block behavior */
|
||||
}
|
||||
|
||||
.image img {
|
||||
width: 100%;
|
||||
/* Image scales to fill the container */
|
||||
height: 100%;
|
||||
/* Image scales to fill the container */
|
||||
object-fit: cover;
|
||||
/* Fills the container while maintaining aspect ratio */
|
||||
object-position: top;
|
||||
/* Aligns the top of the image with the top of the container */
|
||||
display: block;
|
||||
/* Prevents inline whitespace issues */
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
body {
|
||||
/* font-family: Arial, sans-serif; */
|
||||
line-height: 1.6;
|
||||
/* max-width: 800px; */
|
||||
margin: auto;
|
||||
/* padding: 20px; */
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.img-left,
|
||||
.img-right {
|
||||
max-width: 30%;
|
||||
margin: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.img-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.img-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('assets/images/blog/2/agm.jpg');">
|
||||
<div class="banner-overlay"></div>
|
||||
<div class="container">
|
||||
<div class="banner-inner text-white">
|
||||
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">2025 AGM Minutes & Chairman's Report</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">2025 AGM Minutes & Chairman's Report</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Page Banner End -->
|
||||
|
||||
|
||||
<!-- Blog Detaisl Area start -->
|
||||
<section class="blog-detaisl-page py-100 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div class="blog-details-content" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<a href="blog.html" class="category">Report</a>
|
||||
<ul class="blog-meta mb-30">
|
||||
<li><img src="assets/images/pp/default.png" alt="Admin"> <a href="#">John Runciman</a></li>
|
||||
<li><i class="far fa-calendar-alt"></i> <a href="#">5 April 2025</a></li>
|
||||
<li><i class="far fa-comments"></i> <a href="#">Comments (<?= getCommentCount($page_id);?>)</a></li>
|
||||
</ul>
|
||||
<h2>2025 AGM Minutes & Chairman's Report</h2>
|
||||
<?php include_once('agm_content.php');?>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="mb-45">
|
||||
|
||||
<div class="tag-share mb-50">
|
||||
<div class="item" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h6>Tags </h6>
|
||||
<div class="tag-coulds">
|
||||
<a href="blog.php">Reports</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="item" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h6>Share </h6>
|
||||
<div class="social-style-one">
|
||||
<a href="#"><i class="fab fa-facebook-f"></i></a>
|
||||
<a href="#"><i class="fab fa-twitter"></i></a>
|
||||
<a href="#"><i class="fab fa-linkedin-in"></i></a>
|
||||
<a href="#"><i class="fab fa-instagram"></i></a>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- <div class="admin-comment bgc-lighter" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="comment-body">
|
||||
<div class="author-thumb">
|
||||
<img src="assets/images/blog/admin-comment.jpg" alt="Author">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h4>Richard M. Fudge</h4>
|
||||
<p>The world is a book, and those who do not travel read only one page. Every journey we undertake is a chapter filled with lessons, experiences, and stories.</p>
|
||||
<div class="social-icons">
|
||||
<a href="contact.html"><i class="fab fa-facebook-f"></i></a>
|
||||
<a href="contact.html"><i class="fab fa-twitter"></i></a>
|
||||
<a href="contact.html"><i class="fab fa-linkedin-in"></i></a>
|
||||
<a href="contact.html"><i class="fab fa-instagram"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- <form id="comment-form" class="comment-form bgc-lighter z-1 rel mt-25" name="review-form" action="#" method="post" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h5>Leave A Comment</h5>
|
||||
<p>Your email address will not be published. Required fields are marked *</p>
|
||||
<div class="row gap-20 mt-30">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<input type="text" id="full-name" name="full-name" class="form-control" placeholder="Name" value="" required="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<input type="email" id="email-address" name="email" class="form-control" placeholder="Email" value="" required="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<textarea name="message" id="message" class="form-control" rows="5" placeholder="Message" required=""></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group mb-0">
|
||||
<ul class="radio-filter mb-25">
|
||||
<li>
|
||||
<input class="form-check-input" type="radio" name="terms-condition" id="terms-condition">
|
||||
<label for="terms-condition">Save my name, email, and website in this browser for the next time I comment.</label>
|
||||
</li>
|
||||
</ul>
|
||||
<button type="submit" class="theme-btn style-two">
|
||||
<span data-hover="Send Comments">Send Comments</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form> -->
|
||||
<?php include_once('comment_box.php'); ?>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-8 col-sm-10 rmt-75">
|
||||
<div class="blog-sidebar">
|
||||
|
||||
<!-- <div class="widget widget-search" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<form action="#" class="default-search-form">
|
||||
<input type="text" placeholder="Search" required="">
|
||||
<button type="submit" class="searchbutton far fa-search"></button>
|
||||
</form>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="widget widget-category" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h5 class="widget-title">Category</h5>
|
||||
<ul class="list-style-three">
|
||||
<li><a href="blog.html">Adventure</a></li>
|
||||
<li><a href="blog.html">Hiking & Trekking</a></li>
|
||||
<li><a href="blog.html">Cycling Tours</a></li>
|
||||
<li><a href="blog.html">Family Tours</a></li>
|
||||
<li><a href="blog.html">Mountain Hiking</a></li>
|
||||
<li><a href="blog.html">Rafting Excursion</a></li>
|
||||
<li><a href="blog.html">Coastal Paragliding</a></li>
|
||||
</ul>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="widget widget-news" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h5 class="widget-title">Recent News</h5>
|
||||
<ul>
|
||||
<li>
|
||||
<div class="image">
|
||||
<img src="assets/images/widgets/news1.jpg" alt="News">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h6><a href="blog-details.html">Unique Destinations an tolded Stories ways</a></h6>
|
||||
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="image">
|
||||
<img src="assets/images/widgets/news2.jpg" alt="News">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h6><a href="blog-details.html">Immersive Experiences from Around Globe</a></h6>
|
||||
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="image">
|
||||
<img src="assets/images/widgets/news3.jpg" alt="News">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h6><a href="blog-details.html">Journey to Inspire Your Next Adventure</a></h6>
|
||||
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
|
||||
<div class="widget widget-gallery" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h5 class="widget-title">Gallery</h5>
|
||||
<div class="gallery">
|
||||
<?php
|
||||
$folder = 'assets/images/blog/2/';
|
||||
$files = glob($folder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
||||
shuffle($files); // Randomize the order
|
||||
|
||||
foreach ($files as $file) {
|
||||
echo '<a href="' . $file . '" style="width: 110px; height: 110px; overflow: hidden; display: inline-block; margin: 2px;">';
|
||||
echo '<img src="' . $file . '" alt="Gallery" style="width: 100%; height: 100%; object-fit: cover; display: block;">';
|
||||
echo '</a>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Blog Detaisl Area end -->
|
||||
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,46 +1,44 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
include_once(dirname(dirname(dirname(__DIR__))) . '/header.php');
|
||||
?>
|
||||
|
||||
|
||||
<!-- 404 Error Area start -->
|
||||
<section class="error-area pt-70 pb-100 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row align-items-center justify-content-between">
|
||||
<div class="col-xl-5 col-lg-6">
|
||||
<div class="error-content rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h1>OOPS! </h1>
|
||||
<div class="section-title mt-15 mb-25">
|
||||
<h2>This Page Can’t be Found</h2>
|
||||
</div>
|
||||
<!-- <p>Best features to include on business landing page are those that quickly convey your value proposition, build trust, and encourage action. Here are six essential features</p> -->
|
||||
<!-- <form class="newsletter-form mt-40 mb-50" action="#">
|
||||
<input id="news-email" type="text" placeholder="Search keyword" required>
|
||||
<button type="submit" class="theme-btn bgc-secondary style-two">
|
||||
<span data-hover="Search">Search</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</button>
|
||||
</form>
|
||||
<div class="keywords">
|
||||
<a href="blog.html">Travel</a>
|
||||
<a href="blog.html">Luxury Hotel</a>
|
||||
<a href="blog.html">Indonesia</a>
|
||||
<a href="blog.html">Sea Beach</a>
|
||||
<a href="blog.html">Camping</a>
|
||||
<a href="blog.html">Hiking</a>
|
||||
<a href="blog.html">Fishing</a>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-5 col-lg-6">
|
||||
<div class="error-images" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
|
||||
<img src="assets/images/404/lost.jpg" alt="404 Error">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- 404 Error Area end -->
|
||||
|
||||
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
?>
|
||||
|
||||
|
||||
<!-- 404 Error Area start -->
|
||||
<section class="error-area pt-70 pb-100 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row align-items-center justify-content-between">
|
||||
<div class="col-xl-5 col-lg-6">
|
||||
<div class="error-content rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
|
||||
<h1>OOPS! </h1>
|
||||
<div class="section-title mt-15 mb-25">
|
||||
<h2>This Page Can’t be Found</h2>
|
||||
</div>
|
||||
<!-- <p>Best features to include on business landing page are those that quickly convey your value proposition, build trust, and encourage action. Here are six essential features</p> -->
|
||||
<!-- <form class="newsletter-form mt-40 mb-50" action="#">
|
||||
<input id="news-email" type="text" placeholder="Search keyword" required>
|
||||
<button type="submit" class="theme-btn bgc-secondary style-two">
|
||||
<span data-hover="Search">Search</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</button>
|
||||
</form>
|
||||
<div class="keywords">
|
||||
<a href="blog.html">Travel</a>
|
||||
<a href="blog.html">Luxury Hotel</a>
|
||||
<a href="blog.html">Indonesia</a>
|
||||
<a href="blog.html">Sea Beach</a>
|
||||
<a href="blog.html">Camping</a>
|
||||
<a href="blog.html">Hiking</a>
|
||||
<a href="blog.html">Fishing</a>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-5 col-lg-6">
|
||||
<div class="error-images" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
|
||||
<img src="assets/images/404/lost.jpg" alt="404 Error">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- 404 Error Area end -->
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
293
about.php
@@ -1,3 +1,292 @@
|
||||
<?php include_once('header02.php');
|
||||
?>
|
||||
|
||||
<style>
|
||||
.gallery-slider-active {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
/* spacing between images */
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.gallery-three-item {
|
||||
width: 520px;
|
||||
height: 300px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
background: #f9f9f9;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.gallery-three-item .image {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.gallery-three-item img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
/* ensures aspect ratio while filling container */
|
||||
display: block;
|
||||
}
|
||||
|
||||
</style>
|
||||
<!-- Page Banner Start -->
|
||||
<?php
|
||||
// Redirector file - loads the actual page from src/pages/other/
|
||||
require_once __DIR__ . '/src/pages/other/about.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; ?>');">
|
||||
<!-- Overlay PNG -->
|
||||
<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">About</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">About</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Benefit Area start -->
|
||||
<section class="benefit-area mt-100 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row align-items-center justify-content-between">
|
||||
<div class="col-xl-5 col-lg-6">
|
||||
<div class="mobile-app-content rmb-55" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="section-title counter-text-wrap mb-40">
|
||||
<h2>Welcome to the Four Wheel Drive Club of Southern Africa!</h2>
|
||||
</div>
|
||||
<p style="max-width: 600px; margin: 0 auto;">
|
||||
We're a family-friendly outdoor adventure club passionate about exploring the great outdoors through off-road driving, camping, overlanding, cross-border trips, day trips, and unforgettable events. Whether you're new to 4x4 adventures or a seasoned explorer, our community is all about camaraderie, responsible adventure, and creating lasting memories—on and off the road.
|
||||
</p>
|
||||
<ul class="list-style-two mt-35 mb-30">
|
||||
<li>Overlanding</li>
|
||||
<li>Camping</li>
|
||||
<li>Day Trips</li>
|
||||
<li>4x4 Driver Training</li>
|
||||
<li>Family Events</li>
|
||||
<li>Monthly Open Days</li>
|
||||
<li>Guest Speakers</li>
|
||||
<li>4x4 Driving Track</li>
|
||||
</ul>
|
||||
<!-- <a href="about.html" class="theme-btn style-two">
|
||||
<span data-hover="Explore Guides">Explore Guides</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</a> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="benefit-image-part style-two">
|
||||
<div class="image-one" data-aos="fade-down" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
|
||||
<img src="assets/images/benefit/benefit1.png" alt="Benefit">
|
||||
</div>
|
||||
<div class="image-two" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
|
||||
<img src="assets/images/benefit/benefit2.png" alt="Benefit">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Benefit Area end -->
|
||||
|
||||
<!-- Hotel Area start -->
|
||||
<section class="hotel-area bgc-black py-100 rel z-1">
|
||||
<div class="container-fluid">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-12">
|
||||
<div class="section-title text-white text-center counter-text-wrap mb-70" data-aos="fade-up"
|
||||
data-aos-duration="1500" data-aos-offset="50">
|
||||
<h2>BASE4 Open Days</h2>
|
||||
<p style="max-width: 60%; margin: auto;">Whether you're a member or just curious, everyone's welcome at our monthly open events. Come camp with us, enjoy guest speakers, take your rig for a spin on the 4x4 track, or just relax by the swimming pool. Saturday’s Open Day includes breakfast and lunch for sale, plus braai fires ready to go—just bring your tongs! It’s the perfect way to experience the spirit of the club and connect with fellow adventurers. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gallery-slider-active">
|
||||
<?php
|
||||
$folder = 'assets/images/opendays/';
|
||||
$images = glob($folder . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
|
||||
|
||||
// Shuffle and pick first 5
|
||||
shuffle($images);
|
||||
$selected = array_slice($images, 0, 10);
|
||||
|
||||
foreach ($selected as $image) {
|
||||
echo '<div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="image">
|
||||
<img src="' . $image . '" alt="Gallery">
|
||||
</div>
|
||||
|
||||
</div>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="hotel-more-btn text-center mt-40">
|
||||
<a href="destination2.html" class="theme-btn style-four">
|
||||
<span data-hover="Explore More Hotel">Explore More Hotel</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</a>
|
||||
</div> -->
|
||||
</div>
|
||||
</section>
|
||||
<!-- Hotel Area end -->
|
||||
|
||||
|
||||
<!-- Features Area start -->
|
||||
<section class="features-area pt-100 pb-45 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-xl-6">
|
||||
<div class="features-content-part mb-55" data-aos="fade-left" data-aos-duration="1500"
|
||||
data-aos-offset="50">
|
||||
<div class="section-title mb-20">
|
||||
<h2>Want to get involved?<b>JOIN THE COMMITTEE!</b></h2>
|
||||
<p>Want to be more involved in the adventure? Join our committee and help shape the future of the club! Whether it’s planning epic trips, organizing fun events, or assisting with training, your energy and ideas make all the difference. The club runs on the passion of its members—get stuck in, meet awesome people, and be part of what makes it all happen!</p>
|
||||
<div class="image">
|
||||
<img style="border-radius:10px;" src="assets/images/memories/40.jpg" alt="Hotel">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="row pb-25">
|
||||
<div class="section-title text-center counter-text-wrap mb-70" data-aos="fade-up"
|
||||
data-aos-duration="1500" data-aos-offset="50">
|
||||
<h2>4WDCSA Committee and Other Office Bearers</h2>
|
||||
<div>
|
||||
<h3>Committee</h3>
|
||||
<li>Chairman - John Runciman</li>
|
||||
<li>National Liaison - Peter Hutchison</li>
|
||||
<li>Treasurer - Doug Timm</li>
|
||||
<li>Outings - John Runciman</li>
|
||||
<li>Events - Noelene Runciman</li>
|
||||
<li>Driver Training - John Runciman</li>
|
||||
<li>Digital Media - Christopher Pinto</li>
|
||||
|
||||
</div>
|
||||
<div class="pt-30 pb-20">
|
||||
<h3>Administration</h3>
|
||||
<li>Secretary - Jacqui Boshoff</li>
|
||||
|
||||
</div>
|
||||
<p style="font-size:0.8rem;">
|
||||
All portfolio holders/committee members of the 4WDCSA are volunteers and are not paid for their services.<br>The secretary is paid for administrative duties only.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Features Area end -->
|
||||
|
||||
|
||||
<!-- Hotel Area start -->
|
||||
<section class="hotel-area bgc-black py-100 rel z-1">
|
||||
<div class="container-fluid">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-12">
|
||||
<div class="section-title text-white text-center counter-text-wrap mb-70" data-aos="fade-up"
|
||||
data-aos-duration="1500" data-aos-offset="50">
|
||||
<h2>4x4 Memories</h2>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gallery-slider-active"><?php
|
||||
$folder = 'assets/images/memories/';
|
||||
$images = glob($folder . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
|
||||
|
||||
// Shuffle and pick first 5
|
||||
shuffle($images);
|
||||
$selected = array_slice($images, 0, 20);
|
||||
|
||||
foreach ($selected as $image) {
|
||||
echo '<div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="image">
|
||||
<img src="' . $image . '" alt="Gallery">
|
||||
</div>
|
||||
|
||||
</div>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="hotel-more-btn text-center mt-40">
|
||||
<a href="destination2.html" class="theme-btn style-four">
|
||||
<span data-hover="Explore More Hotel">Explore More Hotel</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</a>
|
||||
</div> -->
|
||||
</div>
|
||||
</section>
|
||||
<!-- Hotel Area end -->
|
||||
|
||||
<!-- CTA Area start -->
|
||||
<section class="cta-area pt-100 rel z-1">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-xl-4 col-md-6" data-aos="zoom-in-down" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="cta-item" style="background-image: url(assets/images/trips/1_01.jpg);">
|
||||
<span class="category">Extended Trips</span>
|
||||
<h2>Come and Explore Africa and beyond</h2>
|
||||
<a href="trips.php" class="theme-btn style-two bgc-secondary">
|
||||
<span data-hover="Explore Tours">Explore Trips</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-6" data-aos="zoom-in-down" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="cta-item" style="background-image: url(assets/images/courses/driver_training.png);">
|
||||
<span class="category">Driver Training</span>
|
||||
<h2>Level up your 4x4 Driving Skills</h2>
|
||||
<a href="driver_training.php" class="theme-btn style-two">
|
||||
<span data-hover="Explore Tours">Explore Training</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-6" data-aos="zoom-in-down" data-aos-delay="100" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="cta-item" style="background-image: url(assets/images/base4/camping.jpg);">
|
||||
<span class="category">Events</span>
|
||||
<h2>See whats cooking at BASE4!</h2>
|
||||
<a href="events.php" class="theme-btn style-two bgc-secondary">
|
||||
<span data-hover="Explore Tours">Explore Events</span>
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- CTA Area end -->
|
||||
|
||||
|
||||
<!-- Blog Area start -->
|
||||
<section class="blog-area pt-70 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Blog Area end -->
|
||||
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,247 +1,246 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
include_once(dirname(dirname(dirname(__DIR__))) . '/header.php');
|
||||
|
||||
// Assuming you have the user ID stored in the session
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
// Fetch user data from the database
|
||||
|
||||
$sql = "SELECT * FROM users WHERE user_id = ?";
|
||||
$stmt = $conn->prepare($sql);
|
||||
$stmt->bind_param("i", $user_id);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$user = $result->fetch_assoc();
|
||||
?>
|
||||
|
||||
<style>
|
||||
.profile-picture:hover .edit-icon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.profile-picture {
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.profile-pic-display {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-icon i {
|
||||
color: white;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<!-- Account Settings Area start -->
|
||||
<section class="account-settings-area py-70 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-12">
|
||||
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
|
||||
<form id="accountForm" name="accountForm" method="post" action="update_user">
|
||||
<div class="section-title py-20">
|
||||
<h2>Account Settings</h2>
|
||||
<div id="responseMessage"></div> <!-- Message display area -->
|
||||
</div>
|
||||
|
||||
<!-- Display Profile Picture -->
|
||||
<div class="profile-picture" style="position: relative; width: 150px; height: 150px; margin: 0 auto;">
|
||||
<img id="profile-pic" src="<?php echo $user['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic-display"
|
||||
style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">
|
||||
<button type="button" id="uploadPictureBtn" class="edit-icon">
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
</button>
|
||||
<input type="file" id="profile_picture" name="profile_picture" accept="image/*" style="display:none;">
|
||||
</div>
|
||||
|
||||
<!-- Form Fields -->
|
||||
<div class="row mt-35">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="first_name">First Name</label>
|
||||
<input type="text" id="first_name" name="first_name" class="form-control" value="<?php echo $user['first_name']; ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="last_name">Last Name</label>
|
||||
<input type="text" id="last_name" name="last_name" class="form-control" value="<?php echo $user['last_name']; ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="phone_number">Phone Number</label>
|
||||
<input type="text" id="phone_number" name="phone_number" class="form-control" value="<?php echo $user['phone_number']; ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="email">Email Address</label>
|
||||
<input type="email" id="email" name="email" class="form-control" value="<?php echo $user['email']; ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group mb-0">
|
||||
<button type="submit" class="theme-btn style-two" style="width:100%;">Update Info</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<?php if (getUserType($user_id) !== 'google'){?>
|
||||
|
||||
|
||||
<!-- Change Password Form -->
|
||||
<form id="changePasswordForm" name="changePasswordForm" action="change_password" method="post">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
|
||||
<div class="col-md-12 mt-20">
|
||||
<h4>Change Password</h4>
|
||||
<div id="responseMessage2"></div> <!-- Message display area -->
|
||||
<div class="form-group">
|
||||
<label for="current_password">Current Password</label>
|
||||
<input type="password" id="current_password" name="current_password" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new_password">New Password</label>
|
||||
<input type="password" id="new_password" name="new_password" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="confirm_password">Confirm New Password</label>
|
||||
<input type="password" id="confirm_password" name="confirm_password" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<button type="submit" class="theme-btn style-two" style="width:100%;">Change Password</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<?php }?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Account Settings Area end -->
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Clear the responseMessage when the user changes any form input
|
||||
$('#accountForm input, #changePasswordForm input').on('input', function() {
|
||||
$('#responseMessage').html(''); // Clear the message
|
||||
$('#responseMessage2').html(''); // Clear the message
|
||||
});
|
||||
// Profile Picture Upload
|
||||
$('#uploadPictureBtn').click(function() {
|
||||
$('#profile_picture').click();
|
||||
});
|
||||
|
||||
$('#profile_picture').on('change', function() {
|
||||
var formData = new FormData();
|
||||
formData.append('profile_picture', $('#profile_picture')[0].files[0]);
|
||||
|
||||
$.ajax({
|
||||
url: 'upload_profile_picture',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
if (response.status === 'success') {
|
||||
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
|
||||
// Reload the current page after a short delay
|
||||
setTimeout(function() {
|
||||
window.location.reload();
|
||||
}, 1500);
|
||||
} else {
|
||||
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.log('AJAX Error:', status, error);
|
||||
console.log('Response Text:', xhr.responseText);
|
||||
$('#responseMessage').html('<div class="alert alert-danger">Error uploading profile picture: ' + error + '</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Account Info Update
|
||||
$('#accountForm').on('submit', function(event) {
|
||||
event.preventDefault(); // Prevent default form submission
|
||||
|
||||
$.ajax({
|
||||
url: 'update_user',
|
||||
type: 'POST',
|
||||
data: $(this).serialize(),
|
||||
success: function(response) {
|
||||
// Parse response if needed
|
||||
if (typeof response === "string") {
|
||||
response = JSON.parse(response);
|
||||
}
|
||||
|
||||
if (response.status === 'success') {
|
||||
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
|
||||
} else {
|
||||
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#responseMessage').html('<div class="alert alert-danger">Error updating information.</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Change Password
|
||||
$('#changePasswordForm').on('submit', function(event) {
|
||||
event.preventDefault(); // Prevent default form submission
|
||||
|
||||
$.ajax({
|
||||
url: 'change_password',
|
||||
type: 'POST',
|
||||
data: $(this).serialize(),
|
||||
success: function(response) {
|
||||
// Parse response if needed
|
||||
if (typeof response === "string") {
|
||||
response = JSON.parse(response);
|
||||
}
|
||||
|
||||
if (response.status === 'success') {
|
||||
$('#responseMessage2').html('<div class="alert alert-success">' + response.message + '</div>');
|
||||
} else {
|
||||
$('#responseMessage2').html('<div class="alert alert-danger">' + response.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#responseMessage2').html('<div class="alert alert-danger">Error changing password.</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>
|
||||
<?php
|
||||
include_once('header02.php');
|
||||
|
||||
// Assuming you have the user ID stored in the session
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
// Fetch user data from the database
|
||||
|
||||
$sql = "SELECT * FROM users WHERE user_id = ?";
|
||||
$stmt = $conn->prepare($sql);
|
||||
$stmt->bind_param("i", $user_id);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$user = $result->fetch_assoc();
|
||||
?>
|
||||
|
||||
<style>
|
||||
.profile-picture:hover .edit-icon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.profile-picture {
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.profile-pic-display {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-icon i {
|
||||
color: white;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<!-- Account Settings Area start -->
|
||||
<section class="account-settings-area py-70 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-12">
|
||||
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
|
||||
<form id="accountForm" name="accountForm" method="post" action="update_user.php">
|
||||
<div class="section-title py-20">
|
||||
<h2>Account Settings</h2>
|
||||
<div id="responseMessage"></div> <!-- Message display area -->
|
||||
</div>
|
||||
|
||||
<!-- Display Profile Picture -->
|
||||
<div class="profile-picture" style="position: relative; width: 150px; height: 150px; margin: 0 auto;">
|
||||
<img id="profile-pic" src="<?php echo $user['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic-display"
|
||||
style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">
|
||||
<button type="button" id="uploadPictureBtn" class="edit-icon">
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
</button>
|
||||
<input type="file" id="profile_picture" name="profile_picture" accept="image/*" style="display:none;">
|
||||
</div>
|
||||
|
||||
<!-- Form Fields -->
|
||||
<div class="row mt-35">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="first_name">First Name</label>
|
||||
<input type="text" id="first_name" name="first_name" class="form-control" value="<?php echo $user['first_name']; ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="last_name">Last Name</label>
|
||||
<input type="text" id="last_name" name="last_name" class="form-control" value="<?php echo $user['last_name']; ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="phone_number">Phone Number</label>
|
||||
<input type="text" id="phone_number" name="phone_number" class="form-control" value="<?php echo $user['phone_number']; ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="email">Email Address</label>
|
||||
<input type="email" id="email" name="email" class="form-control" value="<?php echo $user['email']; ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group mb-0">
|
||||
<button type="submit" class="theme-btn style-two" style="width:100%;">Update Info</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<?php if (getUserType($user_id) !== 'google'){?>
|
||||
|
||||
|
||||
<!-- Change Password Form -->
|
||||
<form id="changePasswordForm" name="changePasswordForm" action="change_password.php" method="post">
|
||||
<div class="col-md-12 mt-20">
|
||||
<h4>Change Password</h4>
|
||||
<div id="responseMessage2"></div> <!-- Message display area -->
|
||||
<div class="form-group">
|
||||
<label for="current_password">Current Password</label>
|
||||
<input type="password" id="current_password" name="current_password" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new_password">New Password</label>
|
||||
<input type="password" id="new_password" name="new_password" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="confirm_password">Confirm New Password</label>
|
||||
<input type="password" id="confirm_password" name="confirm_password" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<button type="submit" class="theme-btn style-two" style="width:100%;">Change Password</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<?php }?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Account Settings Area end -->
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Clear the responseMessage when the user changes any form input
|
||||
$('#accountForm input, #changePasswordForm input').on('input', function() {
|
||||
$('#responseMessage').html(''); // Clear the message
|
||||
$('#responseMessage2').html(''); // Clear the message
|
||||
});
|
||||
// Profile Picture Upload
|
||||
$('#uploadPictureBtn').click(function() {
|
||||
$('#profile_picture').click();
|
||||
});
|
||||
|
||||
$('#profile_picture').on('change', function() {
|
||||
var formData = new FormData();
|
||||
formData.append('profile_picture', $('#profile_picture')[0].files[0]);
|
||||
|
||||
$.ajax({
|
||||
url: 'upload_profile_picture.php',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function(response) {
|
||||
// Parse response if needed
|
||||
if (typeof response === "string") {
|
||||
response = JSON.parse(response);
|
||||
}
|
||||
|
||||
if (response.status === 'success') {
|
||||
// Update the profile picture source with cache-busting query string
|
||||
// Reload the current page
|
||||
window.location.reload();
|
||||
|
||||
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
|
||||
} else {
|
||||
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#responseMessage').html('<div class="alert alert-danger">Error uploading profile picture.</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Account Info Update
|
||||
$('#accountForm').on('submit', function(event) {
|
||||
event.preventDefault(); // Prevent default form submission
|
||||
|
||||
$.ajax({
|
||||
url: 'update_user.php',
|
||||
type: 'POST',
|
||||
data: $(this).serialize(),
|
||||
success: function(response) {
|
||||
// Parse response if needed
|
||||
if (typeof response === "string") {
|
||||
response = JSON.parse(response);
|
||||
}
|
||||
|
||||
if (response.status === 'success') {
|
||||
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
|
||||
} else {
|
||||
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#responseMessage').html('<div class="alert alert-danger">Error updating information.</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Change Password
|
||||
$('#changePasswordForm').on('submit', function(event) {
|
||||
event.preventDefault(); // Prevent default form submission
|
||||
|
||||
$.ajax({
|
||||
url: 'change_password.php',
|
||||
type: 'POST',
|
||||
data: $(this).serialize(),
|
||||
success: function(response) {
|
||||
// Parse response if needed
|
||||
if (typeof response === "string") {
|
||||
response = JSON.parse(response);
|
||||
}
|
||||
|
||||
if (response.status === 'success') {
|
||||
$('#responseMessage2').html('<div class="alert alert-success">' + response.message + '</div>');
|
||||
} else {
|
||||
$('#responseMessage2').html('<div class="alert alert-danger">' + response.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#responseMessage2').html('<div class="alert alert-danger">Error changing password.</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,29 +1,29 @@
|
||||
|
||||
<div style="padding-left:15px; padding-right:15px;" id="advertisingCarousel" class="carousel slide" data-bs-ride="carousel" data-bs-interval="5000">
|
||||
<div style="border-radius:20px;" class="carousel-inner">
|
||||
<?php
|
||||
$dir = 'assets/images/advertising/';
|
||||
$images = glob($dir . '*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE);
|
||||
foreach ($images as $index => $img) {
|
||||
$active = $index === 0 ? 'active' : '';
|
||||
echo "<div class='carousel-item $active'>
|
||||
<img src='$img' class='d-block w-100' style='height:394px; object-fit:cover;' alt='Ad $index'>
|
||||
</div>";
|
||||
}
|
||||
?>
|
||||
<a class="carousel-control-prev" href="#advertisingCarousel" role="button" data-bs-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</a>
|
||||
<a class="carousel-control-next" href="#advertisingCarousel" role="button" data-bs-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Next</span>
|
||||
</a>
|
||||
<div class="carousel-indicators">
|
||||
<?php foreach ($images as $i => $_): ?>
|
||||
<button type="button" data-bs-target="#advertisingCarousel" data-bs-slide-to="<?= $i ?>" class="<?= $i === 0 ? 'active' : '' ?>" aria-current="<?= $i === 0 ? 'true' : 'false' ?>" aria-label="Slide <?= $i + 1 ?>"></button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style="padding-left:15px; padding-right:15px;" id="advertisingCarousel" class="carousel slide" data-bs-ride="carousel" data-bs-interval="5000">
|
||||
<div style="border-radius:20px;" class="carousel-inner">
|
||||
<?php
|
||||
$dir = 'assets/images/advertising/';
|
||||
$images = glob($dir . '*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE);
|
||||
foreach ($images as $index => $img) {
|
||||
$active = $index === 0 ? 'active' : '';
|
||||
echo "<div class='carousel-item $active'>
|
||||
<img src='$img' class='d-block w-100' style='height:394px; object-fit:cover;' alt='Ad $index'>
|
||||
</div>";
|
||||
}
|
||||
?>
|
||||
<a class="carousel-control-prev" href="#advertisingCarousel" role="button" data-bs-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</a>
|
||||
<a class="carousel-control-next" href="#advertisingCarousel" role="button" data-bs-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Next</span>
|
||||
</a>
|
||||
<div class="carousel-indicators">
|
||||
<?php foreach ($images as $i => $_): ?>
|
||||
<button type="button" data-bs-target="#advertisingCarousel" data-bs-slide-to="<?= $i ?>" class="<?= $i === 0 ? 'active' : '' ?>" aria-current="<?= $i === 0 ? 'true' : 'false' ?>" aria-label="Slide <?= $i + 1 ?>"></button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
55
add_campsite.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php include_once('connection.php');
|
||||
include_once('functions.php');
|
||||
require_once("env.php");
|
||||
session_start();
|
||||
$user_id = $_SESSION['user_id']; // assuming you're storing it like this
|
||||
|
||||
// campsites.php
|
||||
$conn = openDatabaseConnection();
|
||||
|
||||
// Get text inputs
|
||||
$name = $_POST['name'];
|
||||
$desc = $_POST['description'];
|
||||
$lat = $_POST['latitude'];
|
||||
$lng = $_POST['longitude'];
|
||||
$website = $_POST['website'];
|
||||
$telephone = $_POST['telephone'];
|
||||
|
||||
// Handle file upload
|
||||
$thumbnailPath = null;
|
||||
if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] == 0) {
|
||||
$uploadDir = "assets/uploads/campsites/";
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
$filename = time() . "_" . basename($_FILES["thumbnail"]["name"]);
|
||||
$targetFile = $uploadDir . $filename;
|
||||
|
||||
if (move_uploaded_file($_FILES["thumbnail"]["tmp_name"], $targetFile)) {
|
||||
$thumbnailPath = $targetFile;
|
||||
}
|
||||
}
|
||||
|
||||
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
|
||||
|
||||
if ($id > 0) {
|
||||
// UPDATE
|
||||
if ($thumbnailPath) {
|
||||
$stmt = $conn->prepare("UPDATE campsites SET name=?, description=?, latitude=?, longitude=?, website=?, telephone=?, thumbnail=? WHERE id=?");
|
||||
$stmt->bind_param("ssddsssi", $name, $desc, $lat, $lng, $website, $telephone, $thumbnailPath, $id);
|
||||
} else {
|
||||
$stmt = $conn->prepare("UPDATE campsites SET name=?, description=?, latitude=?, longitude=?, website=?, telephone=? WHERE id=?");
|
||||
$stmt->bind_param("ssddssi", $name, $desc, $lat, $lng, $website, $telephone, $id);
|
||||
}
|
||||
} else {
|
||||
// INSERT
|
||||
$stmt = $conn->prepare("INSERT INTO campsites (name, description, latitude, longitude, website, telephone, thumbnail, user_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("ssddsssi", $name, $desc, $lat, $lng, $website, $telephone, $thumbnailPath, $user_id);
|
||||
|
||||
}
|
||||
$stmt->execute();
|
||||
|
||||
header("Location: campsites.php");
|
||||
?>
|
||||
@@ -1,36 +1,36 @@
|
||||
|
||||
<?php
|
||||
session_start();
|
||||
require_once("env.php");
|
||||
require_once("connection.php");
|
||||
|
||||
if (isset($_POST['tab_id']) && isset($_POST['item_id']) && isset($_POST['item_name']) && isset($_POST['item_price'])) {
|
||||
$tab_id = mysqli_real_escape_string($conn, $_POST['tab_id']);
|
||||
$item_id = mysqli_real_escape_string($conn, $_POST['item_id']);
|
||||
$item_name = mysqli_real_escape_string($conn, $_POST['item_name']);
|
||||
$item_price = mysqli_real_escape_string($conn, $_POST['item_price']);
|
||||
$user_id = mysqli_real_escape_string($conn, $_POST['user_id']);
|
||||
|
||||
// Initialize cart session if not set
|
||||
if (!isset($_SESSION['cart'])) {
|
||||
$_SESSION['cart'] = [];
|
||||
}
|
||||
|
||||
// Add the drink to the cart for the given tab
|
||||
if (!isset($_SESSION['cart'][$tab_id])) {
|
||||
$_SESSION['cart'][$tab_id] = [];
|
||||
}
|
||||
|
||||
// Add the drink as an associative array
|
||||
$_SESSION['cart'][$tab_id][] = [
|
||||
'item_id' => $item_id,
|
||||
'item_name' => $item_name,
|
||||
'item_price' => $item_price,
|
||||
'user_id' => $user_id
|
||||
];
|
||||
|
||||
echo json_encode(['status' => 'success', 'cart' => $_SESSION['cart']]);
|
||||
} else {
|
||||
echo json_encode(['status' => 'error', 'message' => 'Missing required parameters.']);
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
session_start();
|
||||
require_once("env.php");
|
||||
require_once("connection.php");
|
||||
|
||||
if (isset($_POST['tab_id']) && isset($_POST['item_id']) && isset($_POST['item_name']) && isset($_POST['item_price'])) {
|
||||
$tab_id = mysqli_real_escape_string($conn, $_POST['tab_id']);
|
||||
$item_id = mysqli_real_escape_string($conn, $_POST['item_id']);
|
||||
$item_name = mysqli_real_escape_string($conn, $_POST['item_name']);
|
||||
$item_price = mysqli_real_escape_string($conn, $_POST['item_price']);
|
||||
$user_id = mysqli_real_escape_string($conn, $_POST['user_id']);
|
||||
|
||||
// Initialize cart session if not set
|
||||
if (!isset($_SESSION['cart'])) {
|
||||
$_SESSION['cart'] = [];
|
||||
}
|
||||
|
||||
// Add the drink to the cart for the given tab
|
||||
if (!isset($_SESSION['cart'][$tab_id])) {
|
||||
$_SESSION['cart'][$tab_id] = [];
|
||||
}
|
||||
|
||||
// Add the drink as an associative array
|
||||
$_SESSION['cart'][$tab_id][] = [
|
||||
'item_id' => $item_id,
|
||||
'item_name' => $item_name,
|
||||
'item_price' => $item_price,
|
||||
'user_id' => $user_id
|
||||
];
|
||||
|
||||
echo json_encode(['status' => 'success', 'cart' => $_SESSION['cart']]);
|
||||
} else {
|
||||
echo json_encode(['status' => 'error', 'message' => 'Missing required parameters.']);
|
||||
}
|
||||
?>
|
||||
144
admin_blogs.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php include_once('header02.php');
|
||||
checkAdmin();
|
||||
checkUserSession();
|
||||
|
||||
$result = $conn->prepare("
|
||||
SELECT
|
||||
b.blog_id,
|
||||
b.title,
|
||||
b.description,
|
||||
b.status,
|
||||
b.date,
|
||||
b.image,
|
||||
CONCAT(u.first_name, ' ', u.last_name) AS author_name,
|
||||
u.email AS author_email,
|
||||
u.profile_pic
|
||||
FROM blogs b
|
||||
JOIN users u ON b.author = u.user_id
|
||||
WHERE b.status != 'deleted'
|
||||
ORDER BY b.date DESC
|
||||
");
|
||||
|
||||
$result->execute();
|
||||
$posts = $result->get_result();
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<style>
|
||||
.image {
|
||||
width: 400px;
|
||||
/* Set your desired width */
|
||||
height: 350px;
|
||||
/* Set your desired height */
|
||||
overflow: hidden;
|
||||
/* Hide any overflow */
|
||||
display: block;
|
||||
/* Ensure proper block behavior */
|
||||
}
|
||||
|
||||
.image img {
|
||||
width: 100%;
|
||||
/* Image scales to fill the container */
|
||||
height: 100%;
|
||||
/* Image scales to fill the container */
|
||||
object-fit: cover;
|
||||
/* Fills the container while maintaining aspect ratio */
|
||||
object-position: top;
|
||||
/* Aligns the top of the image with the top of the container */
|
||||
display: block;
|
||||
/* Prevents inline whitespace issues */
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<?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; ?>');">
|
||||
<!-- Overlay PNG -->
|
||||
<div class="banner-overlay"></div>
|
||||
<div class="container">
|
||||
<div class="banner-inner text-white">
|
||||
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">Admin Blogs</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">Admin Blogs</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Page Banner End -->
|
||||
|
||||
|
||||
|
||||
<!-- Blog List Area start -->
|
||||
<section class="blog-list-page py-100 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
|
||||
<h2>My Posts</h2>
|
||||
<?php if (isset($_SESSION['message'])): ?>
|
||||
<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']); ?>
|
||||
<?php endif; ?>
|
||||
<a href="blog_create.php">+ New Post</a>
|
||||
|
||||
<?php while ($post = $posts->fetch_assoc()):
|
||||
// Output the HTML structure with dynamic data
|
||||
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:200px;height:200px;">
|
||||
<img src="' . $post["image"] . '" alt="' . $post["title"] . '">
|
||||
</div>
|
||||
<div class="content" style="width:100%;">
|
||||
<div class="destination-header d-flex align-items-start gap-3">
|
||||
<img src="' . $post["profile_pic"] . '" alt="Author" class="rounded-circle border" width="80" height="80">
|
||||
<div>
|
||||
<span class="badge bg-dark mb-1">' . strtoupper($post["status"]) . '</span>
|
||||
<h5 class="mb-0">' . $post["title"] . '</h5>
|
||||
<small class="text-muted">' . $post["author_name"] . '</small>
|
||||
</div>
|
||||
</div>
|
||||
<p>' . $post["description"] . '</p>
|
||||
<div class="destination-footer">
|
||||
<div class="btn-group" style="display:flex; justify-content:flex-end; gap:10px; margin-top:10px;">
|
||||
<a href="blog_edit.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Edit"><i class="bi bi-pencil"></i></a>
|
||||
<a href="blog_read.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Preview"><i class="bi bi-eye"></i></a>
|
||||
<a href="blog_delete.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Delete"><i class="bi bi-trash"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
endwhile; ?>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Blog List Area end -->
|
||||
<script>
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||
tooltipTriggerList.forEach(el => new bootstrap.Tooltip(el));
|
||||
</script>
|
||||
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,227 +1,224 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(__DIR__));
|
||||
include_once($rootPath . '/header.php');
|
||||
checkAdmin();
|
||||
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.trip-booking {
|
||||
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
|
||||
$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">4WDCSA Camping Bookings</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">Camping Bookings</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<?php
|
||||
|
||||
echo "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
|
||||
echo "<div style='padding:10px;'>";
|
||||
echo "<h4>BASE4 Camping</h4>";
|
||||
|
||||
// Fetch bookings for the current trip
|
||||
$bookingsSql = "SELECT b.user_id, b.from_date, b.to_date, b.num_vehicles, b.num_adults, b.num_children, b.add_firewood, b.status,
|
||||
u.first_name, u.last_name,
|
||||
(b.total_amount - b.discount_amount) AS paid
|
||||
FROM bookings b
|
||||
INNER JOIN users u ON b.user_id = u.user_id
|
||||
WHERE b.booking_type = 'camping'";
|
||||
$stmt = $conn->prepare($bookingsSql);
|
||||
$stmt->execute();
|
||||
$bookingsResult = $stmt->get_result();
|
||||
|
||||
if ($bookingsResult->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>From</th>
|
||||
<th>To</th>
|
||||
<th>Vehicles</th>
|
||||
<th>Adults</th>
|
||||
<th>Children</th>
|
||||
<th>Add Firewood</th>
|
||||
<th>Status</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($booking = $bookingsResult->fetch_assoc()) {
|
||||
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
|
||||
$numVehicles = htmlspecialchars($booking['num_vehicles']);
|
||||
$from = htmlspecialchars($booking['from_date']);
|
||||
$to = htmlspecialchars($booking['to_date']);
|
||||
$numAdults = htmlspecialchars($booking['num_adults']);
|
||||
$numChildren = htmlspecialchars($booking['num_children']);
|
||||
$radio = $booking['add_firewood'] == 1 ? "YES" : "NO";
|
||||
$status = htmlspecialchars($booking['status']);
|
||||
$paid = "R " . number_format($booking['paid'], 2);
|
||||
|
||||
echo "<tr>
|
||||
<td>{$userName}</td>
|
||||
<td>{$from}</td>
|
||||
<td>{$to}</td>
|
||||
<td>{$numVehicles}</td>
|
||||
<td>{$numAdults}</td>
|
||||
<td>{$numChildren}</td>
|
||||
<td>{$radio}</td>
|
||||
<td>{$status}</td>
|
||||
<td>{$paid}</td>
|
||||
</tr>";
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
} else {
|
||||
echo '<p>No bookings found for this trip.</p>';
|
||||
}
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
checkAdmin();
|
||||
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.trip-booking {
|
||||
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
|
||||
$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">4WDCSA Camping Bookings</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">Camping Bookings</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<?php
|
||||
|
||||
echo "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
|
||||
echo "<div style='padding:10px;'>";
|
||||
echo "<h4>BASE4 Camping</h4>";
|
||||
|
||||
// Fetch bookings for the current trip
|
||||
$bookingsSql = "SELECT b.user_id, b.from_date, b.to_date, b.num_vehicles, b.num_adults, b.num_children, b.add_firewood, b.status,
|
||||
u.first_name, u.last_name,
|
||||
(b.total_amount - b.discount_amount) AS paid
|
||||
FROM bookings b
|
||||
INNER JOIN users u ON b.user_id = u.user_id
|
||||
WHERE b.booking_type = 'camping'";
|
||||
$stmt = $conn->prepare($bookingsSql);
|
||||
$stmt->execute();
|
||||
$bookingsResult = $stmt->get_result();
|
||||
|
||||
if ($bookingsResult->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>From</th>
|
||||
<th>To</th>
|
||||
<th>Vehicles</th>
|
||||
<th>Adults</th>
|
||||
<th>Children</th>
|
||||
<th>Add Firewood</th>
|
||||
<th>Status</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($booking = $bookingsResult->fetch_assoc()) {
|
||||
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
|
||||
$numVehicles = htmlspecialchars($booking['num_vehicles']);
|
||||
$from = htmlspecialchars($booking['from_date']);
|
||||
$to = htmlspecialchars($booking['to_date']);
|
||||
$numAdults = htmlspecialchars($booking['num_adults']);
|
||||
$numChildren = htmlspecialchars($booking['num_children']);
|
||||
$radio = $booking['add_firewood'] == 1 ? "YES" : "NO";
|
||||
$status = htmlspecialchars($booking['status']);
|
||||
$paid = "R " . number_format($booking['paid'], 2);
|
||||
|
||||
echo "<tr>
|
||||
<td>{$userName}</td>
|
||||
<td>{$from}</td>
|
||||
<td>{$to}</td>
|
||||
<td>{$numVehicles}</td>
|
||||
<td>{$numAdults}</td>
|
||||
<td>{$numChildren}</td>
|
||||
<td>{$radio}</td>
|
||||
<td>{$status}</td>
|
||||
<td>{$paid}</td>
|
||||
</tr>";
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
} else {
|
||||
echo '<p>No bookings found for this trip.</p>';
|
||||
}
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,247 +1,244 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(__DIR__));
|
||||
include_once($rootPath . '/header.php');
|
||||
checkAdmin();
|
||||
|
||||
// Fetch all trips
|
||||
$courseSql = "SELECT date, course_id, course_type FROM courses";
|
||||
|
||||
$courseResult = $conn->query($courseSql);
|
||||
if (!$courseResult) {
|
||||
echo "Error in SQL query: " . $conn->error;
|
||||
}
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.trip-booking {
|
||||
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
|
||||
$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">4WDCSA Course Bookings</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">Course Bookings</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<?php
|
||||
if ($courseResult->num_rows > 0) {
|
||||
while ($course = $courseResult->fetch_assoc()) {
|
||||
$course_id = $course['course_id'];
|
||||
$date = $course['date'];
|
||||
$type = htmlspecialchars($course['course_type']);
|
||||
if ($type === "driver_training") {
|
||||
$course_name = "Basic 4X4 Driver Training Course ".$date;
|
||||
} elseif ($type === "bush_mechanics") {
|
||||
$course_name = "Bush Mechanics Course ".$date;
|
||||
} elseif ($type === "rescue_recovery") {
|
||||
$course_name = "Rescue & Recovery Training Course ".$date;
|
||||
} else {
|
||||
$course_name = "General Course ".$date; // Default fallback description
|
||||
}
|
||||
|
||||
echo "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
|
||||
echo "<div style='padding:10px;'>";
|
||||
echo "<h4>{$course_name}</h4>";
|
||||
|
||||
// Fetch bookings for the current trip
|
||||
$bookingsSql = "SELECT b.user_id, b.num_adults, b.total_amount, b.status, b.course_non_members,
|
||||
u.first_name, u.last_name, u.profile_pic
|
||||
FROM bookings b
|
||||
INNER JOIN users u ON b.user_id = u.user_id
|
||||
WHERE b.course_id = ?";
|
||||
if ($stmt = $conn->prepare($bookingsSql)) {
|
||||
$stmt->bind_param('i', $course_id);
|
||||
$stmt->execute();
|
||||
$bookingsResult = $stmt->get_result();
|
||||
} else {
|
||||
echo "Error in prepared statement: " . $conn->error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($bookingsResult->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Name</th>
|
||||
<th>Members</th>
|
||||
<th>Non-Members</th>
|
||||
<th>Status</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($booking = $bookingsResult->fetch_assoc()) {
|
||||
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
|
||||
$members = htmlspecialchars($booking['num_adults']);
|
||||
$non_members = htmlspecialchars($booking['course_non_members']);
|
||||
$status = htmlspecialchars($booking['status']);
|
||||
$paid = "R " . number_format($booking['total_amount'], 2);
|
||||
|
||||
echo "<tr>
|
||||
<td><img src=".$booking['profile_pic']." alt='Profile Picture' class='profile-pic'></td>
|
||||
<td>{$userName}</td>
|
||||
<td>{$members}</td>
|
||||
<td>{$non_members}</td>
|
||||
<td>{$status}</td>
|
||||
<td>{$paid}</td>
|
||||
</tr>";
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
} else {
|
||||
echo '<p>No bookings found for this trip.</p>';
|
||||
}
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
}
|
||||
} else {
|
||||
echo '<p>No courses found.</p>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
checkAdmin();
|
||||
|
||||
// Fetch all trips
|
||||
$courseSql = "SELECT date, course_id, course_type FROM courses WHERE DATE(date) >= CURDATE()";
|
||||
|
||||
$courseResult = $conn->query($courseSql);
|
||||
if (!$courseResult) {
|
||||
echo "Error in SQL query: " . $conn->error;
|
||||
}
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.trip-booking {
|
||||
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
|
||||
$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">4WDCSA Course Bookings</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">Course Bookings</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<?php
|
||||
if ($courseResult->num_rows > 0) {
|
||||
while ($course = $courseResult->fetch_assoc()) {
|
||||
$course_id = $course['course_id'];
|
||||
$date = $course['date'];
|
||||
$type = htmlspecialchars($course['course_type']);
|
||||
if ($type === "driver_training") {
|
||||
$course_name = "Basic 4X4 Driver Training Course ".$date;
|
||||
} elseif ($type === "bush_mechanics") {
|
||||
$course_name = "Bush Mechanics Course ".$date;
|
||||
} elseif ($type === "rescue_recovery") {
|
||||
$course_name = "Rescue & Recovery Training Course ".$date;
|
||||
} else {
|
||||
$course_name = "General Course ".$date; // Default fallback description
|
||||
}
|
||||
|
||||
echo "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
|
||||
echo "<div style='padding:10px;'>";
|
||||
echo "<h4>{$course_name}</h4>";
|
||||
|
||||
// Fetch bookings for the current trip
|
||||
$bookingsSql = "SELECT b.user_id, b.num_adults, b.total_amount, b.status, b.course_non_members,
|
||||
u.first_name, u.last_name, u.profile_pic
|
||||
FROM bookings b
|
||||
INNER JOIN users u ON b.user_id = u.user_id
|
||||
WHERE b.course_id = ?";
|
||||
if ($stmt = $conn->prepare($bookingsSql)) {
|
||||
$stmt->bind_param('i', $course_id);
|
||||
$stmt->execute();
|
||||
$bookingsResult = $stmt->get_result();
|
||||
} else {
|
||||
echo "Error in prepared statement: " . $conn->error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($bookingsResult->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Name</th>
|
||||
<th>Members</th>
|
||||
<th>Non-Members</th>
|
||||
<th>Status</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($booking = $bookingsResult->fetch_assoc()) {
|
||||
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
|
||||
$members = htmlspecialchars($booking['num_adults']);
|
||||
$non_members = htmlspecialchars($booking['course_non_members']);
|
||||
$status = htmlspecialchars($booking['status']);
|
||||
$paid = "R " . number_format($booking['total_amount'], 2);
|
||||
|
||||
echo "<tr>
|
||||
<td><img src=".$booking['profile_pic']." alt='Profile Picture' class='profile-pic'></td>
|
||||
<td>{$userName}</td>
|
||||
<td>{$members}</td>
|
||||
<td>{$non_members}</td>
|
||||
<td>{$status}</td>
|
||||
<td>{$paid}</td>
|
||||
</tr>";
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
} else {
|
||||
echo '<p>No bookings found for this trip.</p>';
|
||||
}
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
}
|
||||
} else {
|
||||
echo '<p>No courses found.</p>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,227 +1,224 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(__DIR__));
|
||||
include_once($rootPath . '/header.php');
|
||||
checkAdmin();
|
||||
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.theme-btn,
|
||||
a.theme-btn {
|
||||
padding: 0px 14px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA EFT Payments</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA EFT Payments</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<?php
|
||||
// Fetch payments
|
||||
$paymentSql = "SELECT b.user_id, b.eft_id, b.amount, b.status, b.timestamp, b.description,
|
||||
u.first_name, u.last_name
|
||||
FROM efts b
|
||||
INNER JOIN users u ON b.user_id = u.user_id";
|
||||
$stmt = $conn->prepare($paymentSql);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Amount</th>
|
||||
<th>Reference</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
// Generate a unique token for this EFT
|
||||
|
||||
echo "<tr>
|
||||
<td>" . htmlspecialchars($row['timestamp']) . "</td>
|
||||
<td>" . htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['description']) . "</td>
|
||||
<td>" . htmlspecialchars($row['amount']) . "</td>
|
||||
<td>" . htmlspecialchars($row['eft_id']) . "</td>";
|
||||
if (($row['status']) == 'AWAITING PAYMENT') {
|
||||
echo "<td><a href='process_eft.php?token=" . encryptData($row['eft_id'], $salt) . "' class='theme-btn style-two style-three'>
|
||||
<span data-hover='PAYMENT RECEIVED'>" . htmlspecialchars($row['status']) . "</span>
|
||||
</a></td></tr>";
|
||||
} elseif (($row['status']) == 'PROCESSING') {
|
||||
echo "<td><a href='process_payments.php' class='theme-btn style-two style-three'>
|
||||
<span data-hover='PROCESS'>PROCESS</span>
|
||||
</a></td></tr>";
|
||||
} else {
|
||||
echo "<td>" . htmlspecialchars($row['status']) . "</td>";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="5">No records found</td></tr>';
|
||||
} ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
|
||||
|
||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
checkAdmin();
|
||||
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.theme-btn,
|
||||
a.theme-btn {
|
||||
padding: 0px 14px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA EFT Payments</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA EFT Payments</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<?php
|
||||
// Fetch payments
|
||||
$paymentSql = "SELECT b.user_id, b.eft_id, b.amount, b.status, b.timestamp, b.description,
|
||||
u.first_name, u.last_name
|
||||
FROM efts b
|
||||
INNER JOIN users u ON b.user_id = u.user_id";
|
||||
$stmt = $conn->prepare($paymentSql);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Amount</th>
|
||||
<th>Reference</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
// Generate a unique token for this EFT
|
||||
|
||||
echo "<tr>
|
||||
<td>" . htmlspecialchars($row['timestamp']) . "</td>
|
||||
<td>" . htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['description']) . "</td>
|
||||
<td>" . htmlspecialchars($row['amount']) . "</td>
|
||||
<td>" . htmlspecialchars($row['eft_id']) . "</td>";
|
||||
if (($row['status']) == 'AWAITING PAYMENT') {
|
||||
echo "<td><a href='process_eft.php?token=" . encryptData($row['eft_id'], $salt) . "' class='theme-btn style-two style-three'>
|
||||
<span data-hover='PAYMENT RECEIVED'>" . htmlspecialchars($row['status']) . "</span>
|
||||
</a></td></tr>";
|
||||
} elseif (($row['status']) == 'PROCESSING') {
|
||||
echo "<td><a href='process_payments.php' class='theme-btn style-two style-three'>
|
||||
<span data-hover='PROCESS'>PROCESS</span>
|
||||
</a></td></tr>";
|
||||
} else {
|
||||
echo "<td>" . htmlspecialchars($row['status']) . "</td>";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="5">No records found</td></tr>';
|
||||
} ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,238 +1,235 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(__DIR__));
|
||||
include_once($rootPath . '/header.php');
|
||||
checkAdmin();
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['accept_indemnity'])) {
|
||||
$user_id = intval($_POST['user_id']);
|
||||
$stmt = $conn->prepare("UPDATE membership_application SET accept_indemnity = 1 WHERE user_id = ?");
|
||||
if ($stmt) {
|
||||
$stmt->bind_param("i", $user_id);
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
}
|
||||
}
|
||||
|
||||
// SQL query to fetch membership applications
|
||||
$stmt = $conn->prepare("SELECT user_id, first_name, last_name, tel_cell, email, dob, accept_indemnity FROM membership_application");
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.theme-btn,
|
||||
a.theme-btn {
|
||||
padding: 0px 14px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA Members</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA Members</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Cell Number</th>
|
||||
<th>Email</th>
|
||||
<th>Date of Birth</th>
|
||||
<th>Membership</th>
|
||||
<th>View Info</th>
|
||||
<th>Indemnity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if ($result->num_rows > 0) {
|
||||
// Output data of each row
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
echo "<tr>
|
||||
<td>" . htmlspecialchars($row['first_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['last_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['tel_cell']) . "</td>
|
||||
<td>" . htmlspecialchars($row['email']) . "</td>
|
||||
<td>" . htmlspecialchars($row['dob']) . "</td>
|
||||
<td>" . (getUserMemberStatus($row['user_id']) ? 'ACTIVE' : 'INACTIVE') . "</td>
|
||||
<td><a href='member_info.php?token=" . encryptData($row['user_id'], $salt) . "' class='theme-btn style-two style-three'><span data-hover='PAYMENT RECEIVED'>View Info</span></a></td>
|
||||
<td>";
|
||||
|
||||
if (!$row['accept_indemnity']) {
|
||||
echo "<form method='POST' style='display:inline;'>
|
||||
<input type='hidden' name='user_id' value='" . $row['user_id'] . "'>
|
||||
<button type='submit' name='accept_indemnity' class='theme-btn small'>Accept</button>
|
||||
</form>";
|
||||
} else {
|
||||
echo "✅ Accepted";
|
||||
}
|
||||
|
||||
echo "</td>
|
||||
</tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="8">No records found</td></tr>';
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
|
||||
|
||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
checkAdmin();
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['accept_indemnity'])) {
|
||||
$user_id = intval($_POST['user_id']);
|
||||
$stmt = $conn->prepare("UPDATE membership_application SET accept_indemnity = 1 WHERE user_id = ?");
|
||||
if ($stmt) {
|
||||
$stmt->bind_param("i", $user_id);
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
}
|
||||
}
|
||||
|
||||
// SQL query to fetch data
|
||||
$sql = "SELECT user_id, first_name, last_name, tel_cell, email, dob, accept_indemnity FROM membership_application";
|
||||
|
||||
$result = $conn->query($sql);
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.theme-btn,
|
||||
a.theme-btn {
|
||||
padding: 0px 14px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA Members</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA Members</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Cell Number</th>
|
||||
<th>Email</th>
|
||||
<th>Date of Birth</th>
|
||||
<th>Membership</th>
|
||||
<th>View Info</th>
|
||||
<th>Indemnity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if ($result->num_rows > 0) {
|
||||
// Output data of each row
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
echo "<tr>
|
||||
<td>" . htmlspecialchars($row['first_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['last_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['tel_cell']) . "</td>
|
||||
<td>" . htmlspecialchars($row['email']) . "</td>
|
||||
<td>" . htmlspecialchars($row['dob']) . "</td>
|
||||
<td>" . (getUserMemberStatus($row['user_id']) ? 'ACTIVE' : 'INACTIVE') . "</td>
|
||||
<td><a href='member_info.php?token=" . encryptData($row['user_id'], $salt) . "' class='theme-btn style-two style-three'><span data-hover='PAYMENT RECEIVED'>View Info</span></a></td>
|
||||
<td>";
|
||||
|
||||
if (!$row['accept_indemnity']) {
|
||||
echo "<form method='POST' style='display:inline;'>
|
||||
<input type='hidden' name='user_id' value='" . $row['user_id'] . "'>
|
||||
<button type='submit' name='accept_indemnity' class='theme-btn small'>Accept</button>
|
||||
</form>";
|
||||
} else {
|
||||
echo "✅ Accepted";
|
||||
}
|
||||
|
||||
echo "</td>
|
||||
</tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="8">No records found</td></tr>';
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,211 +1,208 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(__DIR__));
|
||||
include_once($rootPath . '/header.php');
|
||||
checkAdmin();
|
||||
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA Payments</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA Payments</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<?php
|
||||
// Fetch payments
|
||||
$paymentSql = "SELECT b.user_id, b.payment_id, b.amount, b.status, b.date, b.description,
|
||||
u.first_name, u.last_name
|
||||
FROM payments b
|
||||
INNER JOIN users u ON b.user_id = u.user_id";
|
||||
$stmt = $conn->prepare($paymentSql);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Amount</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
echo "<tr>
|
||||
<td>" . htmlspecialchars($row['date']) . "</td>
|
||||
<td>" . htmlspecialchars($row['payment_id']) . "</td>
|
||||
<td>" . htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['description']) . "</td>
|
||||
<td>" . htmlspecialchars($row['amount']) . "</td>
|
||||
<td>" . htmlspecialchars($row['status']) . "</td>
|
||||
</tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="5">No records found</td></tr>';
|
||||
} ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
|
||||
|
||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
checkAdmin();
|
||||
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA Payments</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA Payments</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<?php
|
||||
// Fetch payments
|
||||
$paymentSql = "SELECT b.user_id, b.payment_id, b.amount, b.status, b.date, b.description,
|
||||
u.first_name, u.last_name
|
||||
FROM payments b
|
||||
INNER JOIN users u ON b.user_id = u.user_id";
|
||||
$stmt = $conn->prepare($paymentSql);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Amount</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
echo "<tr>
|
||||
<td>" . htmlspecialchars($row['date']) . "</td>
|
||||
<td>" . htmlspecialchars($row['payment_id']) . "</td>
|
||||
<td>" . htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['description']) . "</td>
|
||||
<td>" . htmlspecialchars($row['amount']) . "</td>
|
||||
<td>" . htmlspecialchars($row['status']) . "</td>
|
||||
</tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="5">No records found</td></tr>';
|
||||
} ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,240 +1,237 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(__DIR__));
|
||||
include_once($rootPath . '/header.php');
|
||||
checkAdmin();
|
||||
|
||||
// Fetch all trips
|
||||
$tripsSql = "SELECT trip_id, trip_name FROM trips";
|
||||
$tripsResult = $conn->query($tripsSql);
|
||||
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.trip-booking {
|
||||
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
|
||||
$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">4WDCSA Trip Bookings</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">Trip Bookings</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<?php
|
||||
if ($tripsResult->num_rows > 0) {
|
||||
while ($trip = $tripsResult->fetch_assoc()) {
|
||||
$tripId = $trip['trip_id'];
|
||||
$tripName = htmlspecialchars($trip['trip_name']);
|
||||
|
||||
echo "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
|
||||
echo "<div style='padding:10px;'>";
|
||||
echo "<h4>{$tripName}</h4>";
|
||||
|
||||
// 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.profile_pic,
|
||||
(b.total_amount - b.discount_amount) AS paid
|
||||
FROM bookings b
|
||||
INNER JOIN users u ON b.user_id = u.user_id
|
||||
WHERE b.trip_id = ?";
|
||||
$stmt = $conn->prepare($bookingsSql);
|
||||
$stmt->bind_param('i', $tripId);
|
||||
$stmt->execute();
|
||||
$bookingsResult = $stmt->get_result();
|
||||
|
||||
|
||||
if ($bookingsResult->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Name</th>
|
||||
<th>Vehicles</th>
|
||||
<th>Adults</th>
|
||||
<th>Children</th>
|
||||
<th>Pensioners</th>
|
||||
<th>Radio</th>
|
||||
<th>Status</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($booking = $bookingsResult->fetch_assoc()) {
|
||||
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
|
||||
$numVehicles = htmlspecialchars($booking['num_vehicles']);
|
||||
$numAdults = htmlspecialchars($booking['num_adults']);
|
||||
$numPensioners = htmlspecialchars($booking['num_pensioners']);
|
||||
$numChildren = htmlspecialchars($booking['num_children']);
|
||||
$radio = $booking['radio'] == 1 ? "YES" : "NO";
|
||||
$status = htmlspecialchars($booking['status']);
|
||||
$paid = "R " . number_format($booking['paid'], 2);
|
||||
|
||||
echo "<tr>
|
||||
<td><img src=".$booking['profile_pic']." alt='Profile Picture' class='profile-pic'></td>
|
||||
<td>{$userName}</td>
|
||||
<td>{$numVehicles}</td>
|
||||
<td>{$numAdults}</td>
|
||||
<td>{$numChildren}</td>
|
||||
<td>{$numPensioners}</td>
|
||||
<td>{$radio}</td>
|
||||
<td>{$status}</td>
|
||||
<td>{$paid}</td>
|
||||
</tr>";
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
} else {
|
||||
echo '<p>No bookings found for this trip.</p>';
|
||||
}
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
}
|
||||
} else {
|
||||
echo '<p>No trips found.</p>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
checkAdmin();
|
||||
|
||||
// Fetch all trips
|
||||
$tripsSql = "SELECT trip_id, trip_name FROM trips";
|
||||
$tripsResult = $conn->query($tripsSql);
|
||||
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.trip-booking {
|
||||
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
|
||||
$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">4WDCSA Trip Bookings</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">Trip Bookings</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<?php
|
||||
if ($tripsResult->num_rows > 0) {
|
||||
while ($trip = $tripsResult->fetch_assoc()) {
|
||||
$tripId = $trip['trip_id'];
|
||||
$tripName = htmlspecialchars($trip['trip_name']);
|
||||
|
||||
echo "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
|
||||
echo "<div style='padding:10px;'>";
|
||||
echo "<h4>{$tripName}</h4>";
|
||||
|
||||
// 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,
|
||||
(b.total_amount - b.discount_amount) AS paid
|
||||
FROM bookings b
|
||||
INNER JOIN users u ON b.user_id = u.user_id
|
||||
WHERE b.trip_id = ?";
|
||||
$stmt = $conn->prepare($bookingsSql);
|
||||
$stmt->bind_param('i', $tripId);
|
||||
$stmt->execute();
|
||||
$bookingsResult = $stmt->get_result();
|
||||
|
||||
|
||||
if ($bookingsResult->num_rows > 0) {
|
||||
echo '<input type="text" class="filter-input" placeholder="Filter results...">';
|
||||
echo '<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Name</th>
|
||||
<th>Vehicles</th>
|
||||
<th>Adults</th>
|
||||
<th>Children</th>
|
||||
<th>Pensioners</th>
|
||||
<th>Radio</th>
|
||||
<th>Status</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
while ($booking = $bookingsResult->fetch_assoc()) {
|
||||
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
|
||||
$numVehicles = htmlspecialchars($booking['num_vehicles']);
|
||||
$numAdults = htmlspecialchars($booking['num_adults']);
|
||||
$numPensioners = htmlspecialchars($booking['num_pensioners']);
|
||||
$numChildren = htmlspecialchars($booking['num_children']);
|
||||
$radio = $booking['radio'] == 1 ? "YES" : "NO";
|
||||
$status = htmlspecialchars($booking['status']);
|
||||
$paid = "R " . number_format($booking['paid'], 2);
|
||||
|
||||
echo "<tr>
|
||||
<td><img src=".$booking['profile_pic']." alt='Profile Picture' class='profile-pic'></td>
|
||||
<td>{$userName}</td>
|
||||
<td>{$numVehicles}</td>
|
||||
<td>{$numAdults}</td>
|
||||
<td>{$numChildren}</td>
|
||||
<td>{$numPensioners}</td>
|
||||
<td>{$radio}</td>
|
||||
<td>{$status}</td>
|
||||
<td>{$paid}</td>
|
||||
</tr>";
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
} else {
|
||||
echo '<p>No bookings found for this trip.</p>';
|
||||
}
|
||||
echo "</div>";
|
||||
echo "</div>";
|
||||
}
|
||||
} else {
|
||||
echo '<p>No trips found.</p>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,204 +1,201 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(__DIR__));
|
||||
include_once($rootPath . '/header.php');
|
||||
checkAdmin();
|
||||
// SQL query to fetch data
|
||||
$sql = "SELECT ip_address, user_id, page_url, referrer_url, visit_time, country FROM visitor_logs WHERE NOT (ip_address = '185.203.122.69' OR ip_address = '156.155.29.213') ORDER BY visit_time DESC";
|
||||
|
||||
$result = $conn->query($sql);
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA Visitor Logs</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA Visitor Logs</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Country</th>
|
||||
<th>IP Address</th>
|
||||
<th>User ID</th>
|
||||
<th>Page URL</th>
|
||||
<th>Referrer</th>
|
||||
<th>Timestamp</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if ($result->num_rows > 0) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
echo "<tr>
|
||||
<td>" . ($row['country']) . "</td>
|
||||
<td>" . htmlspecialchars($row['ip_address']) . "</td>
|
||||
<td>" . ($row['user_id'] !== null ? htmlspecialchars(getFullName($row['user_id'])) : '-') . "</td>
|
||||
<td>" . htmlspecialchars($row['page_url']) . "</td>
|
||||
<td>" . ($row['referrer_url'] ? htmlspecialchars($row['referrer_url']) : '-') . "</td>
|
||||
<td>" . htmlspecialchars($row['visit_time']) . "</td>
|
||||
</tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="5">No logs found</td></tr>';
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
|
||||
|
||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
checkAdmin();
|
||||
// SQL query to fetch data
|
||||
$sql = "SELECT ip_address, user_id, page_url, referrer_url, visit_time, country FROM visitor_logs WHERE NOT (ip_address = '185.203.122.69' OR ip_address = '156.155.29.213') ORDER BY visit_time DESC";
|
||||
|
||||
$result = $conn->query($sql);
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA Visitor Logs</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA Visitor Logs</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Country</th>
|
||||
<th>IP Address</th>
|
||||
<th>User ID</th>
|
||||
<th>Page URL</th>
|
||||
<th>Referrer</th>
|
||||
<th>Timestamp</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if ($result->num_rows > 0) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
echo "<tr>
|
||||
<td>" . ($row['country']) . "</td>
|
||||
<td>" . htmlspecialchars($row['ip_address']) . "</td>
|
||||
<td>" . ($row['user_id'] !== null ? htmlspecialchars(getFullName($row['user_id'])) : '-') . "</td>
|
||||
<td>" . htmlspecialchars($row['page_url']) . "</td>
|
||||
<td>" . ($row['referrer_url'] ? htmlspecialchars($row['referrer_url']) : '-') . "</td>
|
||||
<td>" . htmlspecialchars($row['visit_time']) . "</td>
|
||||
</tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="5">No logs found</td></tr>';
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,284 +1,281 @@
|
||||
<?php
|
||||
$headerStyle = 'light';
|
||||
$rootPath = dirname(dirname(__DIR__));
|
||||
include_once($rootPath . '/header.php');
|
||||
checkAdmin();
|
||||
// SQL query to fetch data
|
||||
$sql = "SELECT user_id, first_name, last_name, email, member, date_joined, token, is_verified, profile_pic FROM users";
|
||||
$result = $conn->query($sql);
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA Site Users</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA Site Users</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php if (isset($_SESSION['message'])): ?>
|
||||
<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']); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div id="response-message" style="margin-top: 1rem;"></div>
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<!-- <th></th> -->
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Email</th>
|
||||
<th>Member</th>
|
||||
<th>Indemnity</th>
|
||||
<th>Date Joined</th>
|
||||
<th>Verified</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if ($result->num_rows > 0) {
|
||||
// Output data of each row
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if (getUserMemberStatus($row['user_id'])) {
|
||||
$member = "\u{2713}";
|
||||
} else {
|
||||
$member = "\u{2717}";
|
||||
}
|
||||
|
||||
$indemnityPending = false;
|
||||
|
||||
|
||||
$userId = $row['user_id'];
|
||||
$stmt = $conn->prepare("SELECT user_id FROM membership_application WHERE user_id = ? AND accept_indemnity = 0 LIMIT 1");
|
||||
$stmt->bind_param("i", $userId);
|
||||
$stmt->execute();
|
||||
$stmt->store_result();
|
||||
|
||||
if ($stmt->num_rows > 0) {
|
||||
$indemnityPending = true;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
echo "<tr>
|
||||
<td><img src=" . $row['profile_pic'] . " alt='Profile Picture' class='profile-pic'></td>
|
||||
|
||||
<td>" . htmlspecialchars($row['first_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['last_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['email']) . "</td>
|
||||
<td>" . $member . "</td>
|
||||
<td>" . $indemnityPending . "</td>
|
||||
<td>" . htmlspecialchars($row['date_joined']) . "</td>
|
||||
<td>";
|
||||
if ($row['is_verified'] != 1) {
|
||||
echo "
|
||||
<button class='resend-btn'
|
||||
data-email=" . htmlspecialchars($row['email'] ?? '') . "
|
||||
data-name=" . htmlspecialchars($row['first_name'] ?? '') . " " . htmlspecialchars($row['last_name'] ?? '') . "
|
||||
data-token=" . htmlspecialchars($row['token'] ?? '') . ">
|
||||
Resend Email
|
||||
</button>";
|
||||
} else {
|
||||
echo "\u{2713}";
|
||||
}
|
||||
// echo "</td>
|
||||
// <td><a href='linkmembership.php?user_id=".$row['user_id']."'>Link Membership</a></td>
|
||||
|
||||
// </tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="5">No records found</td></tr>';
|
||||
} ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
<script>
|
||||
document.querySelectorAll('.resend-btn').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const email = this.dataset.email;
|
||||
const name = this.dataset.name;
|
||||
const token = this.dataset.token;
|
||||
|
||||
fetch('resend_verification', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
name,
|
||||
token
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const messageDiv = document.getElementById('response-message');
|
||||
messageDiv.textContent = data.message;
|
||||
messageDiv.style.color = data.success ? 'green' : 'red';
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<?php include_once($rootPath . '/components/insta_footer.php'); ?>
|
||||
<?php include_once('header02.php');
|
||||
checkSuperAdmin();
|
||||
// SQL query to fetch data
|
||||
$sql = "SELECT user_id, first_name, last_name, email, member, date_joined, token, is_verified, profile_pic FROM users";
|
||||
$result = $conn->query($sql);
|
||||
?>
|
||||
<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;
|
||||
/* margin-bottom: 20px; */
|
||||
font-size: 16px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
color: #484848;
|
||||
background: #f9f9f7;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 10px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const table = document.querySelector("table");
|
||||
const headers = table.querySelectorAll("thead th");
|
||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
||||
const filterInput = document.getElementById("filterInput");
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
<!-- Page Banner Start -->
|
||||
<?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">4WDCSA Site Users</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.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">4WDCSA Site Users</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php if (isset($_SESSION['message'])): ?>
|
||||
<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']); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Tour List Area start -->
|
||||
<section class="tour-list-page py-10 rel z-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div id="response-message" style="margin-top: 1rem;"></div>
|
||||
<div class="col-lg-12">
|
||||
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
|
||||
<div style='padding:10px;'>
|
||||
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<!-- <th></th> -->
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Email</th>
|
||||
<th>Member</th>
|
||||
<th>Indemnity</th>
|
||||
<th>Date Joined</th>
|
||||
<th>Verified</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if ($result->num_rows > 0) {
|
||||
// Output data of each row
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if (getUserMemberStatus($row['user_id'])) {
|
||||
$member = "\u{2713}";
|
||||
} else {
|
||||
$member = "\u{2717}";
|
||||
}
|
||||
|
||||
$indemnityPending = false;
|
||||
|
||||
|
||||
$userId = $row['user_id'];
|
||||
$stmt = $conn->prepare("SELECT user_id FROM membership_application WHERE user_id = ? AND accept_indemnity = 0 LIMIT 1");
|
||||
$stmt->bind_param("i", $userId);
|
||||
$stmt->execute();
|
||||
$stmt->store_result();
|
||||
|
||||
if ($stmt->num_rows > 0) {
|
||||
$indemnityPending = true;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
echo "<tr>
|
||||
<td><img src=" . $row['profile_pic'] . " alt='Profile Picture' class='profile-pic'></td>
|
||||
|
||||
<td>" . htmlspecialchars($row['first_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['last_name']) . "</td>
|
||||
<td>" . htmlspecialchars($row['email']) . "</td>
|
||||
<td>" . $member . "</td>
|
||||
<td>" . $indemnityPending . "</td>
|
||||
<td>" . htmlspecialchars($row['date_joined']) . "</td>
|
||||
<td>";
|
||||
if ($row['is_verified'] != 1) {
|
||||
echo "
|
||||
<button class='resend-btn'
|
||||
data-email=" . htmlspecialchars($row['email'] ?? '') . "
|
||||
data-name=" . htmlspecialchars($row['first_name'] ?? '') . " " . htmlspecialchars($row['last_name'] ?? '') . "
|
||||
data-token=" . htmlspecialchars($row['token'] ?? '') . ">
|
||||
Resend Email
|
||||
</button>";
|
||||
} else {
|
||||
echo "\u{2713}";
|
||||
}
|
||||
// echo "</td>
|
||||
// <td><a href='linkmembership.php?user_id=".$row['user_id']."'>Link Membership</a></td>
|
||||
|
||||
// </tr>";
|
||||
}
|
||||
} else {
|
||||
echo '<tr><td colspan="5">No records found</td></tr>';
|
||||
} ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Tour List Area end -->
|
||||
<script>
|
||||
document.querySelectorAll('.resend-btn').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const email = this.dataset.email;
|
||||
const name = this.dataset.name;
|
||||
const token = this.dataset.token;
|
||||
|
||||
fetch('resend_verification.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
name,
|
||||
token
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const messageDiv = document.getElementById('response-message');
|
||||
messageDiv.textContent = data.message;
|
||||
messageDiv.style.color = data.success ? 'green' : 'red';
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<?php include_once("insta_footer.php"); ?>
|
||||
@@ -1,384 +1,384 @@
|
||||
<style>
|
||||
.dropcap {
|
||||
float: left;
|
||||
font-size: 3em;
|
||||
line-height: 1;
|
||||
padding-right: 0.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p><strong>DATE:</strong> 05 April 2025 at 10h00<br>
|
||||
<strong>VENUE:</strong> Base 4
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>NOTICE CONVENING THE MEETING</strong></h6>
|
||||
|
||||
<ul>
|
||||
<li>Proposed: Peter Hutchison</li>
|
||||
<li>Seconded: Doug Timm</li>
|
||||
<li>Attendance register will be available on request</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>WELCOME, APOLOGIES AND PROXIES</strong></h6>
|
||||
<ul>
|
||||
<li>Present: 30</li>
|
||||
<li>Proxies: 15 Total: 45</li>
|
||||
<li>Apologies: 2</li>
|
||||
<li>Quorum confirmed</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>ACCEPTANCE OF THE AGENDA WITH ANY ADDITIONAL ITEMS FROM THE FLOOR</strong></h6>
|
||||
<ul>
|
||||
<li>Proposed: Roy Olivier</li>
|
||||
<li>Seconded: Davin Webster</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>CONFIRMATION OF THE MINUTES OF THE PREVIOUS AGM OF 25 MARCH 2023</strong></h6>
|
||||
<ul>
|
||||
<li>Matters arising from the previous minutes: None</li>
|
||||
<li>Proposed: Dave Nixon</li>
|
||||
<li>Seconded: Peter Hutchison</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h3><strong>CHAIRMAN’S REPORT</strong></h3>
|
||||
<p><span class="dropcap">I</span> am honoured to be standing up here today to welcome you all to the 2025 AGM! We have a lot to cover so I won’t drag this out.
|
||||
It makes me think of my father when he gave a talk at school or at scouts where he went on and on, and we said he did not need a watch, he needed a calendar!</p>
|
||||
|
||||
<h6><strong>FIRE</strong></h6>
|
||||
<p class="content">
|
||||
<img style="max-width: 45%;" src="assets/images/blog/2/agm.jpg" alt="Base 4 Fire" class="img-left">
|
||||
<p>The biggest event of last year, or in fact the biggest event in the history of the Club, was the devastating fire that swept through Base 4. It occurred on a very windy day when a veldfire swept through the area burning everything in its path including I believe 6 homesteads. At Base 4 the Clubhouse and all the contents burned to the ground. If you look at the hulk over there you can only imagine the heat and destruction! The lapa down in the camping area suffered the same loss, leaving smouldering thatch which took days to cool.</p>
|
||||
<p>The only things left standing were the vehicle service structure and the container, the wooden ablution block down in the camping area, and the brick and mortar ablution block on the Northern side of Base 4.
|
||||
Whereto from there? We are not an outdoor adventure club for nothing! Everyone got stuck in and assisted in clearing the rubble, reconnecting the water and restoring electricity to the pool. A huge thank you to all those that put their backs to the wheel!</p>
|
||||
<p>Luckily, the vehicle service structure was still standing, so with a few adjustments and additions, we held the next open day there, a great success! I believe the turnout exceeded the standard turnout in the old Clubhouse.</p>
|
||||
</p>
|
||||
|
||||
<h6><strong>SPECIAL GENERAL MEETING</strong></h6>
|
||||
<p>Following the fire we had to negotiate the insurance claim. With good planning all the requirements as stipulated by the insurers were up to date and current, including the thatch upgrade earlier in the year and the recent issue of the Electrical Certificate of Compliance amongst other things ensured that there were no serious issues with the insurance value, and with the help of Geoff Joubert, the valuation of the insurance payout was submitted to the Club in record breaking time.</p>
|
||||
<p>This valuation gave us an option: either get the Clubhouse rebuilt to its former glory or take the cash which amounted to about 70% of the rebuild tender (the Indemnity Value). Choosing one or the other was not a decision that could be made by the Committee, hence the calling of a Special General Meeting so that the decision could be made by the Membership.</p>
|
||||
<p>There were really 2 decisions that needed to be made at that SGM: keep Base 4 or sell it, and when the decision was made to keep Base 4, whether to get the Clubhouse rebuilt or to take the money. The decision was to take the money and to reinvent the Club more in line with the current membership numbers and needs.</p>
|
||||
<p>All Members were then invited to submit proposals for the future of the Club to be considered and voted for at this Annual General Meeting. I will deal with these proposals later as dictated by the Agenda.</p>
|
||||
|
||||
<h6><strong>BASE 4 MAINTENANCE</strong></h6>
|
||||
<p>Base 4 is a big piece of ground and needs continuous and on-going maintenance. As mentioned earlier, the fire destroyed much of the infrastructure especially water pipes and electrical cabling. Thank you to the generous members that donated time, money and product ensuring that the basic services were in place to allow Base 4 to operate.</p>
|
||||
<p>The grass still needs cutting, the tracks maintained for driver training and for members to hone their skills. The ablution blocks require on-going upkeep and cleaning, fences repaired, water pumped and the myriad of jobs that need to be done but no one thinks about.</p>
|
||||
|
||||
|
||||
<h6><strong>CLUB SECRETARY</strong></h6>
|
||||
<p>Karl Hoffman’s name is synonymous with Base 4 and the Four Wheel Drive Club. He has been the go-to person for the Club for many years! This last year Karl stepped down from the position as Club Secretary due to ill-health: more about that later.</p>
|
||||
<p>The Committee has appointed Jacqui Boshoff to the position of Secretary, and we welcome her with open arms; I ask you all support her going forward.</p>
|
||||
<p>Please make a note regarding the Club contact details:
|
||||
<ul>
|
||||
<li>info@4wdcsa.co.za</li>
|
||||
<li>4wdcsa@gmail.com</li>
|
||||
<li>079 065 2795</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<h6><strong>THANK YOU’S</strong></h6>
|
||||
<p>I want to thank all those that have put in time and effort this past year</p>
|
||||
|
||||
<p><strong>The Committee</strong>
|
||||
<ul>
|
||||
<li>Peter Hutchison</li>
|
||||
<li>Chris Pinto</li>
|
||||
<li>Doug Timm</li>
|
||||
<li>Noelene Runciman</li>
|
||||
<li>Dorota Maskowicz</li>
|
||||
<li>Noel Thompson</li>
|
||||
<li>Dave Nixon</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><strong>The Breakfast brigade</strong>
|
||||
<ul>
|
||||
<li>Linda Hutchison</li>
|
||||
<li>Clara Hitge</li>
|
||||
<li>Lesley Joubert</li>
|
||||
<li>Louise Blignaut</li>
|
||||
<li>Carol Corlett</li>
|
||||
<li>Stan Salida</li>
|
||||
<li>Ashley Salida</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><strong>Event organisation</strong>
|
||||
<ul>
|
||||
<li>Noelene Runciman</li>
|
||||
<li>Dorota Maskowicz</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><strong>Base 4 maintenance</strong>
|
||||
<ul>
|
||||
<li>Dave Nixon</li>
|
||||
<li>Peter Hutchison</li>
|
||||
<li>Dave Bell</li>
|
||||
<li>Andre Botha</li>
|
||||
<li>Andrew Maier</li>
|
||||
<li>Davin Webster</li>
|
||||
<li>Clive Murray</li>
|
||||
<li>Doug Galloway</li>
|
||||
<li>Jenny Crickmore-Thompson</li>
|
||||
<li>John Franklin</li>
|
||||
<li>Marion Nichols</li>
|
||||
<li>Richard Carter</li>
|
||||
<li>Chas Dean</li>
|
||||
<li>Rudolf Engelmann</li>
|
||||
<li>Nelson Larangeira</li>
|
||||
<li><strong>Base 4</strong>: Kingsley Mankhusu</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>If I have left anyone out, please forgive me!</p>
|
||||
<p>
|
||||
<h6><strong>OUTINGS</strong></h6>
|
||||
<p>This has been a bumper year for outings, 11 in total.
|
||||
<ul>
|
||||
<li>Best of the Eastern Cape (February 2024)</li>
|
||||
<li>Parys Dome Extended Trip (March 2024)</li>
|
||||
<li>Piesangskloof Day Trip (May 2024)</li>
|
||||
<li>Botsalano Game Reserve extended trip (June)</li>
|
||||
<li>Groenkloof Day Trip (June 2024)</li>
|
||||
<li>Hobby Park Krugersdorp (August). Sadly no one turned up</li>
|
||||
<li>Old Mill Drift Extended Trip (September)</li>
|
||||
<li>Rust de Winter Weekend Trip (October 2024)</li>
|
||||
<li>Northern Natal Bush and Beach Extended Trip (November 2024)</li>
|
||||
<li>Mabibi Turtle Hatching Extended Trip (February 2025)</li>
|
||||
<li>Marakele National Park Extended Trip (March 2025)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>OPEN DAYS</strong></h6>
|
||||
<ul>
|
||||
<li>February 2024 – Chris Dykes on his 650km walk through the Kruger Park</li>
|
||||
<li>March 2024 – Carol Corlett on Coffee</li>
|
||||
<li>April 2024 – Anita Musevenzo on Save the Bees</li>
|
||||
<li>May 2024 – 4x4 Poker Rally</li>
|
||||
<li>June 2024 – Any pot will do cook-off</li>
|
||||
<li>July 2024 – Rob Milne on Anecdotes of the Boer War</li>
|
||||
<li>August 2024 – Bob Boden on Leopards of the Magaliesburg</li>
|
||||
<li>September 2024 – Spring clean</li>
|
||||
<li>October 2024 – Kevin Davie on Rock Art</li>
|
||||
<li>November 2925 – Tarryn Johnston on Hennops Revival</li>
|
||||
<li>February 2025 – Jack Kapp on Trip Report to Botswana and Zimbabwe</li>
|
||||
<li>March 2025 – Wayne van Onselen on Unchain our Children</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>EVENTS</strong></h6>
|
||||
<ul>
|
||||
<li>Annual General Meeting (April)</li>
|
||||
<li>4x4 Poker Trail Fun Rally (May)</li>
|
||||
<li>Any pot will do cook-off (June) – Winner Sandy Nixon</li>
|
||||
<li>Potjie cooking competition (July) – Winner Muzzy</li>
|
||||
<li>Special General Meeting (November 2024)</li>
|
||||
<li>Christmas Party (December)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>DRIVER TRAINING</strong></h6>
|
||||
<p>Another great perk of Club Membership is free driver training, make use of it!</p>
|
||||
<ul>
|
||||
<li>Driver Training Course (March 2024)</li>
|
||||
<li>Bush Mechanics Course (April 2024)</li>
|
||||
<li>Rescue and Recovery Course (June 2024)</li>
|
||||
<li>Driver Training Course (July 2024)</li>
|
||||
<li>Bush Mechanics Course (October 2024)</li>
|
||||
<li>Ladies’ Driver Training (March 2025)</li>
|
||||
<li>Driver training course (March 2025)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h3><strong>ADDRESS</strong></h3>
|
||||
<p>
|
||||
<span class="dropcap">A</span> little later this morning we are going to make some decisions about the future of Base 4.
|
||||
What I want to talk about is the future of The Four Wheel Club of Southern Africa, Gauteng region.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The burning down of our Clubhouse and Lapa can be seen as a blessing. This gives us the opportunity of starting afresh:
|
||||
new ideas, fresh thoughts. Historically we have spent our years worrying about money and funds and costs.
|
||||
For now, we do not have that hanging over our heads and I want to promote fun, and outings, and camping,
|
||||
and all the good things we associate with being a member of an Outdoor Adventure Club.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The upswing in outings and events this last year show that we are moving in that direction!
|
||||
</p>
|
||||
|
||||
<h6>Membership</h6>
|
||||
|
||||
<p>For members to get the full benefit of membership requires participation.</p>
|
||||
|
||||
<p><strong>Camping.</strong> We offer free camping; come and enjoy parking off under the trees and listen to the gurgling of the stream that is flowing so strongly at the moment. Anyone wanting to camp is not restricted to open weekends, Base 4 is open to you any day or days of the month; it just needs a bit of notice to organise the water and opening the gate etc.</p>
|
||||
|
||||
<p><strong>Driver training.</strong> Free to members. We run three different training subjects: basic driver training, rescue and recovery, and bush mechanics courses. We recently ran a very successful Ladies Driver Training and will be offering follow-up days.</p>
|
||||
|
||||
<p><strong>Open Days and Open Weekends.</strong> Committee members try very hard to get interesting guest speakers and events to make those days and weekends fun and exciting. Come and join in. Bring the family and friends for a picnic on the Sunday and relax under the trees or around the pool.</p>
|
||||
|
||||
<p><strong>Outings.</strong> As members you get preferential rates: day trips, weekend trips and extended trips. The Club does not make a vast profit on these outings, just enough to cover costs. Get out there and experience other places, other trails, other like-minded people.</p>
|
||||
|
||||
<p>
|
||||
These benefits only start there! Getting or giving advice from knowledgeable people.
|
||||
Sharing adventures, enjoying new travel companions.
|
||||
As I said, getting the benefit of your membership requires your participation.
|
||||
</p>
|
||||
|
||||
<h6>Running the Club</h6>
|
||||
|
||||
<p>
|
||||
We have 5 Members on the Committee at this AGM, and those 5 are suffering overload because they are shouldering all the work.
|
||||
We are a voluntary organisation, and the Committee Members are starting to resent the fact that they are expected to carry on
|
||||
regardless and rewardless. These Committee Members are there for the same reason you are there for, fun, education and excitement.
|
||||
If no assistance and change of attitude comes to the fore, there will be no Committee next year and the Club will drown!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Historically Committee Members had portfolios that they managed, Outings, Events, Estate management, Driver training and so on.
|
||||
The idea was that these portfolios would be managed by those Members but what happened in reality is that the Member ended up having
|
||||
to do all the work themselves. For example, Noelene found and organised 6 of the speakers at open days last year.
|
||||
I organised 7 and led 5 of the outings last year, and I ran 5 of the 7 Driver Training courses. As I said, we cannot go on like this!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Going forward, the Committee (or the Management Team) is mandated to run the Club along acceptable company practices,
|
||||
including the financial administration, record keeping, advertising and marketing. Further, the Team will assist in coordinating
|
||||
and organising outings, events etc. but the responsibility for organising and running of these portfolios will now lie with the Membership.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Amongst yourselves volunteer or delegate Members to lead trips, find speakers, organise events. Organise workdays at Base 4.
|
||||
Out of the membership of 80 (current paid up) people this load can be shared by having one person doing only one task a year.
|
||||
Only one! Come on! We need to share the load.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I will stick to my side of the bargain. I will organise and lead at least 1 extended outing this year,
|
||||
and I will conduct driver training for the rest of the year.
|
||||
</p>
|
||||
|
||||
<p><strong>Please get involved!</strong></p>
|
||||
|
||||
<h3><strong>GERALD O’BRIEN</strong></h3>
|
||||
<p>I have pleasure in announcing that the Committee after due consideration has decided to bestow Honorary Life Membership on Gerald O’Brien.</p>
|
||||
<p>Gerald has been a loyal member of our Club for 43 years (joining in 1981) and has made a significant contribution to driver training and offroad travel, all the while flying the flag for the Four Wheel Drive Club.</p>
|
||||
<p>I ask Geoff Joubert to give a brief run down on his life and times.</p>
|
||||
<p><i>Short presentation by Geoff Joubert</i></p>
|
||||
|
||||
<h3><strong>TREASURER'S REPORT AND FINANCIAL STATEMENT FOR 2024 / 2025</strong></h3>
|
||||
<p><strong>FWDCSA February 2025 Financials</strong></p>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Doug Timm, the Club Treasurer, presented the Treasurer’s report.</li>
|
||||
<li>Any member that requires a copy please contact the Club Secretary</li>
|
||||
<li>Any queries please contact Doug on <a href="mailto:dougtimm12@gmail.com">dougtimm12@gmail.com</a></li>
|
||||
<li>Proposed: John Runciman Seconded: Peter Hutchison</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<h3><strong>NOMINATION AND ELECTION OF COMMITTEE FOR 2025</strong></h3>
|
||||
<p>I sound like a stuck record, but all the committee members are volunteers that put aside any number of hours a month to ensure that the club runs smoothly, that there are interesting speakers, that trips are organised, that the grounds are maintained, and so on. This is more work than the 5 remaining members of the committee can effectively do. We need help!</p>
|
||||
|
||||
<h6>Standing members available for re-election</h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>John Runciman</li>
|
||||
<li>Noelene Runciman</li>
|
||||
<li>Doug Timm</li>
|
||||
<li>Peter Hutchison</li>
|
||||
<li>Chris Pinto</li>
|
||||
<li>Proposed: Mike Hitge Seconded: Zita Harber</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h6>Members resigning from the Committee</h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Noel Thompson</li>
|
||||
<li>Dorota Maskowicz</li>
|
||||
<li>Dave Nixon</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h6>New members to the Committee</h6>
|
||||
<p>No one proposed.</p>
|
||||
|
||||
<h3><strong>TRIBUTE TO KARL HOFFMAN</strong></h3>
|
||||
<p>Karl stood down from the position of Club Secretary which he has held for many years. I hand the microphone over the Geoff Joubert for more on this.
|
||||
<i>Short presentation by Geoff Joubert</i>
|
||||
</p>
|
||||
|
||||
<h3><strong>MOTIONS FOR VOTING</strong></h3>
|
||||
<p>As I said earlier, Members were given the opportunity to submit proposals for due consideration and have those proposals presented at the AGM. I have asked all the proposers to give a short motivation of their ideas and to answer any questions.</p>
|
||||
<p>Before they take to the floor, I need to make one point very clear. Whichever proposal or mixture of proposal is adopted, the Membership needs to take on the responsibility to bring it to completion. The Committee will continue to run the Club but will not take on the responsibility of seeing that proposal through.</p>
|
||||
<p>Each proposal was presented by the proposer.</p>
|
||||
|
||||
<h6><strong>PROPOSAL 1 – Andrew Maier</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>We do not develop Base 4 at all and that we try and sell the property.</li>
|
||||
<li>Invest the money in a secure investment for 2 years while searching for a new site within 60km of Johannesburg.</li>
|
||||
<li>Buy and lease to a company for a caravan park/camping ground with exclusive rights for the Club.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>PROPOSAL 2 – John Runciman</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Demolish remains and build new structure at the camping site (15x12m steel portal).</li>
|
||||
<li>3 containers (kitchen, bar, storage), all under roof.</li>
|
||||
<li>Use bottom entrance as main entrance. Cost: R1,200,000</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>PROPOSAL 3 – John Runciman</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Similar to current configuration: 12x12m gum/steel structure + 1 container (kitchen/bar/storage).</li>
|
||||
<li>Use bottom entrance as main entrance. Cost: R450,000</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><em>Proposals 2 and 3 presented together. Proposal 3 seen as a basis for future development.</em></p>
|
||||
|
||||
<h6><strong>PROPOSAL 4 – Alan Exton</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Minimum build, prioritize security. Gum pole shed with lean-to roof.</li>
|
||||
<li>If Proposal 2 adopted, increase container spacing to 1.5m and include adequate toilets.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>PROPOSAL 5 – Dorota Maskowicz</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Sell Base 4 ASAP, invest funds.</li>
|
||||
<li>Open days/weekends continue at various 4x4 and camping venues.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>PROPOSAL 6 – Clive Murray</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Remove old structures, place 4 containers on flat ground, add bow roof structure.</li>
|
||||
<li>Replace camping ablutions with a container. Cost: R1,595,000</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>DISCUSSION</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Engineer to assess toilet/kitchen block structure</li>
|
||||
<li>Base 4 is part of a conservancy: building restrictions</li>
|
||||
<li>Consider security hub on-site</li>
|
||||
<li>Maintain swimming pool</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>VOTING</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li><strong>Vote 1:</strong> Sell Base 4 or develop Base 4<br>Sell: 4 — Develop: 41 — <strong>Vote carried to develop Base 4</strong></li>
|
||||
<li><strong>Vote 2:</strong> Develop the top (Proposal 6) or bottom (Proposal 3)<br>Top: 12 — Bottom: 29 — <strong>Vote carried to develop bottom (Proposal 3)</strong></li>
|
||||
</ul>
|
||||
</p>
|
||||
<h3><strong>GENERAL</strong></h3>
|
||||
<p>Nothing raised</p>
|
||||
|
||||
<h3><strong>CLOSING OF MEETING</strong></h3>
|
||||
<style>
|
||||
.dropcap {
|
||||
float: left;
|
||||
font-size: 3em;
|
||||
line-height: 1;
|
||||
padding-right: 0.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p><strong>DATE:</strong> 05 April 2025 at 10h00<br>
|
||||
<strong>VENUE:</strong> Base 4
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>NOTICE CONVENING THE MEETING</strong></h6>
|
||||
|
||||
<ul>
|
||||
<li>Proposed: Peter Hutchison</li>
|
||||
<li>Seconded: Doug Timm</li>
|
||||
<li>Attendance register will be available on request</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>WELCOME, APOLOGIES AND PROXIES</strong></h6>
|
||||
<ul>
|
||||
<li>Present: 30</li>
|
||||
<li>Proxies: 15 Total: 45</li>
|
||||
<li>Apologies: 2</li>
|
||||
<li>Quorum confirmed</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>ACCEPTANCE OF THE AGENDA WITH ANY ADDITIONAL ITEMS FROM THE FLOOR</strong></h6>
|
||||
<ul>
|
||||
<li>Proposed: Roy Olivier</li>
|
||||
<li>Seconded: Davin Webster</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>CONFIRMATION OF THE MINUTES OF THE PREVIOUS AGM OF 25 MARCH 2023</strong></h6>
|
||||
<ul>
|
||||
<li>Matters arising from the previous minutes: None</li>
|
||||
<li>Proposed: Dave Nixon</li>
|
||||
<li>Seconded: Peter Hutchison</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h3><strong>CHAIRMAN’S REPORT</strong></h3>
|
||||
<p><span class="dropcap">I</span> am honoured to be standing up here today to welcome you all to the 2025 AGM! We have a lot to cover so I won’t drag this out.
|
||||
It makes me think of my father when he gave a talk at school or at scouts where he went on and on, and we said he did not need a watch, he needed a calendar!</p>
|
||||
|
||||
<h6><strong>FIRE</strong></h6>
|
||||
<p class="content">
|
||||
<img style="max-width: 45%;" src="assets/images/blog/2/agm.jpg" alt="Base 4 Fire" class="img-left">
|
||||
<p>The biggest event of last year, or in fact the biggest event in the history of the Club, was the devastating fire that swept through Base 4. It occurred on a very windy day when a veldfire swept through the area burning everything in its path including I believe 6 homesteads. At Base 4 the Clubhouse and all the contents burned to the ground. If you look at the hulk over there you can only imagine the heat and destruction! The lapa down in the camping area suffered the same loss, leaving smouldering thatch which took days to cool.</p>
|
||||
<p>The only things left standing were the vehicle service structure and the container, the wooden ablution block down in the camping area, and the brick and mortar ablution block on the Northern side of Base 4.
|
||||
Whereto from there? We are not an outdoor adventure club for nothing! Everyone got stuck in and assisted in clearing the rubble, reconnecting the water and restoring electricity to the pool. A huge thank you to all those that put their backs to the wheel!</p>
|
||||
<p>Luckily, the vehicle service structure was still standing, so with a few adjustments and additions, we held the next open day there, a great success! I believe the turnout exceeded the standard turnout in the old Clubhouse.</p>
|
||||
</p>
|
||||
|
||||
<h6><strong>SPECIAL GENERAL MEETING</strong></h6>
|
||||
<p>Following the fire we had to negotiate the insurance claim. With good planning all the requirements as stipulated by the insurers were up to date and current, including the thatch upgrade earlier in the year and the recent issue of the Electrical Certificate of Compliance amongst other things ensured that there were no serious issues with the insurance value, and with the help of Geoff Joubert, the valuation of the insurance payout was submitted to the Club in record breaking time.</p>
|
||||
<p>This valuation gave us an option: either get the Clubhouse rebuilt to its former glory or take the cash which amounted to about 70% of the rebuild tender (the Indemnity Value). Choosing one or the other was not a decision that could be made by the Committee, hence the calling of a Special General Meeting so that the decision could be made by the Membership.</p>
|
||||
<p>There were really 2 decisions that needed to be made at that SGM: keep Base 4 or sell it, and when the decision was made to keep Base 4, whether to get the Clubhouse rebuilt or to take the money. The decision was to take the money and to reinvent the Club more in line with the current membership numbers and needs.</p>
|
||||
<p>All Members were then invited to submit proposals for the future of the Club to be considered and voted for at this Annual General Meeting. I will deal with these proposals later as dictated by the Agenda.</p>
|
||||
|
||||
<h6><strong>BASE 4 MAINTENANCE</strong></h6>
|
||||
<p>Base 4 is a big piece of ground and needs continuous and on-going maintenance. As mentioned earlier, the fire destroyed much of the infrastructure especially water pipes and electrical cabling. Thank you to the generous members that donated time, money and product ensuring that the basic services were in place to allow Base 4 to operate.</p>
|
||||
<p>The grass still needs cutting, the tracks maintained for driver training and for members to hone their skills. The ablution blocks require on-going upkeep and cleaning, fences repaired, water pumped and the myriad of jobs that need to be done but no one thinks about.</p>
|
||||
|
||||
|
||||
<h6><strong>CLUB SECRETARY</strong></h6>
|
||||
<p>Karl Hoffman’s name is synonymous with Base 4 and the Four Wheel Drive Club. He has been the go-to person for the Club for many years! This last year Karl stepped down from the position as Club Secretary due to ill-health: more about that later.</p>
|
||||
<p>The Committee has appointed Jacqui Boshoff to the position of Secretary, and we welcome her with open arms; I ask you all support her going forward.</p>
|
||||
<p>Please make a note regarding the Club contact details:
|
||||
<ul>
|
||||
<li>info@4wdcsa.co.za</li>
|
||||
<li>4wdcsa@gmail.com</li>
|
||||
<li>079 065 2795</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<h6><strong>THANK YOU’S</strong></h6>
|
||||
<p>I want to thank all those that have put in time and effort this past year</p>
|
||||
|
||||
<p><strong>The Committee</strong>
|
||||
<ul>
|
||||
<li>Peter Hutchison</li>
|
||||
<li>Chris Pinto</li>
|
||||
<li>Doug Timm</li>
|
||||
<li>Noelene Runciman</li>
|
||||
<li>Dorota Maskowicz</li>
|
||||
<li>Noel Thompson</li>
|
||||
<li>Dave Nixon</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><strong>The Breakfast brigade</strong>
|
||||
<ul>
|
||||
<li>Linda Hutchison</li>
|
||||
<li>Clara Hitge</li>
|
||||
<li>Lesley Joubert</li>
|
||||
<li>Louise Blignaut</li>
|
||||
<li>Carol Corlett</li>
|
||||
<li>Stan Salida</li>
|
||||
<li>Ashley Salida</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><strong>Event organisation</strong>
|
||||
<ul>
|
||||
<li>Noelene Runciman</li>
|
||||
<li>Dorota Maskowicz</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><strong>Base 4 maintenance</strong>
|
||||
<ul>
|
||||
<li>Dave Nixon</li>
|
||||
<li>Peter Hutchison</li>
|
||||
<li>Dave Bell</li>
|
||||
<li>Andre Botha</li>
|
||||
<li>Andrew Maier</li>
|
||||
<li>Davin Webster</li>
|
||||
<li>Clive Murray</li>
|
||||
<li>Doug Galloway</li>
|
||||
<li>Jenny Crickmore-Thompson</li>
|
||||
<li>John Franklin</li>
|
||||
<li>Marion Nichols</li>
|
||||
<li>Richard Carter</li>
|
||||
<li>Chas Dean</li>
|
||||
<li>Rudolf Engelmann</li>
|
||||
<li>Nelson Larangeira</li>
|
||||
<li><strong>Base 4</strong>: Kingsley Mankhusu</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>If I have left anyone out, please forgive me!</p>
|
||||
<p>
|
||||
<h6><strong>OUTINGS</strong></h6>
|
||||
<p>This has been a bumper year for outings, 11 in total.
|
||||
<ul>
|
||||
<li>Best of the Eastern Cape (February 2024)</li>
|
||||
<li>Parys Dome Extended Trip (March 2024)</li>
|
||||
<li>Piesangskloof Day Trip (May 2024)</li>
|
||||
<li>Botsalano Game Reserve extended trip (June)</li>
|
||||
<li>Groenkloof Day Trip (June 2024)</li>
|
||||
<li>Hobby Park Krugersdorp (August). Sadly no one turned up</li>
|
||||
<li>Old Mill Drift Extended Trip (September)</li>
|
||||
<li>Rust de Winter Weekend Trip (October 2024)</li>
|
||||
<li>Northern Natal Bush and Beach Extended Trip (November 2024)</li>
|
||||
<li>Mabibi Turtle Hatching Extended Trip (February 2025)</li>
|
||||
<li>Marakele National Park Extended Trip (March 2025)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>OPEN DAYS</strong></h6>
|
||||
<ul>
|
||||
<li>February 2024 – Chris Dykes on his 650km walk through the Kruger Park</li>
|
||||
<li>March 2024 – Carol Corlett on Coffee</li>
|
||||
<li>April 2024 – Anita Musevenzo on Save the Bees</li>
|
||||
<li>May 2024 – 4x4 Poker Rally</li>
|
||||
<li>June 2024 – Any pot will do cook-off</li>
|
||||
<li>July 2024 – Rob Milne on Anecdotes of the Boer War</li>
|
||||
<li>August 2024 – Bob Boden on Leopards of the Magaliesburg</li>
|
||||
<li>September 2024 – Spring clean</li>
|
||||
<li>October 2024 – Kevin Davie on Rock Art</li>
|
||||
<li>November 2925 – Tarryn Johnston on Hennops Revival</li>
|
||||
<li>February 2025 – Jack Kapp on Trip Report to Botswana and Zimbabwe</li>
|
||||
<li>March 2025 – Wayne van Onselen on Unchain our Children</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>EVENTS</strong></h6>
|
||||
<ul>
|
||||
<li>Annual General Meeting (April)</li>
|
||||
<li>4x4 Poker Trail Fun Rally (May)</li>
|
||||
<li>Any pot will do cook-off (June) – Winner Sandy Nixon</li>
|
||||
<li>Potjie cooking competition (July) – Winner Muzzy</li>
|
||||
<li>Special General Meeting (November 2024)</li>
|
||||
<li>Christmas Party (December)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<h6><strong>DRIVER TRAINING</strong></h6>
|
||||
<p>Another great perk of Club Membership is free driver training, make use of it!</p>
|
||||
<ul>
|
||||
<li>Driver Training Course (March 2024)</li>
|
||||
<li>Bush Mechanics Course (April 2024)</li>
|
||||
<li>Rescue and Recovery Course (June 2024)</li>
|
||||
<li>Driver Training Course (July 2024)</li>
|
||||
<li>Bush Mechanics Course (October 2024)</li>
|
||||
<li>Ladies’ Driver Training (March 2025)</li>
|
||||
<li>Driver training course (March 2025)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h3><strong>ADDRESS</strong></h3>
|
||||
<p>
|
||||
<span class="dropcap">A</span> little later this morning we are going to make some decisions about the future of Base 4.
|
||||
What I want to talk about is the future of The Four Wheel Club of Southern Africa, Gauteng region.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The burning down of our Clubhouse and Lapa can be seen as a blessing. This gives us the opportunity of starting afresh:
|
||||
new ideas, fresh thoughts. Historically we have spent our years worrying about money and funds and costs.
|
||||
For now, we do not have that hanging over our heads and I want to promote fun, and outings, and camping,
|
||||
and all the good things we associate with being a member of an Outdoor Adventure Club.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The upswing in outings and events this last year show that we are moving in that direction!
|
||||
</p>
|
||||
|
||||
<h6>Membership</h6>
|
||||
|
||||
<p>For members to get the full benefit of membership requires participation.</p>
|
||||
|
||||
<p><strong>Camping.</strong> We offer free camping; come and enjoy parking off under the trees and listen to the gurgling of the stream that is flowing so strongly at the moment. Anyone wanting to camp is not restricted to open weekends, Base 4 is open to you any day or days of the month; it just needs a bit of notice to organise the water and opening the gate etc.</p>
|
||||
|
||||
<p><strong>Driver training.</strong> Free to members. We run three different training subjects: basic driver training, rescue and recovery, and bush mechanics courses. We recently ran a very successful Ladies Driver Training and will be offering follow-up days.</p>
|
||||
|
||||
<p><strong>Open Days and Open Weekends.</strong> Committee members try very hard to get interesting guest speakers and events to make those days and weekends fun and exciting. Come and join in. Bring the family and friends for a picnic on the Sunday and relax under the trees or around the pool.</p>
|
||||
|
||||
<p><strong>Outings.</strong> As members you get preferential rates: day trips, weekend trips and extended trips. The Club does not make a vast profit on these outings, just enough to cover costs. Get out there and experience other places, other trails, other like-minded people.</p>
|
||||
|
||||
<p>
|
||||
These benefits only start there! Getting or giving advice from knowledgeable people.
|
||||
Sharing adventures, enjoying new travel companions.
|
||||
As I said, getting the benefit of your membership requires your participation.
|
||||
</p>
|
||||
|
||||
<h6>Running the Club</h6>
|
||||
|
||||
<p>
|
||||
We have 5 Members on the Committee at this AGM, and those 5 are suffering overload because they are shouldering all the work.
|
||||
We are a voluntary organisation, and the Committee Members are starting to resent the fact that they are expected to carry on
|
||||
regardless and rewardless. These Committee Members are there for the same reason you are there for, fun, education and excitement.
|
||||
If no assistance and change of attitude comes to the fore, there will be no Committee next year and the Club will drown!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Historically Committee Members had portfolios that they managed, Outings, Events, Estate management, Driver training and so on.
|
||||
The idea was that these portfolios would be managed by those Members but what happened in reality is that the Member ended up having
|
||||
to do all the work themselves. For example, Noelene found and organised 6 of the speakers at open days last year.
|
||||
I organised 7 and led 5 of the outings last year, and I ran 5 of the 7 Driver Training courses. As I said, we cannot go on like this!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Going forward, the Committee (or the Management Team) is mandated to run the Club along acceptable company practices,
|
||||
including the financial administration, record keeping, advertising and marketing. Further, the Team will assist in coordinating
|
||||
and organising outings, events etc. but the responsibility for organising and running of these portfolios will now lie with the Membership.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Amongst yourselves volunteer or delegate Members to lead trips, find speakers, organise events. Organise workdays at Base 4.
|
||||
Out of the membership of 80 (current paid up) people this load can be shared by having one person doing only one task a year.
|
||||
Only one! Come on! We need to share the load.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I will stick to my side of the bargain. I will organise and lead at least 1 extended outing this year,
|
||||
and I will conduct driver training for the rest of the year.
|
||||
</p>
|
||||
|
||||
<p><strong>Please get involved!</strong></p>
|
||||
|
||||
<h3><strong>GERALD O’BRIEN</strong></h3>
|
||||
<p>I have pleasure in announcing that the Committee after due consideration has decided to bestow Honorary Life Membership on Gerald O’Brien.</p>
|
||||
<p>Gerald has been a loyal member of our Club for 43 years (joining in 1981) and has made a significant contribution to driver training and offroad travel, all the while flying the flag for the Four Wheel Drive Club.</p>
|
||||
<p>I ask Geoff Joubert to give a brief run down on his life and times.</p>
|
||||
<p><i>Short presentation by Geoff Joubert</i></p>
|
||||
|
||||
<h3><strong>TREASURER'S REPORT AND FINANCIAL STATEMENT FOR 2024 / 2025</strong></h3>
|
||||
<p><strong>FWDCSA February 2025 Financials</strong></p>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Doug Timm, the Club Treasurer, presented the Treasurer’s report.</li>
|
||||
<li>Any member that requires a copy please contact the Club Secretary</li>
|
||||
<li>Any queries please contact Doug on <a href="mailto:dougtimm12@gmail.com">dougtimm12@gmail.com</a></li>
|
||||
<li>Proposed: John Runciman Seconded: Peter Hutchison</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<h3><strong>NOMINATION AND ELECTION OF COMMITTEE FOR 2025</strong></h3>
|
||||
<p>I sound like a stuck record, but all the committee members are volunteers that put aside any number of hours a month to ensure that the club runs smoothly, that there are interesting speakers, that trips are organised, that the grounds are maintained, and so on. This is more work than the 5 remaining members of the committee can effectively do. We need help!</p>
|
||||
|
||||
<h6>Standing members available for re-election</h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>John Runciman</li>
|
||||
<li>Noelene Runciman</li>
|
||||
<li>Doug Timm</li>
|
||||
<li>Peter Hutchison</li>
|
||||
<li>Chris Pinto</li>
|
||||
<li>Proposed: Mike Hitge Seconded: Zita Harber</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h6>Members resigning from the Committee</h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Noel Thompson</li>
|
||||
<li>Dorota Maskowicz</li>
|
||||
<li>Dave Nixon</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h6>New members to the Committee</h6>
|
||||
<p>No one proposed.</p>
|
||||
|
||||
<h3><strong>TRIBUTE TO KARL HOFFMAN</strong></h3>
|
||||
<p>Karl stood down from the position of Club Secretary which he has held for many years. I hand the microphone over the Geoff Joubert for more on this.
|
||||
<i>Short presentation by Geoff Joubert</i>
|
||||
</p>
|
||||
|
||||
<h3><strong>MOTIONS FOR VOTING</strong></h3>
|
||||
<p>As I said earlier, Members were given the opportunity to submit proposals for due consideration and have those proposals presented at the AGM. I have asked all the proposers to give a short motivation of their ideas and to answer any questions.</p>
|
||||
<p>Before they take to the floor, I need to make one point very clear. Whichever proposal or mixture of proposal is adopted, the Membership needs to take on the responsibility to bring it to completion. The Committee will continue to run the Club but will not take on the responsibility of seeing that proposal through.</p>
|
||||
<p>Each proposal was presented by the proposer.</p>
|
||||
|
||||
<h6><strong>PROPOSAL 1 – Andrew Maier</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>We do not develop Base 4 at all and that we try and sell the property.</li>
|
||||
<li>Invest the money in a secure investment for 2 years while searching for a new site within 60km of Johannesburg.</li>
|
||||
<li>Buy and lease to a company for a caravan park/camping ground with exclusive rights for the Club.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>PROPOSAL 2 – John Runciman</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Demolish remains and build new structure at the camping site (15x12m steel portal).</li>
|
||||
<li>3 containers (kitchen, bar, storage), all under roof.</li>
|
||||
<li>Use bottom entrance as main entrance. Cost: R1,200,000</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>PROPOSAL 3 – John Runciman</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Similar to current configuration: 12x12m gum/steel structure + 1 container (kitchen/bar/storage).</li>
|
||||
<li>Use bottom entrance as main entrance. Cost: R450,000</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p><em>Proposals 2 and 3 presented together. Proposal 3 seen as a basis for future development.</em></p>
|
||||
|
||||
<h6><strong>PROPOSAL 4 – Alan Exton</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Minimum build, prioritize security. Gum pole shed with lean-to roof.</li>
|
||||
<li>If Proposal 2 adopted, increase container spacing to 1.5m and include adequate toilets.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>PROPOSAL 5 – Dorota Maskowicz</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Sell Base 4 ASAP, invest funds.</li>
|
||||
<li>Open days/weekends continue at various 4x4 and camping venues.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>PROPOSAL 6 – Clive Murray</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Remove old structures, place 4 containers on flat ground, add bow roof structure.</li>
|
||||
<li>Replace camping ablutions with a container. Cost: R1,595,000</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>DISCUSSION</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Engineer to assess toilet/kitchen block structure</li>
|
||||
<li>Base 4 is part of a conservancy: building restrictions</li>
|
||||
<li>Consider security hub on-site</li>
|
||||
<li>Maintain swimming pool</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h6><strong>VOTING</strong></h6>
|
||||
<p>
|
||||
<ul>
|
||||
<li><strong>Vote 1:</strong> Sell Base 4 or develop Base 4<br>Sell: 4 — Develop: 41 — <strong>Vote carried to develop Base 4</strong></li>
|
||||
<li><strong>Vote 2:</strong> Develop the top (Proposal 6) or bottom (Proposal 3)<br>Top: 12 — Bottom: 29 — <strong>Vote carried to develop bottom (Proposal 3)</strong></li>
|
||||
</ul>
|
||||
</p>
|
||||
<h3><strong>GENERAL</strong></h3>
|
||||
<p>Nothing raised</p>
|
||||
|
||||
<h3><strong>CLOSING OF MEETING</strong></h3>
|
||||
<p><strong>Time:</strong> 12h10</p>
|
||||
|
Before Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 340 KiB |
|
Before Width: | Height: | Size: 352 KiB |
|
Before Width: | Height: | Size: 374 KiB |
|
Before Width: | Height: | Size: 482 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 47 KiB |
@@ -46,7 +46,7 @@
|
||||
|
||||
<div class="header-inner rel d-flex align-items-center">
|
||||
<div class="logo-outer">
|
||||
<div class="logo"><a href="index"><img src="assets/images/logos/logo-two.png" alt="Logo" title="Logo"></a></div>
|
||||
<div class="logo"><a href="index.php"><img src="assets/images/logos/logo-two.png" alt="Logo" title="Logo"></a></div>
|
||||
</div>
|
||||
|
||||
<div class="nav-outer mx-lg-auto ps-xxl-5 clearfix">
|
||||
@@ -71,7 +71,7 @@
|
||||
<ul class="navigation clearfix">
|
||||
<li class="dropdown current"><a href="#">Home</a>
|
||||
<ul>
|
||||
<li><a href="index">Travel Agency</a></li>
|
||||
<li><a href="index.php">Travel Agency</a></li>
|
||||
<li><a href="index2.html">City Tou</a></li>
|
||||
<li><a href="index3.html">Tour Package</a></li>
|
||||
</ul>
|
||||
@@ -161,7 +161,7 @@
|
||||
|
||||
<!--Appointment Form-->
|
||||
<div class="appointment-form">
|
||||
<form method="post" action="contact">
|
||||
<form method="post" action="contact.php">
|
||||
<div class="form-group">
|
||||
<input type="text" name="text" value="" placeholder="Name" required>
|
||||
</div>
|
||||
@@ -182,9 +182,9 @@
|
||||
|
||||
<!--Social Icons-->
|
||||
<div class="social-style-one">
|
||||
<a href="contact"><i class="fab fa-twitter"></i></a>
|
||||
<a href="contact"><i class="fab fa-facebook-f"></i></a>
|
||||
<a href="contact"><i class="fab fa-instagram"></i></a>
|
||||
<a href="contact.php"><i class="fab fa-twitter"></i></a>
|
||||
<a href="contact.php"><i class="fab fa-facebook-f"></i></a>
|
||||
<a href="contact.php"><i class="fab fa-instagram"></i></a>
|
||||
<a href="#"><i class="fab fa-pinterest-p"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -201,7 +201,7 @@
|
||||
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">Bali, Indonesia</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"><a href="index.php">Home</a></li>
|
||||
<li class="breadcrumb-item active">Tour Details</li>
|
||||
</ol>
|
||||
</nav>
|
||||
@@ -795,7 +795,7 @@
|
||||
<i class="fal fa-arrow-right"></i>
|
||||
</button>
|
||||
<div class="text-center">
|
||||
<a href="contact">Need some help?</a>
|
||||
<a href="contact.php">Need some help?</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -871,7 +871,7 @@
|
||||
<div class="col col-small" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||
<div class="footer-widget footer-text">
|
||||
<div class="footer-logo mb-40">
|
||||
<a href="index"><img src="assets/images/logos/logo.png" alt="Logo"></a>
|
||||
<a href="index.php"><img src="assets/images/logos/logo.png" alt="Logo"></a>
|
||||
</div>
|
||||
<div class="footer-map">
|
||||
<iframe src="https://www.google.com/maps/embed?pb=!1m10!1m8!1m3!1d96777.16150026117!2d-74.00840582560909!3d40.71171357405996!3m2!1i1024!2i768!4f13.1!5e0!3m2!1sen!2sbd!4v1706508986625!5m2!1sen!2sbd" style="border:0; width: 100%;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
|
||||
@@ -899,7 +899,7 @@
|
||||
<ul class="list-style-three">
|
||||
<li><a href="about.html">About Company</a></li>
|
||||
<li><a href="blog.html">Community Blog</a></li>
|
||||
<li><a href="contact">Jobs and Careers</a></li>
|
||||
<li><a href="contact.php">Jobs and Careers</a></li>
|
||||
<li><a href="blog.html">latest News Blog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -937,7 +937,7 @@
|
||||
<div class="row">
|
||||
<div class="col-lg-5">
|
||||
<div class="copyright-text text-center text-lg-start">
|
||||
<p>@Copy 2024 <a href="index">Ravelo</a>, All rights reserved</p>
|
||||
<p>@Copy 2024 <a href="index.php">Ravelo</a>, All rights reserved</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-7 text-center text-lg-end">
|
||||
|
||||
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 259 KiB |
|
Before Width: | Height: | Size: 259 KiB |
|
Before Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 457 KiB |
|
Before Width: | Height: | Size: 663 KiB |
|
Before Width: | Height: | Size: 457 KiB |
|
Before Width: | Height: | Size: 687 KiB |
|
Before Width: | Height: | Size: 254 KiB |
|
Before Width: | Height: | Size: 280 KiB |
|
Before Width: | Height: | Size: 282 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 302 KiB |
|
Before Width: | Height: | Size: 364 KiB |
|
Before Width: | Height: | Size: 378 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 607 KiB |
|
Before Width: | Height: | Size: 413 KiB |
|
Before Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 264 KiB |
|
Before Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 293 KiB |
|
Before Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 457 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 560 KiB |
|
Before Width: | Height: | Size: 514 KiB |
|
Before Width: | Height: | Size: 304 KiB |
|
Before Width: | Height: | Size: 301 KiB |
|
Before Width: | Height: | Size: 592 KiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 397 KiB |
|
Before Width: | Height: | Size: 571 KiB |
|
Before Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 229 KiB |
|
Before Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 229 KiB |
|
Before Width: | Height: | Size: 197 KiB |
|
Before Width: | Height: | Size: 329 KiB |
|
Before Width: | Height: | Size: 593 KiB |