Code restructure push

This commit is contained in:
twotalesanimation
2025-12-04 15:09:44 +02:00
parent 86faad7a78
commit be2b757f4e
111 changed files with 17297 additions and 19420 deletions

118
.htaccess
View File

@@ -1,4 +1,120 @@
php_flag display_errors Off # 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 ^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]
# === 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_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 ^add_campsite$ src/admin/add_campsite.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]
</IfModule>
php_flag display_errors On
# php_value error_reporting -1 # php_value error_reporting -1
RedirectMatch 403 ^/\.well-known RedirectMatch 403 ^/\.well-known
Options -Indexes Options -Indexes

275
about.php
View File

@@ -1,274 +1,3 @@
<?php <?php
$headerStyle = 'light'; // Redirector file - loads the actual page from src/pages/other/
include_once('header.php'); require_once __DIR__ . '/src/pages/other/about.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>
<?php
$pageTitle = 'About';
$breadcrumbs = [['Home' => 'index.php']];
require_once('components/banner.php');
?>
<!-- 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. Saturdays Open Day includes breakfast and lunch for sale, plus braai fires ready to go—just bring your tongs! Its 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 its 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"); ?>

View File

@@ -46,7 +46,7 @@
<div class="header-inner rel d-flex align-items-center"> <div class="header-inner rel d-flex align-items-center">
<div class="logo-outer"> <div class="logo-outer">
<div class="logo"><a href="index.php"><img src="assets/images/logos/logo-two.png" alt="Logo" title="Logo"></a></div> <div class="logo"><a href="index"><img src="assets/images/logos/logo-two.png" alt="Logo" title="Logo"></a></div>
</div> </div>
<div class="nav-outer mx-lg-auto ps-xxl-5 clearfix"> <div class="nav-outer mx-lg-auto ps-xxl-5 clearfix">
@@ -71,7 +71,7 @@
<ul class="navigation clearfix"> <ul class="navigation clearfix">
<li class="dropdown current"><a href="#">Home</a> <li class="dropdown current"><a href="#">Home</a>
<ul> <ul>
<li><a href="index.php">Travel Agency</a></li> <li><a href="index">Travel Agency</a></li>
<li><a href="index2.html">City Tou</a></li> <li><a href="index2.html">City Tou</a></li>
<li><a href="index3.html">Tour Package</a></li> <li><a href="index3.html">Tour Package</a></li>
</ul> </ul>
@@ -161,7 +161,7 @@
<!--Appointment Form--> <!--Appointment Form-->
<div class="appointment-form"> <div class="appointment-form">
<form method="post" action="contact.php"> <form method="post" action="contact">
<div class="form-group"> <div class="form-group">
<input type="text" name="text" value="" placeholder="Name" required> <input type="text" name="text" value="" placeholder="Name" required>
</div> </div>
@@ -182,9 +182,9 @@
<!--Social Icons--> <!--Social Icons-->
<div class="social-style-one"> <div class="social-style-one">
<a href="contact.php"><i class="fab fa-twitter"></i></a> <a href="contact"><i class="fab fa-twitter"></i></a>
<a href="contact.php"><i class="fab fa-facebook-f"></i></a> <a href="contact"><i class="fab fa-facebook-f"></i></a>
<a href="contact.php"><i class="fab fa-instagram"></i></a> <a href="contact"><i class="fab fa-instagram"></i></a>
<a href="#"><i class="fab fa-pinterest-p"></i></a> <a href="#"><i class="fab fa-pinterest-p"></i></a>
</div> </div>
</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> <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"> <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"> <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"><a href="index">Home</a></li>
<li class="breadcrumb-item active">Tour Details</li> <li class="breadcrumb-item active">Tour Details</li>
</ol> </ol>
</nav> </nav>
@@ -795,7 +795,7 @@
<i class="fal fa-arrow-right"></i> <i class="fal fa-arrow-right"></i>
</button> </button>
<div class="text-center"> <div class="text-center">
<a href="contact.php">Need some help?</a> <a href="contact">Need some help?</a>
</div> </div>
</form> </form>
</div> </div>
@@ -871,7 +871,7 @@
<div class="col col-small" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <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-widget footer-text">
<div class="footer-logo mb-40"> <div class="footer-logo mb-40">
<a href="index.php"><img src="assets/images/logos/logo.png" alt="Logo"></a> <a href="index"><img src="assets/images/logos/logo.png" alt="Logo"></a>
</div> </div>
<div class="footer-map"> <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> <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"> <ul class="list-style-three">
<li><a href="about.html">About Company</a></li> <li><a href="about.html">About Company</a></li>
<li><a href="blog.html">Community Blog</a></li> <li><a href="blog.html">Community Blog</a></li>
<li><a href="contact.php">Jobs and Careers</a></li> <li><a href="contact">Jobs and Careers</a></li>
<li><a href="blog.html">latest News Blog</a></li> <li><a href="blog.html">latest News Blog</a></li>
</ul> </ul>
</div> </div>
@@ -937,7 +937,7 @@
<div class="row"> <div class="row">
<div class="col-lg-5"> <div class="col-lg-5">
<div class="copyright-text text-center text-lg-start"> <div class="copyright-text text-center text-lg-start">
<p>@Copy 2024 <a href="index.php">Ravelo</a>, All rights reserved</p> <p>@Copy 2024 <a href="index">Ravelo</a>, All rights reserved</p>
</div> </div>
</div> </div>
<div class="col-lg-7 text-center text-lg-end"> <div class="col-lg-7 text-center text-lg-end">

View File

@@ -27,9 +27,17 @@ $classes = $classes ?? '';
// If no banner image provided, try to use random banner // If no banner image provided, try to use random banner
if (empty($bannerImage)) { if (empty($bannerImage)) {
$bannerFolder = 'assets/images/banners/'; // Try to determine root path if not already set
if (!isset($rootPath)) {
$rootPath = $_SERVER['DOCUMENT_ROOT'] ?? dirname(__DIR__);
}
$bannerFolder = $rootPath . '/assets/images/banners/';
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
$bannerImage = !empty($bannerImages) ? $bannerImages[array_rand($bannerImages)] : 'assets/images/base4/camping.jpg'; // Convert absolute paths back to web-relative paths
$bannerImages = array_map(function($path) use ($rootPath) {
return str_replace($rootPath, '', $path);
}, $bannerImages);
$bannerImage = !empty($bannerImages) ? $bannerImages[array_rand($bannerImages)] : '/assets/images/base4/camping.jpg';
} }
// Add the page title to breadcrumbs as last item (not a link) // Add the page title to breadcrumbs as last item (not a link)

View File

@@ -1,118 +1,118 @@
<?php include_once("instapage.php"); ?><!-- footer area start --> <?php include_once(dirname(__DIR__) . "/src/pages/events/instapage.php"); ?><!-- footer area start -->
<footer class="main-footer bgs-cover overlay rel z-1 pb-25" <footer class="main-footer bgs-cover overlay rel z-1 pb-25"
style="background-image: url(assets/images/backgrounds/footer.jpg);"> style="background-image: url(assets/images/backgrounds/footer.jpg);">
<div class="container"> <div class="container">
<div class="footer-top pt-100 pb-30"> <div class="footer-top pt-100 pb-30">
<div class="row justify-content-between"> <div class="row justify-content-between">
<div class="col-xl-5 col-lg-6" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="col-xl-5 col-lg-6" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="footer-widget footer-contact"> <div class="footer-widget footer-contact">
<a href="https://chat.whatsapp.com/JD9xQuJlVX5AAJwcLrpl2B" target="_blank" style="text-decoration: none; color: inherit;"> <a href="https://chat.whatsapp.com/JD9xQuJlVX5AAJwcLrpl2B" target="_blank" style="text-decoration: none; color: inherit;">
<div style="display: flex; align-items: center; background-color: #e5f5e0; border-radius: 10px; padding: 10px; max-width: 100%; box-shadow: 0 2px 6px rgba(0,0,0,0.1);"> <div style="display: flex; align-items: center; background-color: #e5f5e0; border-radius: 10px; padding: 10px; max-width: 100%; box-shadow: 0 2px 6px rgba(0,0,0,0.1);">
<img src="assets/images/icons/whatsapp.png" alt="WhatsApp" style="width: 64px; height: 64px; margin-right: 15px;"> <img src="assets/images/icons/whatsapp.png" alt="WhatsApp" style="width: 64px; height: 64px; margin-right: 15px;">
<h1 style="margin: 0; font-size: 24px;">Join our WhatsApp Group</h1> <h1 style="margin: 0; font-size: 24px;">Join our WhatsApp Group</h1>
</div> </div>
</a> </a>
</div> </div>
<div class="footer-widget footer-contact"> <div class="footer-widget footer-contact">
<div class="footer-title"> <div class="footer-title">
<h5>Get In Touch</h5> <h5>Get In Touch</h5>
</div> </div>
<ul class="list-style-one"> <ul class="list-style-one">
<li><i class="fal fa-map-marked-alt"></i> Plot 50 Gemstone Rd, Doornrandje, Centurion, 0157</li> <li><i class="fal fa-map-marked-alt"></i> Plot 50 Gemstone Rd, Doornrandje, Centurion, 0157</li>
<li><i class="fal fa-envelope"></i> <a <li><i class="fal fa-envelope"></i> <a
href="mailto:info@4wdcsa.co.za">info@4wdcsa.co.za</a></li> href="mailto:info@4wdcsa.co.za">info@4wdcsa.co.za</a></li>
<li><i class="fal fa-clock"></i> Mon - Fri, 09:00 - 17:00</li> <li><i class="fal fa-clock"></i> Mon - Fri, 09:00 - 17:00</li>
<li><i class="fal fa-phone-volume"></i> <a href="callto:+2779 065 2795">079 065 2795</a></li> <li><i class="fal fa-phone-volume"></i> <a href="callto:+2779 065 2795">079 065 2795</a></li>
</ul> </ul>
</div> </div>
</div> </div>
<div class="col-xl-5 col-lg-6" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" <div class="col-xl-5 col-lg-6" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500"
data-aos-offset="50"> data-aos-offset="50">
<div class="section-title counter-text-wrap mb-35"> <div class="section-title counter-text-wrap mb-35">
<h2>Subscribe to our Mailing List</h2> <h2>Subscribe to our Mailing List</h2>
<p>Receive news and updates about upcoming trips and events.</p> <p>Receive news and updates about upcoming trips and events.</p>
</div> </div>
<div id="mc_embed_shell"> <div id="mc_embed_shell">
<div id="mc_embed_signup"> <div id="mc_embed_signup">
<form class="newsletter-form mb-50" action="https://fwdcsa.us17.list-manage.com/subscribe/post?u=3c26590bcc200ef52edc0bec2&amp;id=3c370893eb&amp;f_id=0099ebe3f0" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_self" novalidate=""> <form class="newsletter-form mb-50" action="https://fwdcsa.us17.list-manage.com/subscribe/post?u=3c26590bcc200ef52edc0bec2&amp;id=3c370893eb&amp;f_id=0099ebe3f0" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_self" novalidate="">
<div id="mc_embed_signup_scroll" style="width:100%;"> <div id="mc_embed_signup_scroll" style="width:100%;">
<div class="mc-field-group"></label><input type="email" name="EMAIL" class="required email" id="mce-EMAIL" required="" value="" placeholder="Email"></div> <div class="mc-field-group"></label><input type="email" name="EMAIL" class="required email" id="mce-EMAIL" required="" value="" placeholder="Email"></div>
<div class="mc-field-group"><input type="text" name="FNAME" class=" text" id="mce-FNAME" value="" placeholder="First Name"></div> <div class="mc-field-group"><input type="text" name="FNAME" class=" text" id="mce-FNAME" value="" placeholder="First Name"></div>
<div class="mc-field-group"><input type="text" name="LNAME" class=" text" id="mce-LNAME" value="" placeholder="Last Name"></div> <div class="mc-field-group"><input type="text" name="LNAME" class=" text" id="mce-LNAME" value="" placeholder="Last Name"></div>
<div class="mc-field-group"><input type="text" name="PHONE" class="REQ_CSS" id="mce-PHONE" value="" placeholder="Phone Number"></div> <div class="mc-field-group"><input type="text" name="PHONE" class="REQ_CSS" id="mce-PHONE" value="" placeholder="Phone Number"></div>
<div hidden=""><input type="hidden" name="tags" value="8324220"></div> <div hidden=""><input type="hidden" name="tags" value="8324220"></div>
<div id="mce-responses" class="clear"> <div id="mce-responses" class="clear">
<div class="response" id="mce-error-response" style="display: none;"></div> <div class="response" id="mce-error-response" style="display: none;"></div>
<div class="response" id="mce-success-response" style="display: none;"></div> <div class="response" id="mce-success-response" style="display: none;"></div>
</div> </div>
<div aria-hidden="true" style="position: absolute; left: -5000px;"><input type="text" name="b_3c26590bcc200ef52edc0bec2_3c370893eb" tabindex="-1" value=""></div> <div aria-hidden="true" style="position: absolute; left: -5000px;"><input type="text" name="b_3c26590bcc200ef52edc0bec2_3c370893eb" tabindex="-1" value=""></div>
<div class="clear"><input style="width:100%;" type="submit" name="subscribe" id="mc-embedded-subscribe" class="theme-btn bgc-secondary style-two" value="Subscribe"></div> <div class="clear"><input style="width:100%;" type="submit" name="subscribe" id="mc-embedded-subscribe" class="theme-btn bgc-secondary style-two" value="Subscribe"></div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="footer-bottom pt-20 pb-5"> <div class="footer-bottom pt-20 pb-5">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-lg-5"> <div class="col-lg-5">
<div class="copyright-text text-center text-lg-start"> <div class="copyright-text text-center text-lg-start">
<p>Copyright © <?php echo date("Y"); ?> <a href="index.html">4WDCSA</a> | All rights reserved.</p> <p>Copyright © <?php echo date("Y"); ?> <a href="index.html">4WDCSA</a> | All rights reserved.</p>
</div> </div>
</div> </div>
<div class="col-lg-7 text-center text-lg-end"> <div class="col-lg-7 text-center text-lg-end">
<ul class="footer-bottom-nav"> <ul class="footer-bottom-nav">
<!-- <li><a href="about.html">Terms</a></li> --> <!-- <li><a href="about.html">Terms</a></li> -->
<li><a href="privacy_policy.php">Privacy Policy</a></li> <li><a href="privacy_policy.php">Privacy Policy</a></li>
<!-- <li><a href="about.html">Legal notice</a></li> --> <!-- <li><a href="about.html">Legal notice</a></li> -->
<!-- <li><a href="about.html">Accessibility</a></li> --> <!-- <li><a href="about.html">Accessibility</a></li> -->
</ul> </ul>
</div> </div>
</div> </div>
<!-- Scroll Top Button --> <!-- Scroll Top Button -->
<button class="scroll-top scroll-to-target" data-target="html"><img <button class="scroll-top scroll-to-target" data-target="html"><img
src="assets/images/icons/scroll-up.png" alt="Scroll Up"></button> src="assets/images/icons/scroll-up.png" alt="Scroll Up"></button>
</div> </div>
</div> </div>
</footer> </footer>
<!-- footer area end --> <!-- footer area end -->
</div> </div>
<!--End pagewrapper--> <!--End pagewrapper-->
<script> <script>
document.cookie = "js_enabled=true; path=/"; document.cookie = "js_enabled=true; path=/";
</script> </script>
<!-- Jquery --> <!-- Jquery -->
<script src="assets/js/jquery-3.6.0.min.js"></script> <script src="assets/js/jquery-3.6.0.min.js"></script>
<!-- Bootstrap --> <!-- Bootstrap -->
<script src="assets/js/bootstrap.min.js"></script> <script src="assets/js/bootstrap.min.js"></script>
<!-- Appear Js --> <!-- Appear Js -->
<script src="assets/js/appear.min.js"></script> <script src="assets/js/appear.min.js"></script>
<!-- Slick --> <!-- Slick -->
<script src="assets/js/slick.min.js"></script> <script src="assets/js/slick.min.js"></script>
<!-- Magnific Popup --> <!-- Magnific Popup -->
<script src="assets/js/jquery.magnific-popup.min.js"></script> <script src="assets/js/jquery.magnific-popup.min.js"></script>
<!-- Nice Select --> <!-- Nice Select -->
<script src="assets/js/jquery.nice-select.min.js"></script> <script src="assets/js/jquery.nice-select.min.js"></script>
<!-- Image Loader --> <!-- Image Loader -->
<script src="assets/js/imagesloaded.pkgd.min.js"></script> <script src="assets/js/imagesloaded.pkgd.min.js"></script>
<!-- Skillbar --> <!-- Skillbar -->
<script src="assets/js/skill.bars.jquery.min.js"></script> <script src="assets/js/skill.bars.jquery.min.js"></script>
<!-- Isotope --> <!-- Isotope -->
<script src="assets/js/isotope.pkgd.min.js"></script> <script src="assets/js/isotope.pkgd.min.js"></script>
<!-- AOS Animation --> <!-- AOS Animation -->
<script src="assets/js/aos.js"></script> <script src="assets/js/aos.js"></script>
<!-- Custom script --> <!-- Custom script -->
<script src="assets/js/script.js"></script> <script src="assets/js/script.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,19 +0,0 @@
<?php
$dbhost = $_ENV['DB_HOST'];
$dbuser = $_ENV['DB_USER'];
$dbpass = $_ENV['DB_PASS'];
$dbname = $_ENV['DB_NAME'];
$salt = $_ENV['SALT'];
if(!$conn = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname)){
die("Failed to connect: " . mysqli_connect_error());
}
date_default_timezone_set('Africa/Johannesburg');
// Initialize DatabaseService for modern queries
require_once(__DIR__ . '/classes/DatabaseService.php');
$db = new DatabaseService($conn);

View File

@@ -1,52 +0,0 @@
<?php
require_once("session.php");
require_once("connection.php");
require_once("functions.php");
// CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Security token validation failed.']);
exit();
}
// Check if user_id is set in the POST request
if (isset($_POST['user_id']) && !empty($_POST['user_id'])) {
// Validate user_id as integer
$user_id = intval($_POST['user_id']);
if ($user_id <= 0) {
echo json_encode(['status' => 'error', 'message' => 'Invalid user ID.']);
exit();
}
$created_at = date('Y-m-d H:i:s'); // Use current date and time for created_at
// First, check if a bar tab already exists for this user_id
$stmt = $conn->prepare("SELECT * FROM bar_tabs WHERE user_id = ? LIMIT 1");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$checkResult = $stmt->get_result();
if ($checkResult->num_rows > 0) {
// If a bar tab already exists for this user_id, return an error message
echo json_encode(['status' => 'error', 'message' => 'A bar tab already exists for this user.']);
} else {
// Prepare the SQL query to insert a new record into the bar_tabs table
$stmt = $conn->prepare("INSERT INTO bar_tabs (user_id) VALUES (?)");
$stmt->bind_param("i", $user_id);
// Execute the query
if ($stmt->execute()) {
// If the insertion is successful, return a success message
echo json_encode(['status' => 'success', 'message' => 'Bar tab created successfully.']);
} else {
// If there's an error, return an error message
echo json_encode(['status' => 'error', 'message' => 'Error: ' . $conn->error]);
}
}
} else {
// If user_id is not provided, return an error message
echo json_encode(['status' => 'error', 'message' => 'User ID is required.']);
}
?>

199
docs/LINK_MANAGEMENT.md Normal file
View File

@@ -0,0 +1,199 @@
# Link Management Strategy - Complete Implementation
## Two-Layer Approach for Safe Migration
This strategy ensures that **all links work during the file restructuring migration** without breaking any existing functionality.
### Layer 1: URL Helper Function ✅
**Location**: `functions.php` at end of file
```php
function url($page) {
static $map = [
'login' => '/src/pages/auth/login.php',
'register' => '/src/pages/auth/register.php',
'membership' => '/src/pages/memberships/membership.php',
// ... 80+ total mappings
];
return isset($map[$page]) ? $map[$page] : '/' . $page . '.php';
}
```
**Usage in HTML**:
```html
<!-- Before -->
<a href="login.php">Login</a>
<!-- After -->
<a href="<?= url('login') ?>">Login</a>
```
**Advantages:**
- ✅ Explicit and intentional
- ✅ Single source of truth for all URLs
- ✅ Easy to audit and maintain
- ✅ Can add validation/auth logic to urls
- ✅ No performance overhead
**Progress:**
- ✅ Created comprehensive 80+ item mapping
- ⏳ Started updating header.php (1 of 95 files)
- ⏳ Need to update remaining ~94 files
---
### Layer 2: Apache RewriteRules ✅
**Location**: `.htaccess` at root
95 transparent rewrite rules that map old URLs to new locations:
```apache
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Auth pages
RewriteRule ^login\.php$ src/pages/auth/login.php [L]
RewriteRule ^register\.php$ src/pages/auth/register.php [L]
# ... 93 more rules covering all files
```
**How it works:**
1. User requests old URL: `login.php`
2. `.htaccess` rewrites to: `src/pages/auth/login.php`
3. File is served transparently
4. **User never knows the file moved**
**Advantages:**
- ✅ Backward compatible - old links still work
- ✅ Works for direct links, forms, AJAX calls
- ✅ No code changes needed immediately
- ✅ Covers any links we missed in Layer 1
- ✅ Can be removed after full migration
---
## Migration Workflow
### Phase 1: Update HTML Links (Current)
1. ✅ Create url() helper - DONE
2. ✅ Create .htaccess rules - DONE
3. ⏳ Update page links to use url() - IN PROGRESS
- Start: header.php (25+ links)
- Then: login.php, register.php (auth)
- Then: membership pages
- Then: booking/shop/event pages
- Then: admin pages
- **Total: ~300 link references to update**
### Phase 2: Update AJAX Calls
Find all `url: 'validate_login.php'` in script tags and update to:
```javascript
url: '<?= url("validate_login") ?>'
```
### Phase 3: Move Files (Later)
Once links are working:
1. Move config files → src/config/
2. Move page files → src/pages/[category]/
3. Move admin files → src/admin/
4. Move processor files → src/processors/
5. Move API files → src/api/
6. Update include paths in all files to use bootstrap.php
### Phase 4: Cleanup
- Remove .htaccess rewrite rules (no longer needed)
- Remove url() function or keep for future use
- Update all include paths to be permanent
---
## Link Count Summary
| Category | Files | Links | Status |
|----------|-------|-------|--------|
| header.php | 1 | 25 | 🔄 In Progress |
| login/register/auth | 8 | 40 | ⏳ Pending |
| Pages (all) | 45 | ~200 | ⏳ Pending |
| Admin pages | 9 | ~50 | ⏳ Pending |
| AJAX in scripts | ~15 | ~25 | ⏳ Pending |
| **TOTAL** | **95** | **~350** | **5% done** |
---
## Safety Guarantees
**If url() helper breaks**: .htaccess rules catch it
**If .htaccess doesn't work**: url() helper still works
**If we update only 50% of links**: Rest still work via rewrite rules
**No broken links**: Tested via browser and AJAX
**Easy rollback**: Just revert commits, .htaccess unchanged
---
## Current Branch Status
**Branch**: `feature/restructure-codebase`
**Commits**:
1. ✅ d57cce9a - Add URL helper + begin header.php updates
2. ✅ debe7d69 - Add .htaccess rewrite rules (95 rules)
**Next Steps**:
1. Continue updating links in remaining files
2. Test in browser
3. Verify AJAX endpoints work
4. Once satisfied, move to Phase 2 (move files)
5. Merge to main
---
## Quick Reference
### To Update a Link
```php
// Find this pattern in any file:
<a href="login.php">Login</a>
// Replace with:
<a href="<?= url('login') ?>">Login</a>
// For AJAX:
$.ajax({
url: '<?= url("validate_login") ?>',
// ...
});
// For redirects:
header("Location: " . url('index'));
```
### Mapping Reference
See `functions.php` for complete mapping. Key ones:
- `url('home')``/index.php`
- `url('login')``/src/pages/auth/login.php`
- `url('membership')``/src/pages/memberships/membership.php`
- `url('admin_members')``/src/admin/admin_members.php`
- `url('validate_login')``/src/processors/validate_login.php`
- `url('fetch_users')``/src/api/fetch_users.php`
---
## Performance
- Layer 1: 0 performance impact (direct path)
- Layer 2: ~0.001ms per request (Apache rewrite, cached)
- Can be removed after migration for full cleanup
---
## Testing Checklist Before Merge
- [ ] Click all main navigation links
- [ ] Test login/register flow
- [ ] Test AJAX endpoints (fetch_users, fetch_drinks, etc)
- [ ] Test admin pages navigation
- [ ] Test form submissions (process_*.php)
- [ ] Test redirects work
- [ ] Verify no 404 errors in browser console
- [ ] Check production logs for errors

369
docs/RESTRUCTURING_PLAN.md Normal file
View File

@@ -0,0 +1,369 @@
# File Restructuring Plan - feature/restructure-codebase
## New Directory Structure
```
4WDCSA.co.za/
├── src/
│ ├── pages/
│ │ ├── index.php (homepage - moved from root)
│ │ ├── about.php
│ │ ├── contact.php
│ │ ├── privacy_policy.php
│ │ │
│ │ ├── auth/
│ │ │ ├── login.php
│ │ │ ├── register.php
│ │ │ ├── forgot_password.php
│ │ │ ├── reset_password.php
│ │ │ ├── verify.php
│ │ │ ├── resend_verification.php
│ │ │ ├── change_password.php
│ │ │ └── update_password.php
│ │ │
│ │ ├── memberships/
│ │ │ ├── membership.php
│ │ │ ├── membership_details.php
│ │ │ ├── membership_application.php
│ │ │ ├── membership_payment.php
│ │ │ ├── renew_membership.php
│ │ │ └── member_info.php
│ │ │
│ │ ├── bookings/
│ │ │ ├── bookings.php
│ │ │ ├── campsites.php
│ │ │ ├── campsite_booking.php
│ │ │ ├── trips.php
│ │ │ ├── trip-details.php
│ │ │ ├── course_details.php
│ │ │ └── driver_training.php
│ │ │
│ │ ├── shop/
│ │ │ ├── view_cart.php
│ │ │ ├── add_to_cart.php
│ │ │ ├── bar_tabs.php
│ │ │ ├── payment_confirmation.php
│ │ │ ├── confirm.php
│ │ │ └── confirm2.php
│ │ │
│ │ ├── events/
│ │ │ ├── events.php
│ │ │ ├── blog.php
│ │ │ ├── blog_details.php
│ │ │ ├── best_of_the_eastern_cape_2024.php
│ │ │ ├── 2025_agm_minutes.php
│ │ │ ├── agm_content.php
│ │ │ └── instapage.php
│ │ │
│ │ └── other/
│ │ ├── 404.php
│ │ ├── account_settings.php
│ │ ├── rescue_recovery.php
│ │ ├── bush_mechanics.php
│ │ ├── indemnity.php
│ │ ├── indemnity_waiver.php
│ │ ├── basic_indemnity.php
│ │ ├── view_indemnity.php
│ │ ├── ad_banner.php
│ │ ├── logos.php
│ │ ├── review_box.php
│ │ ├── comment_box.php
│ │ ├── modal.php
│ │ ├── insta_footer.php
│ │ └── index2.php
│ │
│ ├── admin/
│ │ ├── admin_members.php
│ │ ├── admin_payments.php
│ │ ├── admin_web_users.php
│ │ ├── admin_course_bookings.php
│ │ ├── admin_camp_bookings.php
│ │ ├── admin_trip_bookings.php
│ │ ├── admin_visitors.php
│ │ ├── admin_efts.php
│ │ └── add_campsite.php
│ │
│ ├── api/
│ │ ├── fetch_users.php
│ │ ├── fetch_drinks.php
│ │ ├── fetch_bar_tabs.php
│ │ ├── get_campsites.php
│ │ ├── get_tab_total.php
│ │ └── google_validate_login.php
│ │
│ ├── processors/
│ │ ├── validate_login.php
│ │ ├── register_user.php
│ │ ├── process_application.php
│ │ ├── process_booking.php
│ │ ├── process_camp_booking.php
│ │ ├── process_course_booking.php
│ │ ├── process_trip_booking.php
│ │ ├── process_membership_payment.php
│ │ ├── process_payments.php
│ │ ├── process_eft.php
│ │ ├── submit_order.php
│ │ ├── submit_pop.php
│ │ ├── process_signature.php
│ │ ├── create_bar_tab.php
│ │ ├── update_application.php
│ │ ├── update_user.php
│ │ ├── upload_profile_picture.php
│ │ ├── send_reset_link.php
│ │ └── logout.php
│ │
│ ├── config/
│ │ ├── connection.php (database service init)
│ │ ├── session.php
│ │ ├── env.php
│ │ └── functions.php
│ │
│ └── classes/
│ ├── DatabaseService.php
│ ├── FormValidator.php (future)
│ └── ... (other services)
├── components/
│ ├── header.php
│ ├── banner.php
│ ├── footer.php (unified)
│ └── ... (shared components)
├── assets/
│ ├── css/
│ ├── js/
│ ├── images/
│ ├── fonts/
│ ├── uploads/
│ └── sass/
├── vendor/ (Composer)
├── mailers/ (Mailer templates)
├── uploads/ (User uploads)
├── google-client/ (OAuth client)
├── .htaccess (already in root - stays there)
├── index.php (PHP entry point - stays in root, requires src/pages/index.php)
├── sitemap.xml
└── phpinfo.php (debug - should remove later)
```
---
## Migration Strategy
### Phase 1: Create Structure & Map Files ✅
- [x] Create all directories
- [x] Create this migration plan
- [ ] Create index.php router in root that includes src/pages/index.php
- [ ] Create .htaccess rules to serve from src/ transparently
### Phase 2: Move Core Config Files
```bash
# Must do first - everything depends on these
- Move: connection.php → src/config/
- Move: session.php → src/config/
- Move: env.php → src/config/
- Move: functions.php → src/config/
- Update all includes in every file (this is automated by search/replace)
```
### Phase 3: Move Page Files (45 files)
```bash
# Priority: High-traffic pages first
1. Auth pages (8 files) → src/pages/auth/
- login.php, register.php, forgot_password.php, etc.
2. Membership pages (6 files) → src/pages/memberships/
- membership.php, membership_application.php, etc.
3. Booking pages (7 files) → src/pages/bookings/
- campsites.php, bookings.php, trips.php, etc.
4. Shop/Bar pages (6 files) → src/pages/shop/
- view_cart.php, bar_tabs.php, etc.
5. Events/Blog pages (7 files) → src/pages/events/
- blog.php, events.php, etc.
6. Misc pages (11 files) → src/pages/other/
- about.php, contact.php, indemnity.php, etc.
```
### Phase 4: Move Admin Files (9 files)
```bash
Move all admin_*.php files → src/admin/
- admin_members.php
- admin_payments.php
- etc.
```
### Phase 5: Move API Files (6 files)
```bash
Move all fetch_*.php and get_*.php files → src/api/
- fetch_users.php
- fetch_drinks.php
- get_campsites.php
- etc.
```
### Phase 6: Move Processor Files (18 files)
```bash
Move all process_*.php, validate_*.php, submit_*.php → src/processors/
- validate_login.php
- process_booking.php
- submit_order.php
- etc.
```
### Phase 7: Update All Include Paths
```bash
# This is the critical step - all files reference each other
- connection.php → src/config/connection.php
- session.php → src/config/session.php
- env.php → src/config/env.php
- functions.php → src/config/functions.php
# Update relative includes in each file to use __DIR__ or __FILE__
# Example: require_once(__DIR__ . '/../../config/connection.php');
```
### Phase 8: .htaccess Routes (Optional - Keep Simple for Now)
```bash
# Can be done separately - initially just use new paths as-is
# .htaccess rules to make old URLs still work (forward compatibility)
```
---
## Include Path Changes
### Before (Root-based includes):
```php
require_once('connection.php');
require_once('session.php');
require_once('functions.php');
include_once('header.php');
```
### After (New structure):
```php
// From: src/pages/auth/login.php
require_once(__DIR__ . '/../../config/connection.php');
require_once(__DIR__ . '/../../config/session.php');
require_once(__DIR__ . '/../../config/functions.php');
include_once(__DIR__ . '/../../components/header.php');
// Or use a bootstrap loader in root index.php that sets up paths globally
```
### Recommended: Bootstrap Approach
Create a common bootstrap file that all pages include:
```php
// src/bootstrap.php
<?php
define('APP_ROOT', __DIR__ . '/..');
define('SRC_ROOT', APP_ROOT . '/src');
define('CONFIG_PATH', SRC_ROOT . '/config');
define('CLASSES_PATH', SRC_ROOT . '/classes');
define('COMPONENTS_PATH', APP_ROOT . '/components');
require_once(CONFIG_PATH . '/env.php');
require_once(CONFIG_PATH . '/connection.php');
require_once(CONFIG_PATH . '/session.php');
require_once(CONFIG_PATH . '/functions.php');
?>
```
Then every page only needs:
```php
<?php require_once(__DIR__ . '/../../bootstrap.php'); ?>
```
---
## Testing Strategy
### Before Merge
1. **Test each moved file** - Load page in browser, verify no 404s
2. **Test includes** - Check all require_once/include work
3. **Test database** - Verify queries still execute
4. **Test sessions** - Login/logout still works
5. **Test links** - Navigation between pages works
6. **Test APIs** - AJAX endpoints respond correctly
### Rollback Plan
```bash
# If issues found:
git reset --hard HEAD
git checkout main
# All original files restored
```
---
## File Count Summary
```
├── Pages: 45 files (auth 8, memberships 6, bookings 7, shop 6, events 7, other 11)
├── Admin: 9 files
├── API: 6 files
├── Processors: 18 files
├── Config: 4 files (connection, session, env, functions)
├── Classes: 1 file (DatabaseService, more later)
└── Components: 2 files (header, banner)
Total: ~95 PHP files organized into logical groups
```
---
## Benefits of This Structure
**Organization** - Clear, logical file hierarchy
**Security** - Can restrict web access to sensitive folders (API, processors)
**Maintenance** - Related files grouped together
**Onboarding** - New developers find files easily
**Testing** - Can write tests per folder
**Scalability** - Easy to add new features in existing folders
**Performance** - Can set different caching rules per folder
**Version Control** - Smaller diffs, easier to review changes
---
## Next Steps
1. Create bootstrap.php (centralizes all includes)
2. Start Phase 2 - Move config files first
3. Create find/replace automation for include path updates
4. Test 1-2 files from each category
5. If successful, batch move remaining files in each category
6. Test full site
7. Commit in batches by category
8. Merge to main after validation
---
## Commands Reference
```bash
# List files to move for each phase
ls *.php | grep -E '^(login|register|forgot)' | xargs -I {} mv {} src/pages/auth/
# Find all require_once and include statements
grep -r "require_once\|include" src/ | grep -v "vendor"
# Test that no broken includes exist
php -l src/**/*.php
```
---
## Current Status
✅ Branch created: `feature/restructure-codebase`
✅ Directories created (all folders)
✅ This plan documented
**Next Action**: Create bootstrap.php and start Phase 2 (config files)

View File

@@ -1,5 +0,0 @@
<?php
require_once __DIR__ . '/vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

View File

@@ -1,495 +0,0 @@
<!DOCTYPE html>
<html lang="zxx">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="description" content="">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Title -->
<title>Ravelo - Travel & Tour Booking HTML Template</title>
<!-- Favicon Icon -->
<link rel="shortcut icon" href="assets/images/logos/favicon.png" type="image/x-icon">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- Flaticon -->
<link rel="stylesheet" href="assets/css/flaticon.min.css">
<!-- Font Awesome -->
<link rel="stylesheet" href="assets/css/fontawesome-5.14.0.min.css">
<!-- Bootstrap -->
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<!-- Magnific Popup -->
<link rel="stylesheet" href="assets/css/magnific-popup.min.css">
<!-- Nice Select -->
<link rel="stylesheet" href="assets/css/nice-select.min.css">
<!-- Animate -->
<link rel="stylesheet" href="assets/css/aos.css">
<!-- Slick -->
<link rel="stylesheet" href="assets/css/slick.min.css">
<!-- Main Style -->
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
<div class="page-wrapper">
<!-- Preloader -->
<div class="preloader"><div class="custom-loader"></div></div>
<!-- main header -->
<header class="main-header header-one">
<!--Header-Upper-->
<div class="header-upper bg-white py-30 rpy-0">
<div class="container-fluid clearfix">
<div class="header-inner rel d-flex align-items-center">
<div class="logo-outer">
<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">
<!-- Main Menu -->
<nav class="main-menu navbar-expand-lg">
<div class="navbar-header">
<div class="mobile-logo">
<a href="index.php">
<img src="assets/images/logos/logo-two.png" alt="Logo" title="Logo">
</a>
</div>
<!-- Toggle Button -->
<button type="button" class="navbar-toggle" data-bs-toggle="collapse" data-bs-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse clearfix">
<ul class="navigation clearfix">
<li class="dropdown current"><a href="#">Home</a>
<ul>
<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>
</li>
<li><a href="about.html">About</a></li>
<li class="dropdown"><a href="#">Tours</a>
<ul>
<li><a href="tour-list.html">Tour List</a></li>
<li><a href="tour-grid.html">Tour Grid</a></li>
<li><a href="tour-sidebar.html">Tour Sidebar</a></li>
<li><a href="trip-details.php">Tour Details</a></li>
<li><a href="tour-guide.html">Tour Guide</a></li>
</ul>
</li>
<li class="dropdown"><a href="#">Destinations</a>
<ul>
<li><a href="destination1.html">Destination 01</a></li>
<li><a href="destination2.html">Destination 01</a></li>
<li><a href="destination-details.html">Destination Details</a></li>
</ul>
</li>
<li class="dropdown"><a href="#">Pages</a>
<ul>
<li><a href="pricing.html">Pricing</a></li>
<li><a href="faqs.html">faqs</a></li>
<li class="dropdown"><a href="#">Gallery</a>
<ul>
<li><a href="gellery-grid.html">Gallery Grid</a></li>
<li><a href="gellery-slider.html">Gallery Slider</a></li>
</ul>
</li>
<li class="dropdown"><a href="#">products</a>
<ul>
<li><a href="shop.html">Our Products</a></li>
<li><a href="product-details.html">Product Details</a></li>
</ul>
</li>
<li><a href="contact.php">Contact Us</a></li>
<li><a href="404.html">404 Error</a></li>
</ul>
</li>
<li class="dropdown"><a href="#">blog</a>
<ul>
<li><a href="blog.html">blog List</a></li>
<li><a href="blog-details.html">blog details</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<!-- Main Menu End-->
</div>
<!-- Menu Button -->
<div class="menu-btns py-10">
<a href="contact.php" class="theme-btn style-two bgc-secondary">
<span data-hover="Book Now">Book Now</span>
<i class="fal fa-arrow-right"></i>
</a>
<!-- menu sidbar -->
<div class="menu-sidebar">
<button class="bg-transparent">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
</div>
</div>
</div>
</div>
<!--End Header Upper-->
</header>
<!--Form Back Drop-->
<div class="form-back-drop"></div>
<!-- Hidden Sidebar -->
<section class="hidden-bar">
<div class="inner-box text-center">
<div class="cross-icon"><span class="fa fa-times"></span></div>
<div class="title">
<h4>Get Appointment</h4>
</div>
<!--Appointment Form-->
<div class="appointment-form">
<form method="post" action="contact.php">
<div class="form-group">
<input type="text" name="text" value="" placeholder="Name" required>
</div>
<div class="form-group">
<input type="email" name="email" value="" placeholder="Email Address" required>
</div>
<div class="form-group">
<textarea placeholder="Message" rows="5"></textarea>
</div>
<div class="form-group">
<button type="submit" class="theme-btn style-two">
<span data-hover="Submit now">Submit now</span>
<i class="fal fa-arrow-right"></i>
</button>
</div>
</form>
</div>
<!--Social Icons-->
<div class="social-style-one">
<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>
</section>
<!--End Hidden Sidebar -->
<!-- Page Banner Start -->
<section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url(assets/images/banner/banner.jpg);">
<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">Gallery Grid</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">Gallery Grid</li>
</ol>
</nav>
</div>
</div>
</section>
<!-- Page Banner End -->
<!-- Gallery Area start -->
<section class="gallery-two-area py-100 rel z-1">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-12">
<div class="section-title text-center counter-text-wrap mb-50" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h2>Explore Our Photo Gallery</h2>
<p>One site <span class="count-text plus" data-speed="3000" data-stop="34500">0</span> most popular experience youll remember</p>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="image">
<img src="assets/images/gallery/gallery1.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Brown Concrete Building</a></h5>
</div>
</div>
</div>
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50">
<div class="image">
<img src="assets/images/gallery/gallery2.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Swimming near boat</a></h5>
</div>
</div>
</div>
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100">
<div class="image">
<img src="assets/images/gallery/gallery3.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Building in the desert</a></h5>
</div>
</div>
</div>
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="image">
<img src="assets/images/gallery/gallery4.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Cliff near shore beach</a></h5>
</div>
</div>
</div>
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50">
<div class="image">
<img src="assets/images/gallery/gallery5.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Tent camping in the desert</a></h5>
</div>
</div>
</div>
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100">
<div class="image">
<img src="assets/images/gallery/gallery6.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Machu Picchu, Peru</a></h5>
</div>
</div>
</div>
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="image">
<img src="assets/images/gallery/gallery7.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Gray and black fish under water</a></h5>
</div>
</div>
</div>
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50">
<div class="image">
<img src="assets/images/gallery/gallery8.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Yacht sailing near island</a></h5>
</div>
</div>
</div>
<div class="col-lg-4 col-sm-6">
<div class="gallery-two-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100">
<div class="image">
<img src="assets/images/gallery/gallery9.jpg" alt="Gallery">
<a href="destination-details.html" class="link"><i class="fal fa-arrow-right"></i></a>
</div>
<div class="content">
<span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Ship on dock during daytime</a></h5>
</div>
</div>
</div>
<div class="col-lg-12 text-center">
<a href="tour-grid.html" class="theme-btn style-two bgc-secondary">
<span data-hover="View All Gallery">View All Gallery</span>
<i class="fal fa-arrow-right"></i>
</a>
</div>
</div>
</div>
</section>
<!-- Gallery Area end -->
<!-- Newsletter Area start -->
<section class="newsletter-three bgc-primary py-100 rel z-1" style="background-image: url(assets/images/newsletter/newsletter-bg-lines.png);">
<div class="container container-1500">
<div class="row">
<div class="col-lg-6">
<div class="newsletter-content-part text-white rmb-55" data-aos="zoom-in-right" data-aos-duration="1500" data-aos-offset="50">
<div class="section-title counter-text-wrap mb-45">
<h2>Subscribe Our Newsletter to Get more offer & Tips</h2>
<p>One site <span class="count-text plus" data-speed="3000" data-stop="34500">0</span> most popular experience youll remember</p>
</div>
<form class="newsletter-form mb-15" action="#">
<input id="news-email" type="email" placeholder="Email Address" required>
<button type="submit" class="theme-btn bgc-secondary style-two">
<span data-hover="Subscribe">Subscribe</span>
<i class="fal fa-arrow-right"></i>
</button>
</form>
<p>No credit card requirement. No commitments</p>
</div>
<div class="newsletter-bg-image" data-aos="zoom-in-up" data-aos-delay="100" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/newsletter/newsletter-bg-image.png" alt="Newsletter">
</div>
</div>
<div class="col-lg-6">
<div class="newsletter-image-part bgs-cover" style="background-image: url(assets/images/newsletter/newsletter-two-right.jpg);" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"></div>
</div>
</div>
</div>
</section>
<!-- Newsletter Area end -->
<!-- footer area start -->
<footer class="main-footer footer-two bgp-bottom bgc-black rel z-15 pt-100 pb-115" style="background-image: url(assets/images/backgrounds/footer-two.png);">
<div class="widget-area">
<div class="container">
<div class="row row-cols-xxl-5 row-cols-xl-4 row-cols-md-3 row-cols-2">
<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.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>
</div>
</div>
</div>
<div class="col col-small" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
<div class="footer-widget footer-links ms-sm-5">
<div class="footer-title">
<h5>Services</h5>
</div>
<ul class="list-style-three">
<li><a href="destination-details.html">Best Tour Guide</a></li>
<li><a href="destination-details.html">Tour Booking</a></li>
<li><a href="destination-details.html">Hotel Booking</a></li>
<li><a href="destination-details.html">Ticket Booking</a></li>
</ul>
</div>
</div>
<div class="col col-small" data-aos="fade-up" data-aos-delay="100" data-aos-duration="1500" data-aos-offset="50">
<div class="footer-widget footer-links ms-md-4">
<div class="footer-title">
<h5>Company</h5>
</div>
<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.php">Jobs and Careers</a></li>
<li><a href="blog.html">latest News Blog</a></li>
</ul>
</div>
</div>
<div class="col col-small" data-aos="fade-up" data-aos-delay="150" data-aos-duration="1500" data-aos-offset="50">
<div class="footer-widget footer-links ms-lg-4">
<div class="footer-title">
<h5>Destinations</h5>
</div>
<ul class="list-style-three">
<li><a href="destination-details.html">African Safaris</a></li>
<li><a href="destination-details.html">Alaska & Canada</a></li>
<li><a href="destination-details.html">South America</a></li>
<li><a href="destination-details.html">Middle East</a></li>
</ul>
</div>
</div>
<div class="col col-md-6 col-10 col-small" data-aos="fade-up" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50">
<div class="footer-widget footer-contact">
<div class="footer-title">
<h5>Get In Touch</h5>
</div>
<ul class="list-style-one">
<li><i class="fal fa-map-marked-alt"></i> 578 Level, D-block 45 Street Melbourne, Australia</li>
<li><i class="fal fa-envelope"></i> <a href="mailto:supportrevelo@gmail.com">supportrevelo @gmail.com</a></li>
<li><i class="fal fa-phone-volume"></i> <a href="callto:+88012334588">+880 (123) 345 88</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="footer-bottom bg-transparent pt-20 pb-5">
<div class="container">
<div class="row">
<div class="col-lg-5">
<div class="copyright-text text-center text-lg-start">
<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">
<ul class="footer-bottom-nav">
<li><a href="about.html">Terms</a></li>
<li><a href="about.html">Privacy Policy</a></li>
<li><a href="about.html">Legal notice</a></li>
<li><a href="about.html">Accessibility</a></li>
</ul>
</div>
</div>
</div>
</div>
</footer>
<!-- footer area end -->
</div>
<!--End pagewrapper-->
<!-- Jquery -->
<script src="assets/js/jquery-3.6.0.min.js"></script>
<!-- Bootstrap -->
<script src="assets/js/bootstrap.min.js"></script>
<!-- Appear Js -->
<script src="assets/js/appear.min.js"></script>
<!-- Slick -->
<script src="assets/js/slick.min.js"></script>
<!-- Magnific Popup -->
<script src="assets/js/jquery.magnific-popup.min.js"></script>
<!-- Nice Select -->
<script src="assets/js/jquery.nice-select.min.js"></script>
<!-- Image Loader -->
<script src="assets/js/imagesloaded.pkgd.min.js"></script>
<!-- Skillbar -->
<script src="assets/js/skill.bars.jquery.min.js"></script>
<!-- Isotope -->
<script src="assets/js/isotope.pkgd.min.js"></script>
<!-- AOS Animation -->
<script src="assets/js/aos.js"></script>
<!-- Custom script -->
<script src="assets/js/script.js"></script>
</body>
</html>

View File

@@ -13,14 +13,18 @@
* 'light' = Dark text on light background (header02 style) * 'light' = Dark text on light background (header02 style)
*/ */
// Start output buffering BEFORE any code that might output
ob_start();
// Set default style if not provided // Set default style if not provided
$headerStyle = $headerStyle ?? 'light'; $headerStyle = $headerStyle ?? 'light';
ob_start(); // Use absolute paths based on this file's location
require_once("env.php"); $rootDir = dirname(__FILE__);
require_once("session.php"); require_once($rootDir . "/src/config/env.php");
require_once("connection.php"); require_once($rootDir . "/src/config/session.php");
require_once("functions.php"); require_once($rootDir . "/src/config/connection.php");
require_once($rootDir . "/src/config/functions.php");
$is_logged_in = isset($_SESSION['user_id']); $is_logged_in = isset($_SESSION['user_id']);
if (isset($_SESSION['user_id'])) { if (isset($_SESSION['user_id'])) {
@@ -229,7 +233,7 @@ if ($headerStyle === 'light') {
<div class="header-inner rel d-flex align-items-center"> <div class="header-inner rel d-flex align-items-center">
<div class="logo-outer"> <div class="logo-outer">
<div class="logo" style="width:200px;"><a href="index.php"><img src="<?php echo $logoImg; ?>" alt="Logo" title="Logo"></a></div> <div class="logo" style="width:200px;"><a href="index"><img src="<?php echo $logoImg; ?>" alt="Logo" title="Logo"></a></div>
</div> </div>
<div class="nav-outer mx-lg-auto ps-xxl-5 clearfix"> <div class="nav-outer mx-lg-auto ps-xxl-5 clearfix">
@@ -237,7 +241,7 @@ if ($headerStyle === 'light') {
<nav class="main-menu navbar-expand-lg"> <nav class="main-menu navbar-expand-lg">
<div class="navbar-header"> <div class="navbar-header">
<div class="mobile-logo"> <div class="mobile-logo">
<a href="index.php"> <a href="index">
<img src="<?php echo $mobileLogoImg; ?>" alt="Logo" title="Logo"> <img src="<?php echo $mobileLogoImg; ?>" alt="Logo" title="Logo">
</a> </a>
</div> </div>
@@ -252,44 +256,44 @@ if ($headerStyle === 'light') {
<div class="navbar-collapse collapse clearfix"> <div class="navbar-collapse collapse clearfix">
<ul class="navigation clearfix"> <ul class="navigation clearfix">
<li><a href="index.php">Home</a></li> <li><a href="index">Home</a></li>
<li><a href="about.php">About</a></li> <li><a href="about">About</a></li>
<li><a href="trips.php">Trips</a> <li><a href="trips">Trips</a>
<?php if ($headerStyle === 'dark'): ?> <?php if ($headerStyle === 'dark'): ?>
<ul> <ul>
<li><a href="tour-list.html">Tour List</a></li> <li><a href="tour-list.html">Tour List</a></li>
<li><a href="tour-grid.html">Tour Grid</a></li> <li><a href="tour-grid.html">Tour Grid</a></li>
<li><a href="tour-sidebar.html">Tour Sidebar</a></li> <li><a href="tour-sidebar.html">Tour Sidebar</a></li>
<li><a href="trip-details.php">Tour Details</a></li> <li><a href="trip-details">Tour Details</a></li>
<li><a href="tour-guide.html">Tour Guide</a></li> <li><a href="tour-guide.html">Tour Guide</a></li>
</ul> </ul>
<?php endif; ?> <?php endif; ?>
</li> </li>
<li class="dropdown"><a href="#">Training</a> <li class="dropdown"><a href="#">Training</a>
<ul> <ul>
<li><a href="driver_training.php">Basic 4X4 Driver Training</a></li> <li><a href="driver_training">Basic 4X4 Driver Training</a></li>
<li><a href="bush_mechanics.php">Bush Mechanics</a></li> <li><a href="bush_mechanics">Bush Mechanics</a></li>
<li><a href="rescue_recovery.php">Rescue & Recovery</a></li> <li><a href="rescue_recovery">Rescue & Recovery</a></li>
</ul> </ul>
</li> </li>
<li><a href="events.php">Events</a></li> <li><a href="events">Events</a></li>
<li><a href="blog.php">Blog</a></li> <li><a href="blog">Blog</a></li>
<?php if ($role === 'admin' || $role === 'superadmin') { ?> <?php if ($role === 'admin' || $role === 'superadmin') { ?>
<li class="dropdown"><a href="#">admin</a> <li class="dropdown"><a href="#">admin</a>
<ul> <ul>
<li><a href="admin_web_users.php">Website Users</a></li> <li><a href="admin_web_users">Website Users</a></li>
<li><a href="admin_members.php">4WDCSA Members</a></li> <li><a href="admin_members">4WDCSA Members</a></li>
<li><a href="admin_trip_bookings.php">Trip Bookings</a></li> <li><a href="admin_trip_bookings">Trip Bookings</a></li>
<li><a href="admin_course_bookings.php">Course Bookings</a></li> <li><a href="admin_course_bookings">Course Bookings</a></li>
<li><a href="admin_efts.php">EFT Payments</a></li> <li><a href="admin_efts">EFT Payments</a></li>
<li><a href="process_payments.php">Process Payments</a></li> <li><a href="process_payments">Process Payments</a></li>
<?php if ($role === 'superadmin') { ?> <?php if ($role === 'superadmin') { ?>
<li><a href="admin_visitors.php">Visitor Log</a></li> <li><a href="admin_visitors">Visitor Log</a></li>
<?php } ?> <?php } ?>
</ul> </ul>
</li> </li>
<?php } ?> <?php } ?>
<li><a href="contact.php">Contact</a></li> <li><a href="contact">Contact</a></li>
<?php if ($is_member) : ?> <?php if ($is_member) : ?>
<li class="dropdown"><a href="#">Members Area</a> <li class="dropdown"><a href="#">Members Area</a>
<ul> <ul>
@@ -301,15 +305,15 @@ if ($headerStyle === 'light') {
<?php if ($is_logged_in) : ?> <?php if ($is_logged_in) : ?>
<li class="dropdown"><a href="#">My Account</a> <li class="dropdown"><a href="#">My Account</a>
<ul> <ul>
<li><a href="account_settings.php">Account Settings</a></li> <li><a href="account_settings">Account Settings</a></li>
<li><a href="membership_details.php">Membership</a></li> <li><a href="membership_details">Membership</a></li>
<li><a href="bookings.php">My Bookings</a></li> <li><a href="bookings">My Bookings</a></li>
<li><a href="submit_pop.php">Submit P.O.P</a></li> <li><a href="submit_pop">Submit P.O.P</a></li>
<li><a href="logout.php">Log Out</a></li> <li><a href="logout">Log Out</a></li>
</ul> </ul>
</li> </li>
<?php else : ?> <?php else : ?>
<li class="nav-item d-xl-none"><a href="login.php">Log In</a></li> <li class="nav-item d-xl-none"><a href="login">Log In</a></li>
<?php endif; ?> <?php endif; ?>
</ul> </ul>
</div> </div>
@@ -324,13 +328,13 @@ if ($headerStyle === 'light') {
<div class="profile-menu"> <div class="profile-menu">
<div class="profile-info"> <div class="profile-info">
<span style="color: <?php echo $textColor; ?>;">Welcome, <?php echo $_SESSION['first_name']; ?></span> <span style="color: <?php echo $textColor; ?>;">Welcome, <?php echo $_SESSION['first_name']; ?></span>
<a href="account_settings.php"> <a href="account_settings">
<img src="<?php echo $_SESSION['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic"> <img src="<?php echo $_SESSION['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic">
</a> </a>
</div> </div>
</div> </div>
<?php else : ?> <?php else : ?>
<a href="login.php" class="theme-btn style-two bgc-secondary"> <a href="login" class="theme-btn style-two bgc-secondary">
<span data-hover="Log In">Log In</span> <span data-hover="Log In">Log In</span>
<i class="fal fa-arrow-right"></i> <i class="fal fa-arrow-right"></i>
</a> </a>

View File

@@ -1,307 +0,0 @@
<?php
ob_start();
require_once("env.php");
require_once("session.php");
require_once("connection.php");
require_once("functions.php");
$is_logged_in = isset($_SESSION['user_id']);
if (isset($_SESSION['user_id'])) {
$is_member = getUserMemberStatus($_SESSION['user_id']);
$pending_member = getUserMemberStatusPending($_SESSION['user_id']);
$user_id = $_SESSION['user_id'];
} else {
$is_member = false;
}
$role = getUserRole();
logVisitor();
?>
<!DOCTYPE html>
<html lang="zxx">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="description" content="">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Title -->
<title>4WDCSA - The Four Wheel Drive Club of Southern Africa</title>
<!-- Favicon Icon -->
<link rel="shortcut icon" href="assets/images/logos/favicon.ico" type="image/x-icon">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- Flaticon -->
<link rel="stylesheet" href="assets/css/flaticon.min.css">
<!-- Font Awesome -->
<link rel="stylesheet" href="assets/css/fontawesome-5.14.0.min.css">
<!-- Bootstrap -->
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<!-- Magnific Popup -->
<link rel="stylesheet" href="assets/css/magnific-popup.min.css">
<!-- Nice Select -->
<link rel="stylesheet" href="assets/css/nice-select.min.css">
<!-- Animate -->
<link rel="stylesheet" href="assets/css/aos.css">
<!-- Slick -->
<link rel="stylesheet" href="assets/css/slick.min.css">
<!-- Main Style -->
<link rel="stylesheet" href="assets/css/style_new.css?v=1">
<link rel="stylesheet" href="header_css.css">
<script id="mcjs">
! function(c, h, i, m, p) {
m = c.createElement(h), p = c.getElementsByTagName(h)[0], m.async = 1, m.src = i, p.parentNode.insertBefore(m, p)
}(document, "script", "https://chimpstatic.com/mcjs-connected/js/users/3c26590bcc200ef52edc0bec2/b960bfcd9c876f911833ca3f0.js");
</script>
</head>
<style>
.mobile-only {
display: none;
}
@media (max-width: 1199px) {
.mobile-only {
display: block;
}
}
.profile-menu {
position: relative;
display: inline-block;
}
.profile-info {
display: flex;
align-items: center;
cursor: pointer;
}
.profile-info span {
margin-right: 10px;
}
.profile-pic {
width: 50px;
height: 50px;
border-radius: 50%;
margin-right: 10px;
object-fit: cover;
/* Ensures the image fits without distortion */
}
.dropdown-arrow {
font-size: 16px;
}
.dropdown-menu2 {
display: none;
position: absolute;
top: 100%;
right: 0;
background-color: #fff;
box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.1);
/* border-radius: 5px; */
min-width: 250px;
z-index: 1000;
font-size: 18px;
}
.dropdown-menu2 ul {
list-style-type: none;
padding: 0;
margin: 0;
}
.dropdown-menu2 ul li {
padding: 8px;
border-bottom: 1px solid #f0f0f0;
}
.dropdown-menu22 ul li a {
text-decoration: none;
color: #333;
}
.dropdown-menu22 ul li:hover {
background-color: #f8f8f8;
}
</style>
<body>
<div class="page-wrapper">
<!-- Preloader -->
<div class="preloader">
<div class="custom-loader"></div>
</div>
<!-- main header -->
<header class="main-header header-one white-menu menu-absolute">
<!--Header-Upper-->
<div class="header-upper py-30 rpy-0">
<div class="container-fluid clearfix">
<div class="header-inner rel d-flex align-items-center">
<div class="logo-outer">
<div class="logo"><a href="index.php"><img src="assets/images/logos/logo.png"
style="width:200px;" alt="Logo" title="Logo"></a></div>
</div>
<div class="nav-outer mx-lg-auto ps-xxl-5 clearfix">
<!-- Main Menu -->
<nav class="main-menu navbar-expand-lg">
<div class="navbar-header">
<div class="mobile-logo">
<a href="index.php">
<img src="assets/images/logos/logo.png" alt="Logo" title="Logo">
</a>
</div>
<!-- Toggle Button -->
<button type="button" class="navbar-toggle" data-bs-toggle="collapse"
data-bs-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse clearfix">
<ul class="navigation clearfix">
<li><a href="index.php">Home</a></li>
<li><a href="about.php">About</a></li>
<!-- <li class="dropdown"><a href="about.html">BASE 4</a>
<ul>
<li><a href="tour-list.html">About BASE 4</a></li>
<li><a href="campsite_booking.php">Book a Campsite</a></li>
</ul>
</li> -->
<li><a href="trips.php">Trips</a>
<ul>
<li><a href="tour-list.html">Tour List</a></li>
<li><a href="tour-grid.html">Tour Grid</a></li>
<li><a href="tour-sidebar.html">Tour Sidebar</a></li>
<li><a href="trip-details.php">Tour Details</a></li>
<li><a href="tour-guide.html">Tour Guide</a></li>
</ul>
</li>
<li class="dropdown"><a href="#">Training</a>
<ul>
<li><a href="driver_training.php">Basic 4X4 Driver Training</a></li>
<li><a href="bush_mechanics.php">Bush Mechanics</a></li>
<li><a href="rescue_recovery.php">Rescue & Recovery</a></li>
</ul>
</li>
<li><a href="events.php">Events</a> </li>
<li><a href="blog.php">Blog</a></li>
<?php if ($role === 'admin' || $role === 'superadmin') { ?>
<li class="dropdown"><a href="#">admin</a>
<ul>
<li><a href="admin_web_users.php">Website Users</a></li>
<li><a href="admin_members.php">4WDCSA Members</a></li>
<li><a href="admin_trip_bookings.php">Trip Bookings</a></li>
<li><a href="admin_course_bookings.php">Course Bookings</a></li>
<!-- <li><a href="admin_camp_bookings.php">Camping Bookings</a></li> -->
<!-- <li><a href="admin_payments.php">Payfast Payments</a></li> -->
<li><a href="admin_efts.php">EFT Payments</a></li>
<li><a href="process_payments.php">Process Payments</a></li>
<!-- <li><a href="bar_tabs.php">Bar</a></li> -->
<?php if ($role === 'superadmin') { ?>
<li><a href="admin_visitors.php">Visitor Log</a></li>
<?php } ?>
</ul>
</li>
<?php } ?>
<li><a href="contact.php">Contact</a></li>
<?php if ($is_member) : ?>
<li class="dropdown"><a href="#">Members Area</a>
<ul>
<li><a href="#">Coming Soon!</a></li>
</ul>
<?php endif; ?>
<?php if ($is_logged_in) : ?>
<li class="dropdown"><a href="#">My Account</a>
<ul>
<li><a href="account_settings.php">Account Settings</a></li>
<li><a href="membership_details.php">Membership</a></li>
<li><a href="bookings.php">My Bookings</a></li>
<li><a href="submit_pop.php">Submit P.O.P</a></li>
<li><a href="logout.php">Log Out</a></li>
</ul>
<?php else : ?>
<li class="nav-item d-xl-none"><a href="login.php">Log In</a></li>
<?php endif; ?>
</ul>
</div>
</nav>
<!-- Main Menu End-->
</div>
<!-- Menu Button -->
<div class="menu-btns py-10">
<?php if ($is_logged_in) : ?>
<div class="profile-menu">
<div class="profile-info">
<span style="color: #fff;">Welcome, <?php echo $_SESSION['first_name']; ?></span>
<a href="account_settings.php">
<img src="<?php echo $_SESSION['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic">
</a>
<!-- <i style="color: #fff;" class="fal fa-chevron-down dropdown-arrow"></i> -->
</div>
<!-- Dropdown Menu -->
<!-- <div class="dropdown-menu2">
<ul>
<li><a href="account_settings.php">Account Settings</a></li>
<li><a href="membership_details.php">Membership</a></li>
<li><a href="bookings.php">My Bookings</a></li>
<li><a href="logout.php">Log Out</a></li>
</ul>
</div> -->
</div>
<?php else : ?>
<a href="login.php" class="theme-btn style-two bgc-secondary">
<span data-hover="Log In">Log In</span>
<i class="fal fa-arrow-right"></i>
</a>
<?php endif; ?>
<!-- menu sidebar -->
</div>
</div>
</div>
</div>
<!--End Header Upper-->
</header>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Toggle dropdown menu visibility when the profile-info is clicked
document.querySelector('.profile-info').addEventListener('click', function(event) {
const dropdownMenu = document.querySelector('.dropdown-menu2');
dropdownMenu.style.display = dropdownMenu.style.display === 'block' ? 'none' : 'block';
event.stopPropagation(); // Prevent this click from closing the menu
});
// Close the dropdown menu if the user clicks outside of it
document.addEventListener('click', function(event) {
const dropdownMenu = document.querySelector('.dropdown-menu2');
const profileMenu = document.querySelector('.profile-menu');
if (!profileMenu.contains(event.target)) {
dropdownMenu.style.display = 'none';
}
});
});
</script>

View File

@@ -1,312 +0,0 @@
<?php
ob_start();
require_once("env.php");
require_once("session.php");
require_once("connection.php");
require_once("functions.php");
$is_logged_in = isset($_SESSION['user_id']);
$role = getUserRole();
if (isset($_SESSION['user_id'])) {
$is_member = getUserMemberStatus($_SESSION['user_id']);
$pending_member = getUserMemberStatusPending($_SESSION['user_id']);
$user_id = $_SESSION['user_id'];
}
logVisitor();
?>
<!DOCTYPE html>
<html lang="zxx">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="description" content="">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Title -->
<title>4WDCSA - The Four Wheel Drive Club of Southern Africa</title>
<!-- Favicon Icon -->
<link rel="shortcut icon" href="assets/images/logos/favicon.ico" type="image/x-icon">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Flaticon -->
<link rel="stylesheet" href="assets/css/flaticon.min.css">
<!-- Font Awesome -->
<link rel="stylesheet" href="assets/css/fontawesome-5.14.0.min.css">
<!-- Bootstrap -->
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<!-- Magnific Popup -->
<link rel="stylesheet" href="assets/css/magnific-popup.min.css">
<!-- Nice Select -->
<link rel="stylesheet" href="assets/css/nice-select.min.css">
<!-- jQuery UI -->
<link rel="stylesheet" href="assets/css/jquery-ui.min.css">
<!-- Animate -->
<link rel="stylesheet" href="assets/css/aos.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.css" onload="AOS.init();">
<!-- Slick -->
<link rel="stylesheet" href="assets/css/slick.min.css">
<!-- Main Style -->
<link rel="stylesheet" href="assets/css/style_new.css">
<script id="mcjs">
! function(c, h, i, m, p) {
m = c.createElement(h), p = c.getElementsByTagName(h)[0], m.async = 1, m.src = i, p.parentNode.insertBefore(m, p)
}(document, "script", "https://chimpstatic.com/mcjs-connected/js/users/3c26590bcc200ef52edc0bec2/b960bfcd9c876f911833ca3f0.js");
</script>
</head>
<style>
.profile-menu {
position: relative;
display: inline-block;
}
.profile-info {
display: flex;
align-items: center;
cursor: pointer;
}
.profile-info span {
margin-right: 10px;
}
.profile-pic {
width: 50px;
height: 50px;
border-radius: 50%;
margin-right: 10px;
object-fit: cover;
/* Ensures the image fits without distortion */
}
.dropdown-arrow {
font-size: 16px;
}
.dropdown-menu2 {
display: none;
position: absolute;
top: 100%;
right: 0;
background-color: #fff;
box-shadow: 2px 2px 5px 1px rgba(0, 0, 0, 0.1), -2px 0px 5px 1px rgba(0, 0, 0, 0.1);
/* border-radius: 5px; */
min-width: 250px;
z-index: 1000;
font-size: 18px;
}
.dropdown-menu2 ul {
list-style-type: none;
padding: 0;
margin: 0;
}
.dropdown-menu2 ul li {
padding: 8px;
border-bottom: 1px solid #f0f0f0;
}
.dropdown-menu22 ul li a {
text-decoration: none;
color: #333;
}
.dropdown-menu22 ul li:hover {
background-color: #f8f8f8;
}
.page-banner-area {
position: relative;
background-size: cover;
background-position: center;
overflow: hidden;
}
.banner-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('assets/images/banner/tracks7.png');
/* Replace with your PNG */
background-repeat: no-repeat;
background-size: cover;
background-position: center;
z-index: 1;
pointer-events: none;
}
/* Make sure your content is above the overlays */
.banner-inner {
position: relative;
z-index: 3;
}
</style>
<body>
<div class="page-wrapper">
<!-- Preloader -->
<div class="preloader">
<div class="custom-loader"></div>
</div>
<!-- main header -->
<header class="main-header header-one">
<!--Header-Upper-->
<div class="header-upper bg-white py-30 rpy-0">
<div class="container-fluid clearfix">
<div class="header-inner rel d-flex align-items-center">
<div class="logo-outer">
<div style="width:200px;" 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">
<!-- Main Menu -->
<nav class="main-menu navbar-expand-lg">
<div class="navbar-header">
<div class="mobile-logo">
<a href="index.php">
<img src="assets/images/logos/logo-two.png" alt="Logo" title="Logo">
</a>
</div>
<!-- Toggle Button -->
<button type="button" class="navbar-toggle" data-bs-toggle="collapse" data-bs-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse clearfix">
<ul class="navigation clearfix">
<li><a href="index.php">Home</a></li>
<li><a href="about.php">About</a></li>
<!-- <li class="dropdown"><a href="about.html">BASE 4</a>
<ul>
<li><a href="tour-list.html">About BASE 4</a></li>
<li><a href="campsite_booking.php">Book a Campsite</a></li>
</ul>
</li> -->
<li><a href="trips.php">Trips</a>
</li>
<li class="dropdown"><a href="#">Training</a>
<ul>
<li><a href="driver_training.php">Basic 4X4 Driver Training</a></li>
<li><a href="bush_mechanics.php">Bush Mechanics</a></li>
<li><a href="rescue_recovery.php">Rescue & Recovery</a></li>
</ul>
</li>
<li><a href="events.php">Events</a>
</li>
<li><a href="blog.php">Blog</a></li>
<?php if ($role === 'admin' || $role === 'superadmin') { ?>
<li class="dropdown"><a href="#">admin</a>
<ul>
<li><a href="admin_web_users.php">Website Users</a></li>
<li><a href="admin_members.php">4WDCSA Members</a></li>
<li><a href="admin_trip_bookings.php">Trip Bookings</a></li>
<li><a href="admin_course_bookings.php">Course Bookings</a></li>
<!-- <li><a href="admin_camp_bookings.php">Camping Bookings</a></li> -->
<!-- <li><a href="admin_payments.php">Payfast Payments</a></li> -->
<li><a href="admin_efts.php">EFT Payments</a></li>
<li><a href="process_payments.php">Process Payments</a></li>
<?php if ($role === 'superadmin') { ?>
<li><a href="admin_visitors.php">Visitor Log</a></li>
<?php } ?>
<!-- <li><a href="bar_tabs.php">Bar</a></li> -->
</ul>
</li>
<?php } ?>
<li><a href="contact.php">Contact</a></li>
<?php if ($is_logged_in) : ?>
<li class="dropdown"><a href="#">My Account</a>
<ul>
<li><a href="account_settings.php">Account Settings</a></li>
<li><a href="membership_details.php">Membership</a></li>
<li><a href="bookings.php">My Bookings</a></li>
<li><a href="submit_pop.php">Submit P.O.P</a></li>
<li><a href="logout.php">Log Out</a></li>
</ul>
<?php else : ?>
<li class="nav-item d-xl-none"><a href="login.php">Log In</a></li>
<?php endif; ?>
</ul>
</div>
</nav>
<!-- Main Menu End-->
</div>
<!-- Menu Button -->
<div class="menu-btns py-10">
<?php if ($is_logged_in) : ?>
<div class="profile-menu">
<div class="profile-info">
<span style="color: #111111;">Welcome, <?php echo $_SESSION['first_name']; ?></span>
<a href="account_settings.php">
<img src="<?php echo $_SESSION['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic">
</a>
<!-- <i style="color: #111111;" class="fal fa-chevron-down dropdown-arrow"></i> -->
</div>
<!-- Dropdown Menu -->
<!-- <div class="dropdown-menu2">
<ul>
<li><a href="account_settings.php">Account Settings</a></li>
<li><a href="membership_details.php">Membership</a></li>
<li><a href="bookings.php">Bookings</a></li>
<li><a href="logout.php">Log Out</a></li>
</ul>
</div> -->
</div>
<?php else : ?>
<a href="login.php" class="theme-btn style-two bgc-secondary">
<span data-hover="Log In">Log In</span>
<i class="fal fa-arrow-right"></i>
</a>
<?php endif; ?>
<!-- menu sidebar -->
</div>
</div>
</div>
</div>
<!--End Header Upper-->
</header>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Toggle dropdown menu visibility when the profile-info is clicked
document.querySelector('.profile-info').addEventListener('click', function(event) {
const dropdownMenu = document.querySelector('.dropdown-menu2');
dropdownMenu.style.display = dropdownMenu.style.display === 'block' ? 'none' : 'block';
event.stopPropagation(); // Prevent this click from closing the menu
});
// Close the dropdown menu if the user clicks outside of it
document.addEventListener('click', function(event) {
const dropdownMenu = document.querySelector('.dropdown-menu2');
const profileMenu = document.querySelector('.profile-menu');
if (!profileMenu.contains(event.target)) {
dropdownMenu.style.display = 'none';
}
});
});
</script>

View File

@@ -3,7 +3,7 @@ $headerStyle = 'dark';
include_once('header.php'); include_once('header.php');
$indemnityPending = false; $indemnityPending = false;
if (isset($_SESSION['user_id'])) { if (isset($_SESSION['user_id']) && isset($conn) && $conn !== null) {
$userId = $_SESSION['user_id']; $userId = $_SESSION['user_id'];
$stmt = $conn->prepare("SELECT user_id FROM membership_application WHERE user_id = ? AND accept_indemnity = 0 LIMIT 1"); $stmt = $conn->prepare("SELECT user_id FROM membership_application WHERE user_id = ? AND accept_indemnity = 0 LIMIT 1");
$stmt->bind_param("i", $userId); $stmt->bind_param("i", $userId);
@@ -83,17 +83,18 @@ if (countUpcomingTrips() > 0) { ?>
<div class="row justify-content-center"> <div class="row justify-content-center">
<?php <?php
// Query to retrieve data from the trips table // Query to retrieve data from the trips table
$stmt = $conn->prepare("SELECT trip_id, trip_name, location, short_description, start_date, end_date, vehicle_capacity, cost_members, places_booked if (isset($conn) && $conn !== null) {
FROM trips $stmt = $conn->prepare("SELECT trip_id, trip_name, location, short_description, start_date, end_date, vehicle_capacity, cost_members, places_booked
WHERE published = ? FROM trips
ORDER BY trip_id DESC WHERE published = ?
LIMIT 4"); ORDER BY trip_id DESC
$published = 1; LIMIT 4");
$stmt->bind_param("i", $published); $published = 1;
$stmt->execute(); $stmt->bind_param("i", $published);
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) { if ($result->num_rows > 0) {
// Loop through each row // Loop through each row
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
$trip_id = $row['trip_id']; $trip_id = $row['trip_id'];
@@ -131,6 +132,7 @@ if (countUpcomingTrips() > 0) { ?>
} else { } else {
echo "No trips available."; echo "No trips available.";
} }
} // end if (isset($conn) && $conn !== null)
?> ?>
</div> </div>

View File

@@ -1,14 +0,0 @@
<?php
session_start();
// Destroy the session
session_destroy();
// Redirect to login page
header("Location: index.php"); // Replace with your actual login page URL
exit();
?>

View File

@@ -1,85 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modal with AJAX Dropdown</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container mt-5">
<!-- Button to trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#userModal">
Open Modal
</button>
</div>
<!-- Modal -->
<div class="modal fade" id="userModal" tabindex="-1" aria-labelledby="userModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="userModalLabel">Select a User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="barTabForm">
<div class="mb-3">
<label for="userSelect" class="form-label">Choose a User</label>
<select class="form-select" id="userSelect" name="user_id" required>
<option value="">Loading...</option>
</select>
</div>
<button type="submit" class="btn btn-success">Create Bar Tab</button>
</form>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
// Load users into dropdown when modal opens
$('#userModal').on('shown.bs.modal', function () {
$.ajax({
url: 'fetch_users.php',
method: 'GET',
dataType: 'json',
success: function (data) {
let dropdown = $('#userSelect');
dropdown.empty();
dropdown.append('<option value="">Select a user</option>');
data.forEach(user => {
dropdown.append(`<option value="${user.id}">${user.first_name} ${user.last_name}</option>`);
});
},
error: function () {
alert('Error fetching users.');
}
});
});
// Handle form submission
$('#barTabForm').submit(function (e) {
e.preventDefault(); // Prevent default form submission
$.ajax({
url: 'create_bar_tab.php',
method: 'POST',
data: $(this).serialize(),
success: function (response) {
alert('Bar tab created successfully!');
$('#userModal').modal('hide'); // Close modal
},
error: function () {
alert('Error creating bar tab.');
}
});
});
});
</script>
</body>
</html>

View File

@@ -1,200 +0,0 @@
<?php
require_once("env.php");
require_once("session.php");
require_once("connection.php");
require_once("functions.php");
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
$eft_id = strtoupper($user_id." SUBS ".date("Y")." ".getInitialSurname($user_id));
$status = 'AWAITING PAYMENT';
$description = 'Membership Fees '.date("Y")." ".getInitialSurname($user_id);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
auditLog($user_id, 'CSRF_VALIDATION_FAILED', 'membership_application', null, ['endpoint' => 'process_application.php']);
http_response_code(403);
die('Security token validation failed. Please try again.');
}
// Get all the form fields with validation
$first_name = validateName($_POST['first_name'] ?? '');
if ($first_name === false) {
die('Invalid first name format.');
}
$last_name = validateName($_POST['last_name'] ?? '');
if ($last_name === false) {
die('Invalid last name format.');
}
$id_number = validateSAIDNumber($_POST['id_number'] ?? '');
if ($id_number === false) {
die('Invalid ID number format.');
}
$dob = validateDate($_POST['dob'] ?? '');
if ($dob === false) {
die('Invalid date of birth format.');
}
$occupation = sanitizeTextInput($_POST['occupation'] ?? '', 100);
$tel_cell = validatePhoneNumber($_POST['tel_cell'] ?? '');
if ($tel_cell === false) {
die('Invalid phone number format.');
}
$email = validateEmail($_POST['email'] ?? '');
if ($email === false) {
die('Invalid email format.');
}
// Spouse or Partner details (optional)
$spouse_first_name = !empty($_POST['spouse_first_name']) ? validateName($_POST['spouse_first_name']) : null;
$spouse_last_name = !empty($_POST['spouse_last_name']) ? validateName($_POST['spouse_last_name']) : null;
$spouse_id_number = !empty($_POST['spouse_id_number']) ? validateSAIDNumber($_POST['spouse_id_number']) : null;
$spouse_dob = !empty($_POST['spouse_dob']) ? validateDate($_POST['spouse_dob']) : NULL;
$spouse_occupation = !empty($_POST['spouse_occupation']) ? sanitizeTextInput($_POST['spouse_occupation'], 100) : null;
$spouse_tel_cell = !empty($_POST['spouse_tel_cell']) ? validatePhoneNumber($_POST['spouse_tel_cell']) : null;
$spouse_email = !empty($_POST['spouse_email']) ? validateEmail($_POST['spouse_email']) : null;
// Children details (optional)
$child_name1 = !empty($_POST['child_name1']) ? $_POST['child_name1'] : null;
$child_dob1 = !empty($_POST['child_dob1']) ? $_POST['child_dob1'] : null;
$child_name2 = !empty($_POST['child_name2']) ? $_POST['child_name2'] : null;
$child_dob2 = !empty($_POST['child_dob2']) ? $_POST['child_dob2'] : null;
$child_name3 = !empty($_POST['child_name3']) ? $_POST['child_name3'] : null;
$child_dob3 = !empty($_POST['child_dob3']) ? $_POST['child_dob3'] : null;
// Address and other details
$physical_address = $_POST['physical_address'];
$postal_address = $_POST['postal_address'];
$interests_hobbies = $_POST['interests_hobbies'];
// Primary vehicle details
$vehicle_make = $_POST['vehicle_make'];
$vehicle_model = $_POST['vehicle_model'];
$vehicle_year = $_POST['vehicle_year'];
$vehicle_registration = $_POST['vehicle_registration'];
// Secondary vehicle details (optional)
$secondary_vehicle_make = !empty($_POST['secondary_vehicle_make']) ? $_POST['secondary_vehicle_make'] : null;
$secondary_vehicle_model = !empty($_POST['secondary_vehicle_model']) ? $_POST['secondary_vehicle_model'] : null;
$secondary_vehicle_year = !empty($_POST['secondary_vehicle_year']) ? $_POST['secondary_vehicle_year'] : null;
$secondary_vehicle_registration = !empty($_POST['secondary_vehicle_registration']) ? $_POST['secondary_vehicle_registration'] : null;
// Start a transaction to ensure data consistency
$conn->begin_transaction();
try {
// Insert into the member application table
$stmt = $conn->prepare("INSERT INTO membership_application (
user_id, first_name, last_name, id_number, dob, occupation, tel_cell, email,
spouse_first_name, spouse_last_name, spouse_id_number, spouse_dob, spouse_occupation, spouse_tel_cell, spouse_email,
child_name1, child_dob1, child_name2, child_dob2, child_name3, child_dob3,
physical_address, postal_address, interests_hobbies, vehicle_make, vehicle_model, vehicle_year, vehicle_registration,
secondary_vehicle_make, secondary_vehicle_model, secondary_vehicle_year, secondary_vehicle_registration
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
// Check if preparation was successful
if (!$stmt) {
die("SQL error: " . $conn->error);
}
$stmt->bind_param(
"isssssssssssssssssssssssssssssss",
$user_id,
$first_name,
$last_name,
$id_number,
$dob,
$occupation,
$tel_cell,
$email,
$spouse_first_name,
$spouse_last_name,
$spouse_id_number,
$spouse_dob,
$spouse_occupation,
$spouse_tel_cell,
$spouse_email,
$child_name1,
$child_dob1,
$child_name2,
$child_dob2,
$child_name3,
$child_dob3,
$physical_address,
$postal_address,
$interests_hobbies,
$vehicle_make,
$vehicle_model,
$vehicle_year,
$vehicle_registration,
$secondary_vehicle_make,
$secondary_vehicle_model,
$secondary_vehicle_year,
$secondary_vehicle_registration
);
if ($stmt->execute()) {
// Insert into the membership fees table
$payment_amount = calculateProrata(210); // Assuming a fixed membership fee, adjust as needed
$payment_date = date('Y-m-d');
$membership_start_date = $payment_date;
// $membership_end_date = date('Y-12-31');
// Get today's date
$today = new DateTime();
// Determine the target February
if ($today->format('n') > 2) {
// If we're past February, target is next year's Feb 28/29
$year = $today->format('Y') + 1;
} else {
// Otherwise, this year's February
$year = $today->format('Y');
}
// Handle leap year (Feb 29) automatically
$membership_end_date = (new DateTime("$year-02-01"))
->modify('last day of this month')
->format('Y-m-d');
$stmt = $conn->prepare("INSERT INTO membership_fees (user_id, payment_amount, payment_date, membership_start_date, membership_end_date, payment_status, payment_id)
VALUES (?, ?, ?, ?, ?, 'PENDING', ?)");
$stmt->bind_param("idssss", $user_id, $payment_amount, $payment_date, $membership_start_date, $membership_end_date, $eft_id);
if ($stmt->execute()) {
// Commit the transaction
$conn->commit();
addSubsEFT($eft_id, $user_id, $status, $payment_amount, $description);
sendInvoice(getEmail($user_id), getFullName($user_id), $eft_id, formatCurrency($payment_amount), $description);
sendAdminNotification('4WDCSA.co.za - New Membership Application - '.$last_name , 'A new member has signed up, '.$first_name.' '.$last_name);
header("Location:indemnity.php");
// Success message
$response = [
'status' => 'success',
'message' => 'Your membership application has been submitted successfully!'
];
} else {
throw new Exception("Failed to insert membership fee. SQL error: " . $conn->error);
}
} else {
throw new Exception("Failed to insert member application.SQL error: " . $conn->error);
}
} catch (Exception $e) {
// Rollback the transaction in case of error
$conn->rollback();
// Error response
$response = [
'status' => 'error',
'message' => 'Error: ' . $e->getMessage()
];
}
// Return the response in JSON format
echo json_encode($response);
}
?>

View File

@@ -1,93 +0,0 @@
<?php
require_once("env.php");
require_once("connection.php");
require_once("functions.php");
// Start session to retrieve the logged-in user's ID
session_start();
// Get user ID from session (assuming user is logged in)
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
// Check if the form has been submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
auditLog($user_id, 'CSRF_VALIDATION_FAILED', 'bookings', null, ['endpoint' => 'process_booking.php']);
echo json_encode(['status' => 'error', 'message' => 'Security token validation failed. Please try again.']);
exit();
}
// Validate dates and integers
$from_date = validateDate($_POST['from_date'] ?? '');
if ($from_date === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid from date format.']);
exit();
}
$to_date = validateDate($_POST['to_date'] ?? '');
if ($to_date === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid to date format.']);
exit();
}
$num_vehicles = validateInteger($_POST['vehicles'] ?? 0, 1, 10);
if ($num_vehicles === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid number of vehicles.']);
exit();
}
$num_adults = validateInteger($_POST['adults'] ?? 0, 0, 20);
if ($num_adults === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid number of adults.']);
exit();
}
$num_children = validateInteger($_POST['children'] ?? 0, 0, 20);
if ($num_children === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid number of children.']);
exit();
}
// Get values from the form
$add_firewood = isset($_POST['AddExtra']) ? 1 : 0; // Checkbox for extras
$is_member = isset($_POST['is_member']) ? (int)$_POST['is_member'] : 0; // Hidden member status
$type = "camping";
// Calculate the total number of nights
$date1 = new DateTime($from_date);
$date2 = new DateTime($to_date);
$nights = $date2->diff($date1)->days;
// Determine rate per night
$rate_per_night = ($is_member) ? 0 : 200; // Free for members, R200 for non-members
// Calculate the total cost
$vehicle_cost = $rate_per_night * $num_vehicles * $nights;
$firewood_cost = $add_firewood ? 50 : 0;
$total_amount = $vehicle_cost + $firewood_cost;
// Calculate discount if the user is a member
$discount_amount = ($is_member) ? $vehicle_cost : 0;
// Insert booking into the database
$sql = "INSERT INTO bookings (booking_type, user_id, from_date, to_date, num_vehicles, num_adults, num_children, add_firewood, total_amount, discount_amount)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param('sissiiiidd', $type, $user_id, $from_date, $to_date, $num_vehicles, $num_adults, $num_children, $add_firewood, $total_amount, $discount_amount);
if ($stmt->execute()) {
// Redirect to success page or display success message
echo "<script>alert('Booking successfully created!'); window.location.href = 'booking.php';</script>";
} else {
// Handle error if insert fails
echo "<script>alert('Error processing booking. Please try again later.');</script>";
}
$stmt->close();
$conn->close();
} else {
echo "Invalid request.";
}
?>

View File

@@ -1,144 +0,0 @@
<?php
require_once("env.php");
require_once("connection.php");
require_once("functions.php");
// Start session to retrieve the logged-in user's ID
session_start();
// Get user ID from session (assuming user is logged in)
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
// Validate user session
if (!$user_id) {
echo "<script>alert('User is not logged in. Please log in to make a booking.'); window.location.href = 'login.php';</script>";
exit();
}
$is_member = getUserMemberStatus($user_id);
// Check if the form has been submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
auditLog($user_id, 'CSRF_VALIDATION_FAILED', 'bookings', null, ['endpoint' => 'process_camp_booking.php']);
echo json_encode(['status' => 'error', 'message' => 'Security token validation failed. Please try again.']);
exit();
}
// Validate dates and integers
$from_date = validateDate($_POST['from_date'] ?? '');
if ($from_date === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid from date format.']);
exit();
}
$to_date = validateDate($_POST['to_date'] ?? '');
if ($to_date === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid to date format.']);
exit();
}
$num_vehicles = validateInteger($_POST['vehicles'] ?? 1, 1, 10);
if ($num_vehicles === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid number of vehicles.']);
exit();
}
$num_adults = validateInteger($_POST['adults'] ?? 0, 0, 20);
if ($num_adults === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid number of adults.']);
exit();
}
$num_children = validateInteger($_POST['children'] ?? 0, 0, 20);
if ($num_children === false) {
echo json_encode(['status' => 'error', 'message' => 'Invalid number of children.']);
exit();
}
// Get values from the form
$add_firewood = isset($_POST['AddExtra']) ? 1 : 0; // Checkbox for extras
// $is_member = isset($_POST['is_member']) ? (int)$_POST['is_member'] : 0; // Hidden member status
$type = "camping";
// Calculate the total number of nights
$date1 = new DateTime($from_date);
$date2 = new DateTime($to_date);
$nights = $date2->diff($date1)->days;
// Validate date range
if ($nights <= 0) {
echo "<script>alert('Invalid date range. Please select valid dates.'); window.history.back();</script>";
exit();
}
// Determine rate per night
$rate_per_night = 200; // Free for members, R200 for non-members
// Calculate the total cost
$vehicle_cost = $rate_per_night * $num_vehicles * $nights;
$total_discount = $is_member ? $vehicle_cost : 0;
$firewood_cost = $add_firewood ? 50 : 0;
$total_amount = $vehicle_cost + $firewood_cost;
$payment_amount = $total_amount - $total_discount;
$status = "AWAITING PAYMENT";
$description = "BASE4 Camping";
$payment_id = uniqid();
$eft_id = strtoupper($trip_code." ".getLastName($user_id));
// Insert booking into the database
$sql = "INSERT INTO bookings (booking_type, user_id, from_date, to_date, num_vehicles, num_adults, num_children, add_firewood, total_amount, discount_amount, status, payment_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param('sissiiiiddss', $type, $user_id, $from_date, $to_date, $num_vehicles, $num_adults, $num_children, $add_firewood, $total_amount, $total_discount, $status, $payment_id);
if ($stmt->execute()) {
$booking_id = $conn->insert_id;
if ($payment_amount < 1) {
if (processZeroPayment($payment_id, $payment_amount, $description)) {
echo "<script>alert('Booking successfully created!'); window.location.href = 'bookings.php';</script>";
} else {
$error_message = $stmt->error;
echo "Error processing booking: $error_message";
}
} else {
addEFT($eft_id, $booking_id, $user_id, $status, $payment_amount, $description);
header("Location: payment_confirmation.php?booking_id=".$booking_id);
exit(); // Ensure no further code is executed after the redirect
}
} else {
// Handle error if insert fails and echo the MySQL error
$error_message = $stmt->error;
echo "Error processing booking: $error_message";
}
// if ($stmt->execute()) {
// if ($payment_amount < 1) {
// if (processZeroPayment($payment_id, $payment_amount, $description)) {
// echo "<script>alert('Booking successfully created!'); window.location.href = 'bookings.php';</script>";
// } else {
// $error_message = $stmt->error;
// echo "Error processing booking: $error_message";
// }
// } else {
// if (processPayment($payment_id, $payment_amount, $description)) {
// echo "<script>alert('Booking successfully created!'); window.location.href = 'bookings.php';</script>";
// } else {
// $error_message = $stmt->error;
// echo "Error processing booking: $error_message";
// }
// }
// } else {
// // Handle error if insert fails and echo the MySQL error
// $error_message = $stmt->error;
// echo "Error processing booking: $error_message";
// }
$stmt->close();
$conn->close();
} else {
echo "Invalid request.";
}

View File

@@ -1,143 +0,0 @@
<?php
require_once("env.php");
require_once("connection.php");
require_once("functions.php");
session_start();
// Get user ID from session (assuming user is logged in)
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
// Validate user session
if (!$user_id) {
echo "<script>alert('User is not logged in. Please log in to make a booking.'); window.location.href = 'login.php';</script>";
exit();
}
$is_member = getUserMemberStatus($user_id);
$pending_member = getUserMemberStatusPending($user_id);
// Check if the form has been submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
auditLog($user_id, 'CSRF_VALIDATION_FAILED', 'bookings', null, ['endpoint' => 'process_course_booking.php']);
http_response_code(403);
header('Content-Type: application/json');
echo json_encode(['error' => 'Security token validation failed.']);
exit();
}
// Input variables from the form (use default values if not provided)
$additional_members = validateInteger($_POST['members'] ?? 0, 0, 20);
if ($additional_members === false) $additional_members = 0;
$num_adults = validateInteger($_POST['non-members'] ?? 0, 0, 20);
if ($num_adults === false) $num_adults = 0;
$course_id = validateInteger($_POST['course_id'] ?? 0, 1, 999999);
if ($course_id === false) {
http_response_code(400);
header('Content-Type: application/json');
echo json_encode(['error' => 'Invalid course ID.']);
exit();
}
checkAndRedirectCourseBooking($course_id);
// Fetch trip costs from the database
$query = "SELECT date, cost_members, cost_nonmembers, course_type FROM courses WHERE course_id = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param('i', $course_id);
$stmt->execute();
$result = $stmt->get_result();
// Check if trip exists
if ($result->num_rows === 0) {
$response = ['error' => 'Trip not found.'];
header('Content-Type: application/json');
echo json_encode($response);
exit();
}
// Fetch trip details
$course = $result->fetch_assoc();
$type = $course['course_type'];
$date = $course['date'];
$cost_members = intval($course['cost_members']);
$cost_nonmembers = intval($course['cost_nonmembers']);
if ($type === "driver_training") {
$description = "Basic 4X4 Driver Training Course " . $date;
} elseif ($type === "bush_mechanics") {
$description = "Bush Mechanics Course " . $date;
} elseif ($type === "rescue_recovery") {
$description = "Rescue & Recovery Training Course " . $date;
} else {
$description = "General Course " . $date; // Default fallback description
}
// Initialize total and discount amount
$total = 0;
// Calculate total based on membership
if ($is_member || $pending_member) {
$num_members = 1 + $additional_members;
$total = ($num_members * $cost_members) + ($num_adults * $cost_nonmembers);
$payment_amount = $total;
} else {
$num_members = 0;
$total = (($cost_nonmembers) + ($num_adults * $cost_nonmembers));
$payment_amount = $total;
$num_adults = $num_adults + 1;
}
$status = "AWAITING PAYMENT";
$type = 'course';
$payment_id = uniqid();
$num_vehicles = 1;
$discountAmount = 0;
$eft_id = strtoupper("COURSE ".date("m-d", strtotime($date))." ".getInitialSurname($user_id));
$notes = "";
if ($pending_member){
$notes = "Membership Payment pending at time of booking. Please confirm payment has been received.";
}
// Insert booking into the database
$sql = "INSERT INTO bookings (booking_type, user_id, from_date, to_date, num_vehicles, num_adults, total_amount, discount_amount, status, payment_id, course_id, course_non_members, eft_id, notes)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
if (!$stmt) {
die("Preparation failed: " . $conn->error);
}
$stmt->bind_param('sissiiddssiiss', $type, $user_id, $date, $date, $num_vehicles, $num_members, $total, $discountAmount, $status, $payment_id, $course_id, $num_adults, $eft_id, $notes);
if ($stmt->execute()) {
$booking_id = $conn->insert_id;
if ($payment_amount < 1) {
if (processZeroPayment($payment_id, $payment_amount, $description)) {
echo "<script>alert('Booking successfully created!'); window.location.href = 'bookings.php';</script>";
} else {
$error_message = $stmt->error;
echo "Error processing booking: $error_message";
}
} else {
addEFT($eft_id, $booking_id, $user_id, $status, $payment_amount, $description);
sendInvoice(getEmail($user_id), getFullName($user_id), $eft_id, formatCurrency($payment_amount), $description);
sendAdminNotification('New Course Booking - '.getFullName($user_id), getFullName($user_id).' has booked for '.$description);
header("Location: payment_confirmation.php?token=".encryptData($booking_id, $salt));
exit(); // Ensure no further code is executed after the redirect
}
} else {
// Handle error if insert fails and echo the MySQL error
$error_message = $stmt->error;
echo "Error processing booking: $error_message";
}
$stmt->close();
$conn->close();
} else {
echo "Invalid request.";
}

View File

@@ -1,97 +0,0 @@
<?php
require_once("env.php");
require_once("session.php");
require_once("connection.php");
require_once("functions.php");
checkAdmin();
// CSRF Token Validation for POST requests
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
auditLog($_SESSION['user_id'] ?? null, 'CSRF_VALIDATION_FAILED', 'efts', null, ['endpoint' => 'process_eft.php']);
http_response_code(403);
die('Security token validation failed.');
}
}
if (!isset($_GET['token']) || empty($_GET['token'])) {
die("Invalid request.");
}
$token = $_GET['token'];
// echo $token;
$eft_id = decryptData($token, $salt);
$user = getUserIdFromEFT($eft_id);
// echo $eft_id;
// Start transaction for atomicity
$conn->begin_transaction();
try {
// Update the efts table to set status = 'PAID'
$updateEFT = "UPDATE efts SET status = 'PAID' WHERE eft_id = ?";
$stmt = $conn->prepare($updateEFT);
if (!$stmt) {
throw new Exception("Prepare failed: " . $conn->error);
}
$stmt->bind_param("s", $eft_id);
if (!$stmt->execute()) {
throw new Exception("EFT update failed: " . $stmt->error);
}
$stmt->close();
// Retrieve the booking_id from efts table
$getBooking = "SELECT booking_id FROM efts WHERE eft_id = ?";
$stmt = $conn->prepare($getBooking);
if (!$stmt) {
throw new Exception("Prepare failed: " . $conn->error);
}
$stmt->bind_param("s", $eft_id);
$stmt->execute();
$stmt->bind_result($booking_id);
$stmt->fetch();
$stmt->close();
if (!empty($booking_id)) {
// Update the bookings table if booking_id exists
$updateBooking = "UPDATE bookings SET status = 'PAID' WHERE booking_id = ?";
$stmt = $conn->prepare($updateBooking);
if (!$stmt) {
throw new Exception("Prepare failed: " . $conn->error);
}
$stmt->bind_param("i", $booking_id);
if (!$stmt->execute()) {
throw new Exception("Booking update failed: " . $stmt->error);
}
} else {
// If no booking_id is found, update membership_fees instead
$updateMembership = "UPDATE membership_fees SET payment_status = 'PAID' WHERE payment_id = ?";
$stmt = $conn->prepare($updateMembership);
if (!$stmt) {
throw new Exception("Prepare failed: " . $conn->error);
}
$stmt->bind_param("s", $eft_id);
if (!$stmt->execute()) {
throw new Exception("Membership fee update failed: " . $stmt->error);
}
}
$stmt->close();
// Commit transaction if everything was successful
$conn->commit();
sendPaymentConfirmation(getEmail($user), getFullName($user), getEftDescription($eft_id));
header("Location: admin_efts.php");
exit(); // Ensure no further code is executed after the redirect
} catch (Exception $e) {
// Rollback transaction if an error occurs
$conn->rollback();
echo "Error: " . $e->getMessage();
}
// Close database connection
$conn->close();

View File

@@ -1,76 +0,0 @@
<?php
require_once("env.php");
require_once("connection.php");
require_once("functions.php");
// Start session to retrieve the logged-in user's ID
session_start();
// Get user ID from session (assuming user is logged in)
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
// Validate user session
if (!$user_id) {
echo "<script>alert('User is not logged in. Please log in to make a booking.'); window.location.href = 'login.php';</script>";
exit();
}
$is_member = getUserMemberStatus($user_id);
$query = "SELECT payment_amount, payment_status, membership_end_date FROM membership_fees WHERE user_id = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param('i', $user_id);
$stmt->execute();
$result = $stmt->get_result();
// Check if trip exists
if ($result->num_rows === 0) {
$response = ['error' => 'Application Fee not found.'];
header('Content-Type: application/json');
echo json_encode($response);
exit();
}
// Fetch trip details
$fee = $result->fetch_assoc();
$payment_status = $fee['payment_status'];
$membership_end_date = $fee['membership_end_date'];
$payment_amount = intval($fee['payment_amount']);
$description = "4WDCSA: Membership Fee " . getFullName($user_id) . " " . date("Y");
$payment_id = uniqid();
$eft_id = "SUBS 2025 ".getLastName($user_id);
// Update the membership_fees table to set payment_id
$stmt = $conn->prepare("UPDATE membership_fees SET payment_id = ? WHERE user_id = ?");
if ($stmt) {
$stmt->bind_param("ss", $payment_id, $user_id);
if (!$stmt->execute()) {
throw new Exception("Failed to update membership_fees table.");
}
$stmt->close();
$conn->close();
} else {
throw new Exception("Failed to prepare statement for membership_fees table: " . $conn->error);
}
// Get the current date
$current_date = new DateTime();
// Convert $membership_end_date to a DateTime object
$membership_end_date_obj = DateTime::createFromFormat('Y-m-d', $membership_end_date);
// Check if the current date is after membership_end_date
// OR if the current date is before or on membership_end_date AND payment_status is "PENDING"
if (
$current_date > $membership_end_date_obj ||
($current_date <= $membership_end_date_obj && $payment_status === "PENDING")
) {
// Call the processMembershipPayment function
// processMembershipPayment($payment_id, $payment_amount, $description);
addMembershipEFT($eft_id, $user_id, $status, $amount, $description, $membershipfee_id);
header("Location: payment_confirmation.php?booking_id=" . $booking_id);
exit(); // Ensure no further code is executed after the redirect
}

View File

@@ -1,151 +0,0 @@
<?php
$headerStyle = 'light';
include_once('header.php');
checkAdmin();
checkUserSession();
$user_id = $_SESSION['user_id'];
?>
<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 */
}
.message-box {
text-align: center;
position: relative;
padding: 10px;
padding-right: 35px;
/* Ensures text doesn't overlap with the close button */
}
.close-btn {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
/* Centers vertically */
cursor: pointer;
font-size: 20px;
font-weight: bold;
color: #333;
background: none;
border: none;
}
.close-btn:hover {
color: red;
}
</style>
</style>
<?php
$status = "PROCESSING";
$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">Process 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">Process Payments</li>
</ol>
</nav>
</div>
</div>
</section>
<!-- Tour List Area start -->
<section class="tour-list-page py-100 rel z-1">
<div class="container">
<div class="row">
<div class="col-lg-12">
<?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'">&times;</span>
</div>
<?php unset($_SESSION['message']); ?>
<?php endif; ?>
<?php
// Query to retrieve data from the bookings table
$sql = "SELECT * FROM efts WHERE status = ? ORDER BY timestamp DESC";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $status);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
// Loop through each row
while ($row = $result->fetch_assoc()) {
$eft_id = $row['eft_id'];
$file_name = str_replace(' ', '_', $eft_id);
$eft_user = $row['user_id'];
$eft_amount = $row['amount'];
$eft_description = $row['description'];
// 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="p-4" >
<iframe src="uploads/pop/'.$file_name.'.pdf#toolbar=0" width="400px" height="200px"></iframe>
<p><a href="uploads/pop/'.$file_name.'.pdf" target="_new" class="theme-btn style-three" style="width:100%;">View Full PDF</a></p>
</div>
<div style="width:100%;" class="content">
<h5>' . htmlspecialchars($eft_description) . '</a></h5>
<h5>' . getFullName($eft_user) . '</a></h5>
<div class="destination-footer">
<span class="price"><span>Booking Total: R ' . number_format($eft_amount, 2) . '</span></span>
<a href="process_eft.php?token=' . encryptData($eft_id, $salt) . '" class="theme-btn style-three"><span data-hover="POP RECEIVED">PROCESS</span></a>
</div>
</div>';
}
} else {
echo '<p>There are no pending payments for processing.</p>';
}
// Close connection
$conn->close();
?>
</div>
</div>
</div>
</section>
<!-- Tour List Area end -->
<?php include_once("insta_footer.php"); ?>

View File

@@ -1,68 +0,0 @@
<?php
require_once("env.php");
require_once("session.php");
require_once("connection.php");
require_once("functions.php");
if (!isset($_SESSION['user_id'])) {
die(json_encode(['status' => 'error', 'message' => 'User not logged in']));
}
if (isset($_POST['signature'])) {
// CSRF Token Validation
// if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
// auditLog($_SESSION['user_id'], 'CSRF_VALIDATION_FAILED', 'membership_application', null, ['endpoint' => 'process_signature.php']);
// die(json_encode(['status' => 'error', 'message' => 'Security token validation failed']));
// }
$user_id = $_SESSION['user_id']; // Get the user ID from the session
$signature = $_POST['signature']; // Base64 image data
// Decode the base64 image
$signature = str_replace('data:image/png;base64,', '', $signature);
$signature = str_replace(' ', '+', $signature);
$signatureData = base64_decode($signature);
// Create a file path for the signature image
$fileName = 'signature_' . $user_id . '.png';
$filePath = 'uploads/signatures/' . $fileName;
// Ensure the directory exists
if (!is_dir('uploads/signatures')) {
mkdir('uploads/signatures', 0777, true);
}
// Save the image file
if (file_put_contents($filePath, $signatureData)) {
// Update the database
if ($conn->connect_error) {
die(json_encode(['status' => 'error', 'message' => 'Database connection failed']));
}
// Update the signature and indemnity acceptance in the membership application table
$stmt = $conn->prepare("UPDATE membership_application SET sig = ?, accept_indemnity = 1 WHERE user_id = ?");
$stmt->bind_param('si', $filePath, $user_id);
if ($stmt->execute()) {
// Check the payment status
$paymentStatus = checkMembershipPaymentStatus($user_id) ? 'PAID' : 'NOT_PAID';
// Respond with the appropriate redirect URL based on the payment status
echo json_encode([
'status' => 'success',
'message' => 'Signature saved successfully!',
'paymentStatus' => $paymentStatus // Send payment status
]);
} else {
echo json_encode(['status' => 'error', 'message' => 'Database update failed']);
}
$stmt->close();
$conn->close();
} else {
echo json_encode(['status' => 'error', 'message' => 'Failed to save signature']);
}
} else {
echo json_encode(['status' => 'error', 'message' => 'Signature not provided']);
}

View File

@@ -1,170 +0,0 @@
<?php
require_once("env.php");
require_once("connection.php");
require_once("functions.php");
session_start();
// Get the trip_id from the request (ensure it's sanitized)
$trip_id = isset($_POST['trip_id']) ? intval($_POST['trip_id']) : 0;
checkAndRedirectBooking($trip_id);
// Check available spaces
$available_spaces = getAvailableSpaces($trip_id); // Assuming you're using MySQLi and the function is updated for it
if ($available_spaces < 1) {
// Redirect back to trips.php with an error message
header("Location: trips.php?error=fully_booked");
exit();
}
// Get user ID from session (assuming user is logged in)
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
// Validate user session
if (!$user_id) {
echo "<script>alert('User is not logged in. Please log in to make a booking.'); window.location.href = 'login.php';</script>";
exit();
}
$is_member = getUserMemberStatus($user_id);
// Check if the form has been submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
auditLog($user_id, 'CSRF_VALIDATION_FAILED', 'bookings', null, ['endpoint' => 'process_trip_booking.php']);
http_response_code(403);
header('Content-Type: application/json');
echo json_encode(['error' => 'Security token validation failed.']);
exit();
}
// Input variables from the form (use default values if not provided)
$num_vehicles = validateInteger($_POST['vehicles'] ?? 1, 1, 10);
if ($num_vehicles === false) $num_vehicles = 1;
$num_adults = validateInteger($_POST['adults'] ?? 1, 1, 20);
if ($num_adults === false) $num_adults = 1;
$num_children = validateInteger($_POST['children'] ?? 0, 0, 20);
if ($num_children === false) $num_children = 0;
$num_pensioners = validateInteger($_POST['pensioners'] ?? 0, 0, 20);
if ($num_pensioners === false) $num_pensioners = 0;
// Fetch trip costs from the database
$query = "SELECT trip_name, cost_members, cost_nonmembers, cost_pensioner_member, cost_pensioner, booking_fee, start_date, end_date, trip_code FROM trips WHERE trip_id = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param('i', $trip_id);
$stmt->execute();
$result = $stmt->get_result();
// Check if trip exists
if ($result->num_rows === 0) {
$response = ['error' => 'Trip not found.'];
header('Content-Type: application/json');
echo json_encode($response);
exit();
}
// Fetch trip details
$trip = $result->fetch_assoc();
$trip_code = $trip['trip_code'];
$trip_name = $trip['trip_name'];
$cost_members = intval($trip['cost_members']);
$cost_nonmembers = intval($trip['cost_nonmembers']);
$cost_pensioner_member = intval($trip['cost_pensioner_member']);
$cost_pensioner = intval($trip['cost_pensioner']);
$member_discount = $cost_nonmembers - $cost_members;
$member_discount_pensioner = $cost_pensioner - $cost_pensioner_member;
$booking_fee = $trip['booking_fee'];
$radioCost = $radio ? 50 : 0;
$start_date = $trip['start_date']; // Start date of the trip
$end_date = $trip['end_date']; // End date of the trip
// Assume the membership status is determined elsewhere
$is_member = getUserMemberStatus($user_id);
// Initialize total and discount amount
$total = 0;
$discountAmount = 0;
// Calculate total based on membership
if ($is_member) {
$total = (($num_adults + $num_children) * $cost_nonmembers) + ($num_pensioners * $cost_pensioner) + $radioCost + ($num_vehicles * $booking_fee);
$discountAmount = (($num_adults + $num_children) * $member_discount) + ($num_pensioners * $member_discount_pensioner );
$payment_amount = $total - $discountAmount;
} else {
$total = (($num_adults + $num_children) * $cost_nonmembers) + ($num_pensioners * $cost_pensioner) + $radioCost + ($num_vehicles * $booking_fee);
$payment_amount = $total;
}
$status = "AWAITING PAYMENT";
$description = $trip_name;
$type = 'trip';
$payment_id = uniqid();
// $eft_id = strtoupper(base_convert(time(), 10, 36)); // Convert timestamp to base36
$eft_id = strtoupper($trip_code." ".getInitialSurname($user_id));
// Insert booking into the database
$sql = "INSERT INTO bookings (booking_type, user_id, from_date, to_date, num_vehicles, num_adults, num_children, total_amount, discount_amount, status, payment_id, trip_id, radio, eft_id, num_pensioners)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
if (!$stmt) {
die("Preparation failed: " . $conn->error);
}
$stmt->bind_param('sissiiiddssiisi', $type, $user_id, $start_date, $end_date, $num_vehicles, $num_adults, $num_children, $total, $discountAmount, $status, $payment_id, $trip_id, $radio, $eft_id, $num_pensioners);
if ($stmt->execute()) {
// Get the generated booking_id
$booking_id = $conn->insert_id;
if ($payment_amount < 1) {
if (processZeroPayment($payment_id, $payment_amount, $description)) {
echo "<script>alert('Booking successfully created!'); window.location.href = 'bookings.php';</script>";
} else {
$error_message = $stmt->error;
echo "Error processing booking: $error_message";
}
} else {
addEFT($eft_id, $booking_id, $user_id, $status, $payment_amount, $description);
sendAdminNotification('New Trip Booking - '.getFullName($user_id), getFullName($user_id).' has booked for '.$description);
header("Location: payment_confirmation.php?token=".encryptData($booking_id, $salt));
exit(); // Ensure no further code is executed after the redirect
}
} else {
// Handle error if insert fails and echo the MySQL error
$error_message = $stmt->error;
echo "Error processing booking: $error_message";
}
// if ($stmt->execute()) {
// if ($payment_amount < 1) {
// if (processZeroPayment($payment_id, $payment_amount, $description)) {
// echo "<script>alert('Booking successfully created!'); window.location.href = 'bookings.php';</script>";
// } else {
// $error_message = $stmt->error;
// echo "Error processing booking: $error_message";
// }
// } else {
// if (processPayment($payment_id, $payment_amount, $description)) {
// echo "<script>alert('Booking successfully created!'); window.location.href = 'bookings.php';</script>";
// } else {
// $error_message = $stmt->error;
// echo "Error processing booking: $error_message";
// }
// }
// } else {
// // Handle error if insert fails and echo the MySQL error
// $error_message = $stmt->error;
// echo "Error processing booking: $error_message";
// }
$stmt->close();
$conn->close();
} else {
echo "Invalid request.";
}

View File

@@ -1,145 +0,0 @@
<?php
require_once("env.php");
require_once("session.php");
require_once("connection.php");
require_once("functions.php");
require_once "vendor/autoload.php";
use GuzzleHttp\Client;
// Create connection
$conn = openDatabaseConnection();
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Form processing
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
auditLog(null, 'CSRF_VALIDATION_FAILED', 'users', null, ['endpoint' => 'register_user.php']);
echo json_encode(['status' => 'error', 'message' => 'Security token validation failed. Please try again.']);
exit();
}
// Check rate limiting on registration endpoint (by IP)
$ip = getClientIPAddress();
$cutoffTime = date('Y-m-d H:i:s', time() - (3600)); // Last hour
$stmt = $conn->prepare("SELECT COUNT(*) as count FROM audit_log WHERE action = 'REGISTRATION_ATTEMPT' AND ip_address = ? AND created_at > ?");
$stmt->bind_param('ss', $ip, $cutoffTime);
$stmt->execute();
$stmt->bind_result($regAttempts);
$stmt->fetch();
$stmt->close();
// Allow max 5 registration attempts per IP per hour
if ($regAttempts >= 5) {
auditLog(null, 'REGISTRATION_RATE_LIMIT_EXCEEDED', 'users', null, ['ip' => $ip, 'attempts' => $regAttempts]);
echo json_encode(['status' => 'error', 'message' => 'Too many registration attempts. Please try again later.']);
exit();
}
// Validate and sanitize first name
$first_name = validateName($_POST['first_name'] ?? '');
if ($first_name === false) {
auditLog(null, 'REGISTRATION_INVALID_FIRST_NAME', 'users');
echo json_encode(['status' => 'error', 'message' => 'Invalid first name. Only letters, spaces, hyphens, and apostrophes allowed (2-100 characters).']);
exit();
}
// Validate and sanitize last name
$last_name = validateName($_POST['last_name'] ?? '');
if ($last_name === false) {
auditLog(null, 'REGISTRATION_INVALID_LAST_NAME', 'users');
echo json_encode(['status' => 'error', 'message' => 'Invalid last name. Only letters, spaces, hyphens, and apostrophes allowed (2-100 characters).']);
exit();
}
// Validate and sanitize phone number
$phone_number = validatePhoneNumber($_POST['phone_number'] ?? '');
if ($phone_number === false) {
auditLog(null, 'REGISTRATION_INVALID_PHONE', 'users');
echo json_encode(['status' => 'error', 'message' => 'Invalid phone number format.']);
exit();
}
// Validate email
$email = validateEmail($_POST['email'] ?? '');
if ($email === false) {
auditLog(null, 'REGISTRATION_INVALID_EMAIL', 'users');
echo json_encode(['status' => 'error', 'message' => 'Invalid email format.']);
exit();
}
$password = $_POST['password'] ?? '';
$password_confirm = $_POST['password_confirm'] ?? '';
// Validate password strength (minimum 8 characters, must contain uppercase, lowercase, number, special char)
if (strlen($password) < 8) {
echo json_encode(['status' => 'error', 'message' => 'Password must be at least 8 characters long.']);
exit();
}
if (!preg_match('/[A-Z]/', $password) || !preg_match('/[a-z]/', $password) ||
!preg_match('/[0-9]/', $password) || !preg_match('/[!@#$%^&*]/', $password)) {
echo json_encode(['status' => 'error', 'message' => 'Password must contain uppercase, lowercase, number, and special character (!@#$%^&*).']);
exit();
}
if ($password !== $password_confirm) {
echo json_encode(['status' => 'error', 'message' => 'Passwords do not match.']);
exit();
}
// Check if the email is already registered
$stmt = $conn->prepare('SELECT user_id FROM users WHERE email = ?');
$stmt->bind_param('s', $email);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
auditLog(null, 'REGISTRATION_EMAIL_EXISTS', 'users', null, ['email' => $email]);
echo json_encode(['status' => 'error', 'message' => 'Email is already registered.']);
$stmt->close();
$conn->close();
exit();
}
$stmt->close();
// Hash password
$hashed_password = password_hash($password, PASSWORD_BCRYPT);
// Generate email verification token
$token = bin2hex(random_bytes(50));
// Prepare and execute query
$stmt = $conn->prepare('INSERT INTO users (first_name, last_name, phone_number, email, password, token, is_verified, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
$is_verified = 0; // Not verified
$type = 'credentials';
$stmt->bind_param('ssssssis', $first_name, $last_name, $phone_number, $email, $hashed_password, $token, $is_verified, $type);
if ($stmt->execute()) {
$newUser_id = $conn->insert_id;
processLegacyMembership($newUser_id);
auditLog($newUser_id, 'USER_REGISTRATION', 'users', $newUser_id, ['email' => $email]);
if (sendVerificationEmail($email, $first_name . ' ' . $last_name, $token)) {
sendEmail($_ENV['ADMIN_EMAIL'], '4WDCSA: New User Registration', $first_name . ' ' . $last_name . ' (' . $email . ') has just created an account using Credentials.');
echo json_encode(['status' => 'success', 'message' => 'Registration successful. Please check your email to verify your account.']);
} else {
echo json_encode(['status' => 'error', 'message' => 'Failed to send verification email.']);
}
} else {
auditLog(null, 'REGISTRATION_DATABASE_ERROR', 'users', null, ['email' => $email]);
echo json_encode(['status' => 'error', 'message' => 'Failed to register user.']);
}
$stmt->close();
}
$conn->close();

View File

@@ -1,47 +0,0 @@
<?php
require_once("env.php");
require_once("connection.php");
require_once("functions.php");
$response = array('status' => 'error', 'message' => 'Something went wrong');
if (isset($_POST['email'])) {
$email = $_POST['email'];
// Check if the email exists
$sql = "SELECT user_id FROM users WHERE email = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $email);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$user = $result->fetch_assoc();
$user_id = $user['user_id'];
// Generate a unique token
$token = bin2hex(random_bytes(50));
// Store the token and expiration time in the database
$expiry = date("Y-m-d H:i:s", strtotime('+3 hour')); // Token expires in 1 hour
$sql = "INSERT INTO password_resets (user_id, token, expires_at) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE token = VALUES(token), expires_at = VALUES(expires_at)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("iss", $user_id, $token, $expiry);
$stmt->execute();
// Send the reset link to the user
$reset_link = "https://www.4wdcsa.co.za/reset_password.php?token=$token";
$subject = "Password Reset Request";
$message = "Click the following link to reset your password: $reset_link";
sendEmail($email, $subject, $message);
$response['status'] = 'success';
$response['message'] = 'Password reset link has been sent to your email.';
} else {
$response['message'] = 'Email not found.';
}
}
echo json_encode($response);
?>

View File

@@ -1,94 +1,95 @@
<?php include_once('connection.php'); <?php include_once('../config/connection.php');
include_once('functions.php'); include_once('../config/functions.php');
require_once("env.php"); require_once("../config/env.php");
session_start(); session_start();
$user_id = $_SESSION['user_id'] ?? null; $user_id = $_SESSION['user_id'] ?? null;
// CSRF Token Validation // CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) { if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
http_response_code(403); http_response_code(403);
die('Security token validation failed. Please try again.'); die('Security token validation failed. Please try again.');
} }
// campsites.php // campsites.php
$conn = openDatabaseConnection(); $conn = openDatabaseConnection();
// Get text inputs // Get text inputs
$name = validateName($_POST['name'] ?? '') ?: ''; $name = validateName($_POST['name'] ?? '') ?: '';
$desc = isset($_POST['description']) ? htmlspecialchars($_POST['description'], ENT_QUOTES, 'UTF-8') : ''; $desc = isset($_POST['description']) ? htmlspecialchars($_POST['description'], ENT_QUOTES, 'UTF-8') : '';
$lat = isset($_POST['latitude']) ? floatval($_POST['latitude']) : 0.0; $lat = isset($_POST['latitude']) ? floatval($_POST['latitude']) : 0.0;
$lng = isset($_POST['longitude']) ? floatval($_POST['longitude']) : 0.0; $lng = isset($_POST['longitude']) ? floatval($_POST['longitude']) : 0.0;
$website = isset($_POST['website']) ? filter_var($_POST['website'], FILTER_VALIDATE_URL) : ''; $website = isset($_POST['website']) ? filter_var($_POST['website'], FILTER_VALIDATE_URL) : '';
$telephone = validatePhoneNumber($_POST['telephone'] ?? '') ?: ''; $telephone = validatePhoneNumber($_POST['telephone'] ?? '') ?: '';
if (empty($name)) { if (empty($name)) {
http_response_code(400); http_response_code(400);
die('Campsite name is required.'); die('Campsite name is required.');
} }
// Handle file upload // Handle file upload
$thumbnailPath = null; $thumbnailPath = null;
if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] !== UPLOAD_ERR_NO_FILE) { if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] !== UPLOAD_ERR_NO_FILE) {
// Validate file using hardened validation function // Validate file using hardened validation function
$validationResult = validateFileUpload($_FILES['thumbnail'], 'profile_picture'); $validationResult = validateFileUpload($_FILES['thumbnail'], 'profile_picture');
if ($validationResult === false) { if ($validationResult === false) {
http_response_code(400); http_response_code(400);
die('Invalid thumbnail image. Only JPG, JPEG, PNG, GIF, and WEBP images under 5MB are allowed.'); die('Invalid thumbnail image. Only JPG, JPEG, PNG, GIF, and WEBP images under 5MB are allowed.');
} }
$uploadDir = "assets/uploads/campsites/"; $uploadDir = "assets/uploads/campsites/";
if (!is_dir($uploadDir)) { if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true); mkdir($uploadDir, 0755, true);
} }
if (!is_writable($uploadDir)) { if (!is_writable($uploadDir)) {
http_response_code(500); http_response_code(500);
die('Upload directory is not writable.'); die('Upload directory is not writable.');
} }
$randomFilename = $validationResult['filename']; $randomFilename = $validationResult['filename'];
$targetFile = $uploadDir . $randomFilename; $targetFile = $uploadDir . $randomFilename;
if (move_uploaded_file($_FILES["thumbnail"]["tmp_name"], $targetFile)) { if (move_uploaded_file($_FILES["thumbnail"]["tmp_name"], $targetFile)) {
chmod($targetFile, 0644); chmod($targetFile, 0644);
$thumbnailPath = $targetFile; $thumbnailPath = $targetFile;
} else { } else {
http_response_code(500); http_response_code(500);
die('Failed to move uploaded file.'); die('Failed to move uploaded file.');
} }
} }
$id = isset($_POST['id']) ? intval($_POST['id']) : 0; $id = isset($_POST['id']) ? intval($_POST['id']) : 0;
if ($id > 0) { if ($id > 0) {
// UPDATE // UPDATE
if ($thumbnailPath) { if ($thumbnailPath) {
$stmt = $conn->prepare("UPDATE campsites SET name=?, description=?, latitude=?, longitude=?, website=?, telephone=?, thumbnail=? WHERE id=?"); $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); $stmt->bind_param("ssddsssi", $name, $desc, $lat, $lng, $website, $telephone, $thumbnailPath, $id);
} else { } else {
$stmt = $conn->prepare("UPDATE campsites SET name=?, description=?, latitude=?, longitude=?, website=?, telephone=? WHERE id=?"); $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); $stmt->bind_param("ssddssi", $name, $desc, $lat, $lng, $website, $telephone, $id);
} }
// Log the action // Log the action
auditLog($user_id, 'CAMPSITE_UPDATE', 'campsites', $id, ['name' => $name]); auditLog($user_id, 'CAMPSITE_UPDATE', 'campsites', $id, ['name' => $name]);
} else { } else {
// INSERT // INSERT
$stmt = $conn->prepare("INSERT INTO campsites (name, description, latitude, longitude, website, telephone, thumbnail, user_id) $stmt = $conn->prepare("INSERT INTO campsites (name, description, latitude, longitude, website, telephone, thumbnail, user_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param("ssddsssi", $name, $desc, $lat, $lng, $website, $telephone, $thumbnailPath, $user_id); $stmt->bind_param("ssddsssi", $name, $desc, $lat, $lng, $website, $telephone, $thumbnailPath, $user_id);
// Log the action // Log the action
auditLog($user_id, 'CAMPSITE_CREATE', 'campsites', 0, ['name' => $name]); auditLog($user_id, 'CAMPSITE_CREATE', 'campsites', 0, ['name' => $name]);
} }
if (!$stmt->execute()) { if (!$stmt->execute()) {
http_response_code(500); http_response_code(500);
die('Database error: ' . $stmt->error); die('Database error: ' . $stmt->error);
} }
$stmt->close(); $stmt->close();
header("Location: campsites.php"); header("Location: campsites.php");
?> ?>

View File

@@ -1,226 +1,227 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(__DIR__));
checkAdmin(); include_once($rootPath . '/header.php');
checkAdmin();
?>
<style> ?>
table { <style>
width: 100%; table {
border-collapse: separate; width: 100%;
border-spacing: 0; border-collapse: separate;
margin: 10px 0; border-spacing: 0;
} margin: 10px 0;
}
thead th {
cursor: pointer; thead th {
text-align: left; cursor: pointer;
padding: 10px; text-align: left;
font-weight: bold; padding: 10px;
position: relative; font-weight: bold;
} position: relative;
}
thead th::after {
content: '\25B2'; thead th::after {
/* Up arrow */ content: '\25B2';
font-size: 0.8em; /* Up arrow */
position: absolute; font-size: 0.8em;
right: 10px; position: absolute;
opacity: 0; right: 10px;
transition: opacity 0.2s; opacity: 0;
} transition: opacity 0.2s;
}
thead th.asc::after {
content: '\25B2'; thead th.asc::after {
/* Up arrow */ content: '\25B2';
opacity: 1; /* Up arrow */
} opacity: 1;
}
thead th.desc::after {
content: '\25BC'; thead th.desc::after {
/* Down arrow */ content: '\25BC';
opacity: 1; /* Down arrow */
} opacity: 1;
}
tbody tr:nth-child(odd) {
background-color: transparent; tbody tr:nth-child(odd) {
} background-color: transparent;
}
tbody tr:nth-child(even) {
background-color: rgb(255, 255, 255); tbody tr:nth-child(even) {
border-radius: 10px; background-color: rgb(255, 255, 255);
} border-radius: 10px;
}
tbody td {
padding: 5px; tbody td {
} padding: 5px;
}
tbody tr:nth-child(even) td:first-child {
border-top-left-radius: 10px; tbody tr:nth-child(even) td:first-child {
border-bottom-left-radius: 10px; border-top-left-radius: 10px;
} border-bottom-left-radius: 10px;
}
tbody tr:nth-child(even) td:last-child {
border-top-right-radius: 10px; tbody tr:nth-child(even) td:last-child {
border-bottom-right-radius: 10px; border-top-right-radius: 10px;
} border-bottom-right-radius: 10px;
}
.filter-input {
width: 100%; .filter-input {
padding: 5px; width: 100%;
/* margin-bottom: 20px; */ padding: 5px;
font-size: 16px; /* margin-bottom: 20px; */
background-color: rgb(255, 255, 255); font-size: 16px;
border-radius: 25px; background-color: rgb(255, 255, 255);
} border-radius: 25px;
}
.trip-booking {
color: #484848; .trip-booking {
background: #f9f9f7; color: #484848;
border: 1px solid #d8d8d8; background: #f9f9f7;
border-radius: 10px; border: 1px solid #d8d8d8;
margin-top: 15px; border-radius: 10px;
margin-bottom: 15px; margin-top: 15px;
} margin-bottom: 15px;
</style> }
<script> </style>
document.addEventListener("DOMContentLoaded", function() { <script>
const tables = document.querySelectorAll("table"); document.addEventListener("DOMContentLoaded", function() {
tables.forEach((table) => { const tables = document.querySelectorAll("table");
const headers = table.querySelectorAll("thead th"); tables.forEach((table) => {
const rows = Array.from(table.querySelectorAll("tbody tr")); const headers = table.querySelectorAll("thead th");
const filterInput = table.previousElementSibling; const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = table.previousElementSibling;
headers.forEach((header, index) => {
header.addEventListener("click", () => { headers.forEach((header, index) => {
const sortedRows = rows.sort((a, b) => { header.addEventListener("click", () => {
const aText = a.cells[index].textContent.trim().toLowerCase(); const sortedRows = rows.sort((a, b) => {
const bText = b.cells[index].textContent.trim().toLowerCase(); 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; if (aText < bText) return -1;
return 0; if (aText > bText) return 1;
}); return 0;
});
if (header.classList.contains("asc")) {
header.classList.remove("asc"); if (header.classList.contains("asc")) {
header.classList.add("desc"); header.classList.remove("asc");
sortedRows.reverse(); header.classList.add("desc");
} else { sortedRows.reverse();
headers.forEach(h => h.classList.remove("asc", "desc")); } else {
header.classList.add("asc"); headers.forEach(h => h.classList.remove("asc", "desc"));
} header.classList.add("asc");
}
const tbody = table.querySelector("tbody");
tbody.innerHTML = ""; const tbody = table.querySelector("tbody");
sortedRows.forEach(row => tbody.appendChild(row)); tbody.innerHTML = "";
}); sortedRows.forEach(row => tbody.appendChild(row));
}); });
});
if (rows.length === 0) {
filterInput.style.display = "none"; if (rows.length === 0) {
} else { filterInput.style.display = "none";
filterInput.addEventListener("input", function() { } else {
const filterValue = filterInput.value.trim().toLowerCase(); filterInput.addEventListener("input", function() {
rows.forEach(row => { const filterValue = filterInput.value.trim().toLowerCase();
const rowText = row.textContent.trim().toLowerCase(); rows.forEach(row => {
row.style.display = rowText.includes(filterValue) ? "" : "none"; const rowText = row.textContent.trim().toLowerCase();
}); row.style.display = rowText.includes(filterValue) ? "" : "none";
}); });
} });
}); }
}); });
</script> });
<?php </script>
$bannerFolder = 'assets/images/banners/'; <?php
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $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 = 'assets/images/base4/camping.jpg'; // default fallback
$randomBanner = $bannerImages[array_rand($bannerImages)]; 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> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="banner-overlay"></div>
<div class="banner-inner text-white mb-50"> <div class="container">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Camping Bookings</h2> <div class="banner-inner text-white mb-50">
<nav aria-label="breadcrumb"> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Camping Bookings</h2>
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50"> <nav aria-label="breadcrumb">
<li class="breadcrumb-item"><a href="index.php">Home</a></li> <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 active">Camping Bookings</li> <li class="breadcrumb-item"><a href="index.php">Home</a></li>
</ol> <li class="breadcrumb-item active">Camping Bookings</li>
</nav> </ol>
</div> </nav>
</div> </div>
</section> </div>
<section class="tour-list-page py-10 rel z-1"> </section>
<div class="container"> <section class="tour-list-page py-10 rel z-1">
<?php <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 "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
echo "<h4>BASE4 Camping</h4>"; 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, // Fetch bookings for the current trip
u.first_name, u.last_name, $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,
(b.total_amount - b.discount_amount) AS paid u.first_name, u.last_name,
FROM bookings b (b.total_amount - b.discount_amount) AS paid
INNER JOIN users u ON b.user_id = u.user_id FROM bookings b
WHERE b.booking_type = 'camping'"; INNER JOIN users u ON b.user_id = u.user_id
$stmt = $conn->prepare($bookingsSql); WHERE b.booking_type = 'camping'";
$stmt->execute(); $stmt = $conn->prepare($bookingsSql);
$bookingsResult = $stmt->get_result(); $stmt->execute();
$bookingsResult = $stmt->get_result();
if ($bookingsResult->num_rows > 0) {
echo '<input type="text" class="filter-input" placeholder="Filter results...">'; if ($bookingsResult->num_rows > 0) {
echo '<table> echo '<input type="text" class="filter-input" placeholder="Filter results...">';
<thead> echo '<table>
<tr> <thead>
<th>Name</th> <tr>
<th>From</th> <th>Name</th>
<th>To</th> <th>From</th>
<th>Vehicles</th> <th>To</th>
<th>Adults</th> <th>Vehicles</th>
<th>Children</th> <th>Adults</th>
<th>Add Firewood</th> <th>Children</th>
<th>Status</th> <th>Add Firewood</th>
<th>Amount</th> <th>Status</th>
</tr> <th>Amount</th>
</thead> </tr>
<tbody>'; </thead>
while ($booking = $bookingsResult->fetch_assoc()) { <tbody>';
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']); while ($booking = $bookingsResult->fetch_assoc()) {
$numVehicles = htmlspecialchars($booking['num_vehicles']); $userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
$from = htmlspecialchars($booking['from_date']); $numVehicles = htmlspecialchars($booking['num_vehicles']);
$to = htmlspecialchars($booking['to_date']); $from = htmlspecialchars($booking['from_date']);
$numAdults = htmlspecialchars($booking['num_adults']); $to = htmlspecialchars($booking['to_date']);
$numChildren = htmlspecialchars($booking['num_children']); $numAdults = htmlspecialchars($booking['num_adults']);
$radio = $booking['add_firewood'] == 1 ? "YES" : "NO"; $numChildren = htmlspecialchars($booking['num_children']);
$status = htmlspecialchars($booking['status']); $radio = $booking['add_firewood'] == 1 ? "YES" : "NO";
$paid = "R " . number_format($booking['paid'], 2); $status = htmlspecialchars($booking['status']);
$paid = "R " . number_format($booking['paid'], 2);
echo "<tr>
<td>{$userName}</td> echo "<tr>
<td>{$from}</td> <td>{$userName}</td>
<td>{$to}</td> <td>{$from}</td>
<td>{$numVehicles}</td> <td>{$to}</td>
<td>{$numAdults}</td> <td>{$numVehicles}</td>
<td>{$numChildren}</td> <td>{$numAdults}</td>
<td>{$radio}</td> <td>{$numChildren}</td>
<td>{$status}</td> <td>{$radio}</td>
<td>{$paid}</td> <td>{$status}</td>
</tr>"; <td>{$paid}</td>
} </tr>";
echo '</tbody></table>'; }
} else { echo '</tbody></table>';
echo '<p>No bookings found for this trip.</p>'; } else {
} echo '<p>No bookings found for this trip.</p>';
echo "</div>"; }
echo "</div>"; echo "</div>";
echo "</div>";
?>
</div> ?>
</section> </div>
<?php include_once("insta_footer.php"); ?> </section>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,246 +1,247 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(__DIR__));
checkAdmin(); include_once($rootPath . '/header.php');
checkAdmin();
// Fetch all trips
$courseSql = "SELECT date, course_id, course_type FROM courses"; // Fetch all trips
$courseSql = "SELECT date, course_id, course_type FROM courses";
$courseResult = $conn->query($courseSql);
if (!$courseResult) { $courseResult = $conn->query($courseSql);
echo "Error in SQL query: " . $conn->error; if (!$courseResult) {
} echo "Error in SQL query: " . $conn->error;
?> }
<style> ?>
table { <style>
width: 100%; table {
border-collapse: separate; width: 100%;
border-spacing: 0; border-collapse: separate;
margin: 10px 0; border-spacing: 0;
} margin: 10px 0;
}
thead th {
cursor: pointer; thead th {
text-align: left; cursor: pointer;
padding: 10px; text-align: left;
font-weight: bold; padding: 10px;
position: relative; font-weight: bold;
} position: relative;
}
thead th::after {
content: '\25B2'; thead th::after {
/* Up arrow */ content: '\25B2';
font-size: 0.8em; /* Up arrow */
position: absolute; font-size: 0.8em;
right: 10px; position: absolute;
opacity: 0; right: 10px;
transition: opacity 0.2s; opacity: 0;
} transition: opacity 0.2s;
}
thead th.asc::after {
content: '\25B2'; thead th.asc::after {
/* Up arrow */ content: '\25B2';
opacity: 1; /* Up arrow */
} opacity: 1;
}
thead th.desc::after {
content: '\25BC'; thead th.desc::after {
/* Down arrow */ content: '\25BC';
opacity: 1; /* Down arrow */
} opacity: 1;
}
tbody tr:nth-child(odd) {
background-color: transparent; tbody tr:nth-child(odd) {
} background-color: transparent;
}
tbody tr:nth-child(even) {
background-color: rgb(255, 255, 255); tbody tr:nth-child(even) {
border-radius: 10px; background-color: rgb(255, 255, 255);
} border-radius: 10px;
}
tbody td {
padding: 5px; tbody td {
} padding: 5px;
}
tbody tr:nth-child(even) td:first-child {
border-top-left-radius: 10px; tbody tr:nth-child(even) td:first-child {
border-bottom-left-radius: 10px; border-top-left-radius: 10px;
} border-bottom-left-radius: 10px;
}
tbody tr:nth-child(even) td:last-child {
border-top-right-radius: 10px; tbody tr:nth-child(even) td:last-child {
border-bottom-right-radius: 10px; border-top-right-radius: 10px;
} border-bottom-right-radius: 10px;
}
.filter-input {
width: 100%; .filter-input {
padding: 5px; width: 100%;
/* margin-bottom: 20px; */ padding: 5px;
font-size: 16px; /* margin-bottom: 20px; */
background-color: rgb(255, 255, 255); font-size: 16px;
border-radius: 25px; background-color: rgb(255, 255, 255);
} border-radius: 25px;
}
.trip-booking {
color: #484848; .trip-booking {
background: #f9f9f7; color: #484848;
border: 1px solid #d8d8d8; background: #f9f9f7;
border-radius: 10px; border: 1px solid #d8d8d8;
margin-top: 15px; border-radius: 10px;
margin-bottom: 15px; margin-top: 15px;
} margin-bottom: 15px;
}
</style>
<script> </style>
document.addEventListener("DOMContentLoaded", function() { <script>
const tables = document.querySelectorAll("table"); document.addEventListener("DOMContentLoaded", function() {
tables.forEach((table) => { const tables = document.querySelectorAll("table");
const headers = table.querySelectorAll("thead th"); tables.forEach((table) => {
const rows = Array.from(table.querySelectorAll("tbody tr")); const headers = table.querySelectorAll("thead th");
const filterInput = table.previousElementSibling; const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = table.previousElementSibling;
headers.forEach((header, index) => {
header.addEventListener("click", () => { headers.forEach((header, index) => {
const sortedRows = rows.sort((a, b) => { header.addEventListener("click", () => {
const aText = a.cells[index].textContent.trim().toLowerCase(); const sortedRows = rows.sort((a, b) => {
const bText = b.cells[index].textContent.trim().toLowerCase(); 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; if (aText < bText) return -1;
return 0; if (aText > bText) return 1;
}); return 0;
});
if (header.classList.contains("asc")) {
header.classList.remove("asc"); if (header.classList.contains("asc")) {
header.classList.add("desc"); header.classList.remove("asc");
sortedRows.reverse(); header.classList.add("desc");
} else { sortedRows.reverse();
headers.forEach(h => h.classList.remove("asc", "desc")); } else {
header.classList.add("asc"); headers.forEach(h => h.classList.remove("asc", "desc"));
} header.classList.add("asc");
}
const tbody = table.querySelector("tbody");
tbody.innerHTML = ""; const tbody = table.querySelector("tbody");
sortedRows.forEach(row => tbody.appendChild(row)); tbody.innerHTML = "";
}); sortedRows.forEach(row => tbody.appendChild(row));
}); });
});
if (rows.length === 0) {
filterInput.style.display = "none"; if (rows.length === 0) {
} else { filterInput.style.display = "none";
filterInput.addEventListener("input", function() { } else {
const filterValue = filterInput.value.trim().toLowerCase(); filterInput.addEventListener("input", function() {
rows.forEach(row => { const filterValue = filterInput.value.trim().toLowerCase();
const rowText = row.textContent.trim().toLowerCase(); rows.forEach(row => {
row.style.display = rowText.includes(filterValue) ? "" : "none"; const rowText = row.textContent.trim().toLowerCase();
}); row.style.display = rowText.includes(filterValue) ? "" : "none";
}); });
} });
}); }
}); });
</script> });
<?php </script>
$bannerFolder = 'assets/images/banners/'; <?php
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $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 = 'assets/images/base4/camping.jpg'; // default fallback
$randomBanner = $bannerImages[array_rand($bannerImages)]; 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> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="banner-overlay"></div>
<div class="banner-inner text-white mb-50"> <div class="container">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Course Bookings</h2> <div class="banner-inner text-white mb-50">
<nav aria-label="breadcrumb"> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Course Bookings</h2>
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50"> <nav aria-label="breadcrumb">
<li class="breadcrumb-item"><a href="index.php">Home</a></li> <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 active">Course Bookings</li> <li class="breadcrumb-item"><a href="index.php">Home</a></li>
</ol> <li class="breadcrumb-item active">Course Bookings</li>
</nav> </ol>
</div> </nav>
</div> </div>
</section> </div>
<section class="tour-list-page py-10 rel z-1"> </section>
<div class="container"> <section class="tour-list-page py-10 rel z-1">
<?php <div class="container">
if ($courseResult->num_rows > 0) { <?php
while ($course = $courseResult->fetch_assoc()) { if ($courseResult->num_rows > 0) {
$course_id = $course['course_id']; while ($course = $courseResult->fetch_assoc()) {
$date = $course['date']; $course_id = $course['course_id'];
$type = htmlspecialchars($course['course_type']); $date = $course['date'];
if ($type === "driver_training") { $type = htmlspecialchars($course['course_type']);
$course_name = "Basic 4X4 Driver Training Course ".$date; if ($type === "driver_training") {
} elseif ($type === "bush_mechanics") { $course_name = "Basic 4X4 Driver Training Course ".$date;
$course_name = "Bush Mechanics Course ".$date; } elseif ($type === "bush_mechanics") {
} elseif ($type === "rescue_recovery") { $course_name = "Bush Mechanics Course ".$date;
$course_name = "Rescue & Recovery Training Course ".$date; } elseif ($type === "rescue_recovery") {
} else { $course_name = "Rescue & Recovery Training Course ".$date;
$course_name = "General Course ".$date; // Default fallback description } 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 "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
echo "<h4>{$course_name}</h4>"; 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, // Fetch bookings for the current trip
u.first_name, u.last_name, u.profile_pic $bookingsSql = "SELECT b.user_id, b.num_adults, b.total_amount, b.status, b.course_non_members,
FROM bookings b u.first_name, u.last_name, u.profile_pic
INNER JOIN users u ON b.user_id = u.user_id FROM bookings b
WHERE b.course_id = ?"; INNER JOIN users u ON b.user_id = u.user_id
if ($stmt = $conn->prepare($bookingsSql)) { WHERE b.course_id = ?";
$stmt->bind_param('i', $course_id); if ($stmt = $conn->prepare($bookingsSql)) {
$stmt->execute(); $stmt->bind_param('i', $course_id);
$bookingsResult = $stmt->get_result(); $stmt->execute();
} else { $bookingsResult = $stmt->get_result();
echo "Error in prepared statement: " . $conn->error; } else {
} echo "Error in prepared statement: " . $conn->error;
}
if ($bookingsResult->num_rows > 0) {
echo '<input type="text" class="filter-input" placeholder="Filter results...">'; if ($bookingsResult->num_rows > 0) {
echo '<table> echo '<input type="text" class="filter-input" placeholder="Filter results...">';
<thead> echo '<table>
<tr> <thead>
<th></th> <tr>
<th>Name</th> <th></th>
<th>Members</th> <th>Name</th>
<th>Non-Members</th> <th>Members</th>
<th>Status</th> <th>Non-Members</th>
<th>Amount</th> <th>Status</th>
</tr> <th>Amount</th>
</thead> </tr>
<tbody>'; </thead>
while ($booking = $bookingsResult->fetch_assoc()) { <tbody>';
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']); while ($booking = $bookingsResult->fetch_assoc()) {
$members = htmlspecialchars($booking['num_adults']); $userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
$non_members = htmlspecialchars($booking['course_non_members']); $members = htmlspecialchars($booking['num_adults']);
$status = htmlspecialchars($booking['status']); $non_members = htmlspecialchars($booking['course_non_members']);
$paid = "R " . number_format($booking['total_amount'], 2); $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> echo "<tr>
<td>{$userName}</td> <td><img src=".$booking['profile_pic']." alt='Profile Picture' class='profile-pic'></td>
<td>{$members}</td> <td>{$userName}</td>
<td>{$non_members}</td> <td>{$members}</td>
<td>{$status}</td> <td>{$non_members}</td>
<td>{$paid}</td> <td>{$status}</td>
</tr>"; <td>{$paid}</td>
} </tr>";
echo '</tbody></table>'; }
} else { echo '</tbody></table>';
echo '<p>No bookings found for this trip.</p>'; } else {
} echo '<p>No bookings found for this trip.</p>';
echo "</div>"; }
echo "</div>"; echo "</div>";
} echo "</div>";
} else { }
echo '<p>No courses found.</p>'; } else {
} echo '<p>No courses found.</p>';
?> }
</div> ?>
</section> </div>
<?php include_once("insta_footer.php"); ?> </section>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,226 +1,227 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(__DIR__));
checkAdmin(); include_once($rootPath . '/header.php');
checkAdmin();
?>
<style> ?>
table { <style>
width: 100%; table {
border-collapse: separate; width: 100%;
border-spacing: 0; border-collapse: separate;
margin: 10px 0; border-spacing: 0;
} margin: 10px 0;
}
thead th {
cursor: pointer; thead th {
text-align: left; cursor: pointer;
padding: 10px; text-align: left;
font-weight: bold; padding: 10px;
position: relative; font-weight: bold;
} position: relative;
}
thead th::after {
content: '\25B2'; thead th::after {
/* Up arrow */ content: '\25B2';
font-size: 0.8em; /* Up arrow */
position: absolute; font-size: 0.8em;
right: 10px; position: absolute;
opacity: 0; right: 10px;
transition: opacity 0.2s; opacity: 0;
} transition: opacity 0.2s;
}
thead th.asc::after {
content: '\25B2'; thead th.asc::after {
/* Up arrow */ content: '\25B2';
opacity: 1; /* Up arrow */
} opacity: 1;
}
thead th.desc::after {
content: '\25BC'; thead th.desc::after {
/* Down arrow */ content: '\25BC';
opacity: 1; /* Down arrow */
} opacity: 1;
}
tbody tr:nth-child(odd) {
background-color: transparent; tbody tr:nth-child(odd) {
} background-color: transparent;
}
tbody tr:nth-child(even) {
background-color: rgb(255, 255, 255); tbody tr:nth-child(even) {
border-radius: 10px; background-color: rgb(255, 255, 255);
} border-radius: 10px;
}
tbody td {
padding: 5px; tbody td {
} padding: 5px;
}
tbody tr:nth-child(even) td:first-child {
border-top-left-radius: 10px; tbody tr:nth-child(even) td:first-child {
border-bottom-left-radius: 10px; border-top-left-radius: 10px;
} border-bottom-left-radius: 10px;
}
tbody tr:nth-child(even) td:last-child {
border-top-right-radius: 10px; tbody tr:nth-child(even) td:last-child {
border-bottom-right-radius: 10px; border-top-right-radius: 10px;
} border-bottom-right-radius: 10px;
}
.filter-input {
width: 100%; .filter-input {
padding: 5px; width: 100%;
/* margin-bottom: 20px; */ padding: 5px;
font-size: 16px; /* margin-bottom: 20px; */
background-color: rgb(255, 255, 255); font-size: 16px;
border-radius: 25px; background-color: rgb(255, 255, 255);
} border-radius: 25px;
}
.infobox {
color: #484848; .infobox {
background: #f9f9f7; color: #484848;
border: 1px solid #d8d8d8; background: #f9f9f7;
border-radius: 10px; border: 1px solid #d8d8d8;
margin-top: 15px; border-radius: 10px;
margin-bottom: 15px; margin-top: 15px;
} margin-bottom: 15px;
}
.theme-btn,
a.theme-btn { .theme-btn,
padding: 0px 14px; a.theme-btn {
} padding: 0px 14px;
}
</style>
<script> </style>
document.addEventListener("DOMContentLoaded", function() { <script>
const table = document.querySelector("table"); document.addEventListener("DOMContentLoaded", function() {
const headers = table.querySelectorAll("thead th"); const table = document.querySelector("table");
const rows = Array.from(table.querySelectorAll("tbody tr")); const headers = table.querySelectorAll("thead th");
const filterInput = document.getElementById("filterInput"); const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = document.getElementById("filterInput");
headers.forEach((header, index) => {
header.addEventListener("click", () => { headers.forEach((header, index) => {
const sortedRows = rows.sort((a, b) => { header.addEventListener("click", () => {
const aText = a.cells[index].textContent.trim().toLowerCase(); const sortedRows = rows.sort((a, b) => {
const bText = b.cells[index].textContent.trim().toLowerCase(); 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; if (aText < bText) return -1;
return 0; if (aText > bText) return 1;
}); return 0;
});
if (header.classList.contains("asc")) {
header.classList.remove("asc"); if (header.classList.contains("asc")) {
header.classList.add("desc"); header.classList.remove("asc");
sortedRows.reverse(); header.classList.add("desc");
} else { sortedRows.reverse();
headers.forEach(h => h.classList.remove("asc", "desc")); } else {
header.classList.add("asc"); headers.forEach(h => h.classList.remove("asc", "desc"));
} header.classList.add("asc");
}
const tbody = table.querySelector("tbody");
tbody.innerHTML = ""; const tbody = table.querySelector("tbody");
sortedRows.forEach(row => tbody.appendChild(row)); tbody.innerHTML = "";
}); sortedRows.forEach(row => tbody.appendChild(row));
}); });
});
filterInput.addEventListener("input", function() {
const filterValue = filterInput.value.trim().toLowerCase(); filterInput.addEventListener("input", function() {
rows.forEach(row => { const filterValue = filterInput.value.trim().toLowerCase();
const rowText = row.textContent.trim().toLowerCase(); rows.forEach(row => {
row.style.display = rowText.includes(filterValue) ? "" : "none"; const rowText = row.textContent.trim().toLowerCase();
}); row.style.display = rowText.includes(filterValue) ? "" : "none";
}); });
}); });
</script> });
<!-- Page Banner Start --> </script>
<?php <!-- Page Banner Start -->
$bannerFolder = 'assets/images/banners/'; <?php
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $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 = 'assets/images/base4/camping.jpg'; // default fallback
$randomBanner = $bannerImages[array_rand($bannerImages)]; 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> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="banner-overlay"></div>
<div class="banner-inner text-white mb-50"> <div class="container">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA EFT Payments</h2> <div class="banner-inner text-white mb-50">
<nav aria-label="breadcrumb"> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA EFT Payments</h2>
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50"> <nav aria-label="breadcrumb">
<li class="breadcrumb-item"><a href="index.php">Home</a></li> <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 active">4WDCSA EFT Payments</li> <li class="breadcrumb-item"><a href="index.php">Home</a></li>
</ol> <li class="breadcrumb-item active">4WDCSA EFT Payments</li>
</nav> </ol>
</div> </nav>
</div> </div>
</section> </div>
</section>
<!-- Tour List Area start -->
<section class="tour-list-page py-10 rel z-1"> <!-- Tour List Area start -->
<div class="container"> <section class="tour-list-page py-10 rel z-1">
<div class="row"> <div class="container">
<div class="col-lg-12"> <div class="row">
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'> <div class="col-lg-12">
<div style='padding:10px;'> <div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
<?php <div style='padding:10px;'>
// Fetch payments <?php
$paymentSql = "SELECT b.user_id, b.eft_id, b.amount, b.status, b.timestamp, b.description, // Fetch payments
u.first_name, u.last_name $paymentSql = "SELECT b.user_id, b.eft_id, b.amount, b.status, b.timestamp, b.description,
FROM efts b u.first_name, u.last_name
INNER JOIN users u ON b.user_id = u.user_id"; FROM efts b
$stmt = $conn->prepare($paymentSql); INNER JOIN users u ON b.user_id = u.user_id";
$stmt->execute(); $stmt = $conn->prepare($paymentSql);
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo '<input type="text" class="filter-input" placeholder="Filter results...">'; if ($result->num_rows > 0) {
echo '<table> echo '<input type="text" class="filter-input" placeholder="Filter results...">';
<thead> echo '<table>
<tr> <thead>
<th>Date</th> <tr>
<th>Name</th> <th>Date</th>
<th>Description</th> <th>Name</th>
<th>Amount</th> <th>Description</th>
<th>Reference</th> <th>Amount</th>
<th>Status</th> <th>Reference</th>
</tr> <th>Status</th>
</thead> </tr>
<tbody>'; </thead>
while ($row = $result->fetch_assoc()) { <tbody>';
// Generate a unique token for this EFT while ($row = $result->fetch_assoc()) {
// Generate a unique token for this EFT
echo "<tr>
<td>" . htmlspecialchars($row['timestamp']) . "</td> echo "<tr>
<td>" . htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) . "</td> <td>" . htmlspecialchars($row['timestamp']) . "</td>
<td>" . htmlspecialchars($row['description']) . "</td> <td>" . htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) . "</td>
<td>" . htmlspecialchars($row['amount']) . "</td> <td>" . htmlspecialchars($row['description']) . "</td>
<td>" . htmlspecialchars($row['eft_id']) . "</td>"; <td>" . htmlspecialchars($row['amount']) . "</td>
if (($row['status']) == 'AWAITING PAYMENT') { <td>" . htmlspecialchars($row['eft_id']) . "</td>";
echo "<td><a href='process_eft.php?token=" . encryptData($row['eft_id'], $salt) . "' class='theme-btn style-two style-three'> if (($row['status']) == 'AWAITING PAYMENT') {
<span data-hover='PAYMENT RECEIVED'>" . htmlspecialchars($row['status']) . "</span> echo "<td><a href='process_eft.php?token=" . encryptData($row['eft_id'], $salt) . "' class='theme-btn style-two style-three'>
</a></td></tr>"; <span data-hover='PAYMENT RECEIVED'>" . htmlspecialchars($row['status']) . "</span>
} elseif (($row['status']) == 'PROCESSING') { </a></td></tr>";
echo "<td><a href='process_payments.php' class='theme-btn style-two style-three'> } elseif (($row['status']) == 'PROCESSING') {
<span data-hover='PROCESS'>PROCESS</span> echo "<td><a href='process_payments.php' class='theme-btn style-two style-three'>
</a></td></tr>"; <span data-hover='PROCESS'>PROCESS</span>
} else { </a></td></tr>";
echo "<td>" . htmlspecialchars($row['status']) . "</td>"; } else {
} echo "<td>" . htmlspecialchars($row['status']) . "</td>";
} }
} else { }
echo '<tr><td colspan="5">No records found</td></tr>'; } else {
} ?> echo '<tr><td colspan="5">No records found</td></tr>';
} ?>
</tbody>
</table> </tbody>
</div> </table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<!-- Tour List Area end --> </section>
<!-- Tour List Area end -->
<?php include_once("insta_footer.php"); ?>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,237 +1,238 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(__DIR__));
checkAdmin(); include_once($rootPath . '/header.php');
checkAdmin();
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['accept_indemnity'])) {
$user_id = intval($_POST['user_id']); if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['accept_indemnity'])) {
$stmt = $conn->prepare("UPDATE membership_application SET accept_indemnity = 1 WHERE user_id = ?"); $user_id = intval($_POST['user_id']);
if ($stmt) { $stmt = $conn->prepare("UPDATE membership_application SET accept_indemnity = 1 WHERE user_id = ?");
$stmt->bind_param("i", $user_id); if ($stmt) {
$stmt->execute(); $stmt->bind_param("i", $user_id);
$stmt->close(); $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"); // SQL query to fetch membership applications
$stmt->execute(); $stmt = $conn->prepare("SELECT user_id, first_name, last_name, tel_cell, email, dob, accept_indemnity FROM membership_application");
$result = $stmt->get_result(); $stmt->execute();
?> $result = $stmt->get_result();
<style> ?>
table { <style>
width: 100%; table {
border-collapse: separate; width: 100%;
border-spacing: 0; border-collapse: separate;
margin: 10px 0; border-spacing: 0;
} margin: 10px 0;
}
thead th {
cursor: pointer; thead th {
text-align: left; cursor: pointer;
padding: 10px; text-align: left;
font-weight: bold; padding: 10px;
position: relative; font-weight: bold;
} position: relative;
}
thead th::after {
content: '\25B2'; thead th::after {
/* Up arrow */ content: '\25B2';
font-size: 0.8em; /* Up arrow */
position: absolute; font-size: 0.8em;
right: 10px; position: absolute;
opacity: 0; right: 10px;
transition: opacity 0.2s; opacity: 0;
} transition: opacity 0.2s;
}
thead th.asc::after {
content: '\25B2'; thead th.asc::after {
/* Up arrow */ content: '\25B2';
opacity: 1; /* Up arrow */
} opacity: 1;
}
thead th.desc::after {
content: '\25BC'; thead th.desc::after {
/* Down arrow */ content: '\25BC';
opacity: 1; /* Down arrow */
} opacity: 1;
}
tbody tr:nth-child(odd) {
background-color: transparent; tbody tr:nth-child(odd) {
} background-color: transparent;
}
tbody tr:nth-child(even) {
background-color: rgb(255, 255, 255); tbody tr:nth-child(even) {
border-radius: 10px; background-color: rgb(255, 255, 255);
} border-radius: 10px;
}
tbody td {
padding: 5px; tbody td {
} padding: 5px;
}
tbody tr:nth-child(even) td:first-child {
border-top-left-radius: 10px; tbody tr:nth-child(even) td:first-child {
border-bottom-left-radius: 10px; border-top-left-radius: 10px;
} border-bottom-left-radius: 10px;
}
tbody tr:nth-child(even) td:last-child {
border-top-right-radius: 10px; tbody tr:nth-child(even) td:last-child {
border-bottom-right-radius: 10px; border-top-right-radius: 10px;
} border-bottom-right-radius: 10px;
}
.filter-input {
width: 100%; .filter-input {
padding: 5px; width: 100%;
/* margin-bottom: 20px; */ padding: 5px;
font-size: 16px; /* margin-bottom: 20px; */
background-color: rgb(255, 255, 255); font-size: 16px;
border-radius: 25px; background-color: rgb(255, 255, 255);
} border-radius: 25px;
}
.infobox {
color: #484848; .infobox {
background: #f9f9f7; color: #484848;
border: 1px solid #d8d8d8; background: #f9f9f7;
border-radius: 10px; border: 1px solid #d8d8d8;
margin-top: 15px; border-radius: 10px;
margin-bottom: 15px; margin-top: 15px;
} margin-bottom: 15px;
.theme-btn, }
a.theme-btn { .theme-btn,
padding: 0px 14px; a.theme-btn {
} padding: 0px 14px;
}
</style>
<script> </style>
document.addEventListener("DOMContentLoaded", function() { <script>
const table = document.querySelector("table"); document.addEventListener("DOMContentLoaded", function() {
const headers = table.querySelectorAll("thead th"); const table = document.querySelector("table");
const rows = Array.from(table.querySelectorAll("tbody tr")); const headers = table.querySelectorAll("thead th");
const filterInput = document.getElementById("filterInput"); const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = document.getElementById("filterInput");
headers.forEach((header, index) => {
header.addEventListener("click", () => { headers.forEach((header, index) => {
const sortedRows = rows.sort((a, b) => { header.addEventListener("click", () => {
const aText = a.cells[index].textContent.trim().toLowerCase(); const sortedRows = rows.sort((a, b) => {
const bText = b.cells[index].textContent.trim().toLowerCase(); 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; if (aText < bText) return -1;
return 0; if (aText > bText) return 1;
}); return 0;
});
if (header.classList.contains("asc")) {
header.classList.remove("asc"); if (header.classList.contains("asc")) {
header.classList.add("desc"); header.classList.remove("asc");
sortedRows.reverse(); header.classList.add("desc");
} else { sortedRows.reverse();
headers.forEach(h => h.classList.remove("asc", "desc")); } else {
header.classList.add("asc"); headers.forEach(h => h.classList.remove("asc", "desc"));
} header.classList.add("asc");
}
const tbody = table.querySelector("tbody");
tbody.innerHTML = ""; const tbody = table.querySelector("tbody");
sortedRows.forEach(row => tbody.appendChild(row)); tbody.innerHTML = "";
}); sortedRows.forEach(row => tbody.appendChild(row));
}); });
});
filterInput.addEventListener("input", function() {
const filterValue = filterInput.value.trim().toLowerCase(); filterInput.addEventListener("input", function() {
rows.forEach(row => { const filterValue = filterInput.value.trim().toLowerCase();
const rowText = row.textContent.trim().toLowerCase(); rows.forEach(row => {
row.style.display = rowText.includes(filterValue) ? "" : "none"; const rowText = row.textContent.trim().toLowerCase();
}); row.style.display = rowText.includes(filterValue) ? "" : "none";
}); });
}); });
</script> });
<!-- Page Banner Start --> </script>
<?php <!-- Page Banner Start -->
$bannerFolder = 'assets/images/banners/'; <?php
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $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 = 'assets/images/base4/camping.jpg'; // default fallback
$randomBanner = $bannerImages[array_rand($bannerImages)]; 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> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="banner-overlay"></div>
<div class="banner-inner text-white mb-50"> <div class="container">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Members</h2> <div class="banner-inner text-white mb-50">
<nav aria-label="breadcrumb"> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Members</h2>
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50"> <nav aria-label="breadcrumb">
<li class="breadcrumb-item"><a href="index.php">Home</a></li> <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 active">4WDCSA Members</li> <li class="breadcrumb-item"><a href="index.php">Home</a></li>
</ol> <li class="breadcrumb-item active">4WDCSA Members</li>
</nav> </ol>
</div> </nav>
</div> </div>
</section> </div>
</section>
<!-- Tour List Area start -->
<section class="tour-list-page py-10 rel z-1"> <!-- Tour List Area start -->
<div class="container"> <section class="tour-list-page py-10 rel z-1">
<div class="row"> <div class="container">
<div class="col-lg-12"> <div class="row">
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'> <div class="col-lg-12">
<div style='padding:10px;'> <div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results..."> <div style='padding:10px;'>
<table> <input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
<thead> <table>
<tr> <thead>
<th>First Name</th> <tr>
<th>Last Name</th> <th>First Name</th>
<th>Cell Number</th> <th>Last Name</th>
<th>Email</th> <th>Cell Number</th>
<th>Date of Birth</th> <th>Email</th>
<th>Membership</th> <th>Date of Birth</th>
<th>View Info</th> <th>Membership</th>
<th>Indemnity</th> <th>View Info</th>
</tr> <th>Indemnity</th>
</thead> </tr>
<tbody> </thead>
<?php <tbody>
if ($result->num_rows > 0) { <?php
// Output data of each row if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { // Output data of each row
echo "<tr> while ($row = $result->fetch_assoc()) {
<td>" . htmlspecialchars($row['first_name']) . "</td> echo "<tr>
<td>" . htmlspecialchars($row['last_name']) . "</td> <td>" . htmlspecialchars($row['first_name']) . "</td>
<td>" . htmlspecialchars($row['tel_cell']) . "</td> <td>" . htmlspecialchars($row['last_name']) . "</td>
<td>" . htmlspecialchars($row['email']) . "</td> <td>" . htmlspecialchars($row['tel_cell']) . "</td>
<td>" . htmlspecialchars($row['dob']) . "</td> <td>" . htmlspecialchars($row['email']) . "</td>
<td>" . (getUserMemberStatus($row['user_id']) ? 'ACTIVE' : 'INACTIVE') . "</td> <td>" . htmlspecialchars($row['dob']) . "</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>" . (getUserMemberStatus($row['user_id']) ? 'ACTIVE' : 'INACTIVE') . "</td>
<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;'> if (!$row['accept_indemnity']) {
<input type='hidden' name='user_id' value='" . $row['user_id'] . "'> echo "<form method='POST' style='display:inline;'>
<button type='submit' name='accept_indemnity' class='theme-btn small'>Accept</button> <input type='hidden' name='user_id' value='" . $row['user_id'] . "'>
</form>"; <button type='submit' name='accept_indemnity' class='theme-btn small'>Accept</button>
} else { </form>";
echo "✅ Accepted"; } else {
} echo "✅ Accepted";
}
echo "</td>
</tr>"; echo "</td>
} </tr>";
} else { }
echo '<tr><td colspan="8">No records found</td></tr>'; } else {
} echo '<tr><td colspan="8">No records found</td></tr>';
?> }
?>
</tbody>
</table> </tbody>
</div> </table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<!-- Tour List Area end --> </section>
<!-- Tour List Area end -->
<?php include_once("insta_footer.php"); ?>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,210 +1,211 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(__DIR__));
checkAdmin(); include_once($rootPath . '/header.php');
checkAdmin();
?>
<style> ?>
table { <style>
width: 100%; table {
border-collapse: separate; width: 100%;
border-spacing: 0; border-collapse: separate;
margin: 10px 0; border-spacing: 0;
} margin: 10px 0;
}
thead th {
cursor: pointer; thead th {
text-align: left; cursor: pointer;
padding: 10px; text-align: left;
font-weight: bold; padding: 10px;
position: relative; font-weight: bold;
} position: relative;
}
thead th::after {
content: '\25B2'; thead th::after {
/* Up arrow */ content: '\25B2';
font-size: 0.8em; /* Up arrow */
position: absolute; font-size: 0.8em;
right: 10px; position: absolute;
opacity: 0; right: 10px;
transition: opacity 0.2s; opacity: 0;
} transition: opacity 0.2s;
}
thead th.asc::after {
content: '\25B2'; thead th.asc::after {
/* Up arrow */ content: '\25B2';
opacity: 1; /* Up arrow */
} opacity: 1;
}
thead th.desc::after {
content: '\25BC'; thead th.desc::after {
/* Down arrow */ content: '\25BC';
opacity: 1; /* Down arrow */
} opacity: 1;
}
tbody tr:nth-child(odd) {
background-color: transparent; tbody tr:nth-child(odd) {
} background-color: transparent;
}
tbody tr:nth-child(even) {
background-color: rgb(255, 255, 255); tbody tr:nth-child(even) {
border-radius: 10px; background-color: rgb(255, 255, 255);
} border-radius: 10px;
}
tbody td {
padding: 5px; tbody td {
} padding: 5px;
}
tbody tr:nth-child(even) td:first-child {
border-top-left-radius: 10px; tbody tr:nth-child(even) td:first-child {
border-bottom-left-radius: 10px; border-top-left-radius: 10px;
} border-bottom-left-radius: 10px;
}
tbody tr:nth-child(even) td:last-child {
border-top-right-radius: 10px; tbody tr:nth-child(even) td:last-child {
border-bottom-right-radius: 10px; border-top-right-radius: 10px;
} border-bottom-right-radius: 10px;
}
.filter-input {
width: 100%; .filter-input {
padding: 5px; width: 100%;
/* margin-bottom: 20px; */ padding: 5px;
font-size: 16px; /* margin-bottom: 20px; */
background-color: rgb(255, 255, 255); font-size: 16px;
border-radius: 25px; background-color: rgb(255, 255, 255);
} border-radius: 25px;
}
.infobox {
color: #484848; .infobox {
background: #f9f9f7; color: #484848;
border: 1px solid #d8d8d8; background: #f9f9f7;
border-radius: 10px; border: 1px solid #d8d8d8;
margin-top: 15px; border-radius: 10px;
margin-bottom: 15px; margin-top: 15px;
} margin-bottom: 15px;
}
</style>
<script> </style>
document.addEventListener("DOMContentLoaded", function() { <script>
const table = document.querySelector("table"); document.addEventListener("DOMContentLoaded", function() {
const headers = table.querySelectorAll("thead th"); const table = document.querySelector("table");
const rows = Array.from(table.querySelectorAll("tbody tr")); const headers = table.querySelectorAll("thead th");
const filterInput = document.getElementById("filterInput"); const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = document.getElementById("filterInput");
headers.forEach((header, index) => {
header.addEventListener("click", () => { headers.forEach((header, index) => {
const sortedRows = rows.sort((a, b) => { header.addEventListener("click", () => {
const aText = a.cells[index].textContent.trim().toLowerCase(); const sortedRows = rows.sort((a, b) => {
const bText = b.cells[index].textContent.trim().toLowerCase(); 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; if (aText < bText) return -1;
return 0; if (aText > bText) return 1;
}); return 0;
});
if (header.classList.contains("asc")) {
header.classList.remove("asc"); if (header.classList.contains("asc")) {
header.classList.add("desc"); header.classList.remove("asc");
sortedRows.reverse(); header.classList.add("desc");
} else { sortedRows.reverse();
headers.forEach(h => h.classList.remove("asc", "desc")); } else {
header.classList.add("asc"); headers.forEach(h => h.classList.remove("asc", "desc"));
} header.classList.add("asc");
}
const tbody = table.querySelector("tbody");
tbody.innerHTML = ""; const tbody = table.querySelector("tbody");
sortedRows.forEach(row => tbody.appendChild(row)); tbody.innerHTML = "";
}); sortedRows.forEach(row => tbody.appendChild(row));
}); });
});
filterInput.addEventListener("input", function() {
const filterValue = filterInput.value.trim().toLowerCase(); filterInput.addEventListener("input", function() {
rows.forEach(row => { const filterValue = filterInput.value.trim().toLowerCase();
const rowText = row.textContent.trim().toLowerCase(); rows.forEach(row => {
row.style.display = rowText.includes(filterValue) ? "" : "none"; const rowText = row.textContent.trim().toLowerCase();
}); row.style.display = rowText.includes(filterValue) ? "" : "none";
}); });
}); });
</script> });
<!-- Page Banner Start --> </script>
<?php <!-- Page Banner Start -->
$bannerFolder = 'assets/images/banners/'; <?php
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $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 = 'assets/images/base4/camping.jpg'; // default fallback
$randomBanner = $bannerImages[array_rand($bannerImages)]; 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> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="banner-overlay"></div>
<div class="banner-inner text-white mb-50"> <div class="container">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Payments</h2> <div class="banner-inner text-white mb-50">
<nav aria-label="breadcrumb"> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Payments</h2>
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50"> <nav aria-label="breadcrumb">
<li class="breadcrumb-item"><a href="index.php">Home</a></li> <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 active">4WDCSA Payments</li> <li class="breadcrumb-item"><a href="index.php">Home</a></li>
</ol> <li class="breadcrumb-item active">4WDCSA Payments</li>
</nav> </ol>
</div> </nav>
</div> </div>
</section> </div>
</section>
<!-- Tour List Area start -->
<section class="tour-list-page py-10 rel z-1"> <!-- Tour List Area start -->
<div class="container"> <section class="tour-list-page py-10 rel z-1">
<div class="row"> <div class="container">
<div class="col-lg-12"> <div class="row">
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'> <div class="col-lg-12">
<div style='padding:10px;'> <div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
<?php <div style='padding:10px;'>
// Fetch payments <?php
$paymentSql = "SELECT b.user_id, b.payment_id, b.amount, b.status, b.date, b.description, // Fetch payments
u.first_name, u.last_name $paymentSql = "SELECT b.user_id, b.payment_id, b.amount, b.status, b.date, b.description,
FROM payments b u.first_name, u.last_name
INNER JOIN users u ON b.user_id = u.user_id"; FROM payments b
$stmt = $conn->prepare($paymentSql); INNER JOIN users u ON b.user_id = u.user_id";
$stmt->execute(); $stmt = $conn->prepare($paymentSql);
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo '<input type="text" class="filter-input" placeholder="Filter results...">'; if ($result->num_rows > 0) {
echo '<table> echo '<input type="text" class="filter-input" placeholder="Filter results...">';
<thead> echo '<table>
<tr> <thead>
<th>Date</th> <tr>
<th>ID</th> <th>Date</th>
<th>Name</th> <th>ID</th>
<th>Description</th> <th>Name</th>
<th>Amount</th> <th>Description</th>
<th>Status</th> <th>Amount</th>
</tr> <th>Status</th>
</thead> </tr>
<tbody>'; </thead>
while ($row = $result->fetch_assoc()) { <tbody>';
echo "<tr> while ($row = $result->fetch_assoc()) {
<td>" . htmlspecialchars($row['date']) . "</td> echo "<tr>
<td>" . htmlspecialchars($row['payment_id']) . "</td> <td>" . htmlspecialchars($row['date']) . "</td>
<td>" . htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) . "</td> <td>" . htmlspecialchars($row['payment_id']) . "</td>
<td>" . htmlspecialchars($row['description']) . "</td> <td>" . htmlspecialchars($row['first_name'] . ' ' . $row['last_name']) . "</td>
<td>" . htmlspecialchars($row['amount']) . "</td> <td>" . htmlspecialchars($row['description']) . "</td>
<td>" . htmlspecialchars($row['status']) . "</td> <td>" . htmlspecialchars($row['amount']) . "</td>
</tr>"; <td>" . htmlspecialchars($row['status']) . "</td>
} </tr>";
} else { }
echo '<tr><td colspan="5">No records found</td></tr>'; } else {
} ?> echo '<tr><td colspan="5">No records found</td></tr>';
} ?>
</tbody>
</table> </tbody>
</div> </table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<!-- Tour List Area end --> </section>
<!-- Tour List Area end -->
<?php include_once("insta_footer.php"); ?>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,239 +1,240 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(__DIR__));
checkAdmin(); include_once($rootPath . '/header.php');
checkAdmin();
// Fetch all trips
$tripsSql = "SELECT trip_id, trip_name FROM trips"; // Fetch all trips
$tripsResult = $conn->query($tripsSql); $tripsSql = "SELECT trip_id, trip_name FROM trips";
$tripsResult = $conn->query($tripsSql);
?>
<style> ?>
table { <style>
width: 100%; table {
border-collapse: separate; width: 100%;
border-spacing: 0; border-collapse: separate;
margin: 10px 0; border-spacing: 0;
} margin: 10px 0;
}
thead th {
cursor: pointer; thead th {
text-align: left; cursor: pointer;
padding: 10px; text-align: left;
font-weight: bold; padding: 10px;
position: relative; font-weight: bold;
} position: relative;
}
thead th::after {
content: '\25B2'; thead th::after {
/* Up arrow */ content: '\25B2';
font-size: 0.8em; /* Up arrow */
position: absolute; font-size: 0.8em;
right: 10px; position: absolute;
opacity: 0; right: 10px;
transition: opacity 0.2s; opacity: 0;
} transition: opacity 0.2s;
}
thead th.asc::after {
content: '\25B2'; thead th.asc::after {
/* Up arrow */ content: '\25B2';
opacity: 1; /* Up arrow */
} opacity: 1;
}
thead th.desc::after {
content: '\25BC'; thead th.desc::after {
/* Down arrow */ content: '\25BC';
opacity: 1; /* Down arrow */
} opacity: 1;
}
tbody tr:nth-child(odd) {
background-color: transparent; tbody tr:nth-child(odd) {
} background-color: transparent;
}
tbody tr:nth-child(even) {
background-color: rgb(255, 255, 255); tbody tr:nth-child(even) {
border-radius: 10px; background-color: rgb(255, 255, 255);
} border-radius: 10px;
}
tbody td {
padding: 5px; tbody td {
} padding: 5px;
}
tbody tr:nth-child(even) td:first-child {
border-top-left-radius: 10px; tbody tr:nth-child(even) td:first-child {
border-bottom-left-radius: 10px; border-top-left-radius: 10px;
} border-bottom-left-radius: 10px;
}
tbody tr:nth-child(even) td:last-child {
border-top-right-radius: 10px; tbody tr:nth-child(even) td:last-child {
border-bottom-right-radius: 10px; border-top-right-radius: 10px;
} border-bottom-right-radius: 10px;
}
.filter-input {
width: 100%; .filter-input {
padding: 5px; width: 100%;
/* margin-bottom: 20px; */ padding: 5px;
font-size: 16px; /* margin-bottom: 20px; */
background-color: rgb(255, 255, 255); font-size: 16px;
border-radius: 25px; background-color: rgb(255, 255, 255);
} border-radius: 25px;
}
.trip-booking {
color: #484848; .trip-booking {
background: #f9f9f7; color: #484848;
border: 1px solid #d8d8d8; background: #f9f9f7;
border-radius: 10px; border: 1px solid #d8d8d8;
margin-top: 15px; border-radius: 10px;
margin-bottom: 15px; margin-top: 15px;
} margin-bottom: 15px;
}
</style>
<script> </style>
document.addEventListener("DOMContentLoaded", function() { <script>
const tables = document.querySelectorAll("table"); document.addEventListener("DOMContentLoaded", function() {
tables.forEach((table) => { const tables = document.querySelectorAll("table");
const headers = table.querySelectorAll("thead th"); tables.forEach((table) => {
const rows = Array.from(table.querySelectorAll("tbody tr")); const headers = table.querySelectorAll("thead th");
const filterInput = table.previousElementSibling; const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = table.previousElementSibling;
headers.forEach((header, index) => {
header.addEventListener("click", () => { headers.forEach((header, index) => {
const sortedRows = rows.sort((a, b) => { header.addEventListener("click", () => {
const aText = a.cells[index].textContent.trim().toLowerCase(); const sortedRows = rows.sort((a, b) => {
const bText = b.cells[index].textContent.trim().toLowerCase(); 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; if (aText < bText) return -1;
return 0; if (aText > bText) return 1;
}); return 0;
});
if (header.classList.contains("asc")) {
header.classList.remove("asc"); if (header.classList.contains("asc")) {
header.classList.add("desc"); header.classList.remove("asc");
sortedRows.reverse(); header.classList.add("desc");
} else { sortedRows.reverse();
headers.forEach(h => h.classList.remove("asc", "desc")); } else {
header.classList.add("asc"); headers.forEach(h => h.classList.remove("asc", "desc"));
} header.classList.add("asc");
}
const tbody = table.querySelector("tbody");
tbody.innerHTML = ""; const tbody = table.querySelector("tbody");
sortedRows.forEach(row => tbody.appendChild(row)); tbody.innerHTML = "";
}); sortedRows.forEach(row => tbody.appendChild(row));
}); });
});
if (rows.length === 0) {
filterInput.style.display = "none"; if (rows.length === 0) {
} else { filterInput.style.display = "none";
filterInput.addEventListener("input", function() { } else {
const filterValue = filterInput.value.trim().toLowerCase(); filterInput.addEventListener("input", function() {
rows.forEach(row => { const filterValue = filterInput.value.trim().toLowerCase();
const rowText = row.textContent.trim().toLowerCase(); rows.forEach(row => {
row.style.display = rowText.includes(filterValue) ? "" : "none"; const rowText = row.textContent.trim().toLowerCase();
}); row.style.display = rowText.includes(filterValue) ? "" : "none";
}); });
} });
}); }
}); });
</script> });
<?php </script>
$bannerFolder = 'assets/images/banners/'; <?php
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $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 = 'assets/images/base4/camping.jpg'; // default fallback
$randomBanner = $bannerImages[array_rand($bannerImages)]; 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> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="banner-overlay"></div>
<div class="banner-inner text-white mb-50"> <div class="container">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Trip Bookings</h2> <div class="banner-inner text-white mb-50">
<nav aria-label="breadcrumb"> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Trip Bookings</h2>
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50"> <nav aria-label="breadcrumb">
<li class="breadcrumb-item"><a href="index.php">Home</a></li> <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 active">Trip Bookings</li> <li class="breadcrumb-item"><a href="index.php">Home</a></li>
</ol> <li class="breadcrumb-item active">Trip Bookings</li>
</nav> </ol>
</div> </nav>
</div> </div>
</section> </div>
<section class="tour-list-page py-10 rel z-1"> </section>
<div class="container"> <section class="tour-list-page py-10 rel z-1">
<?php <div class="container">
if ($tripsResult->num_rows > 0) { <?php
while ($trip = $tripsResult->fetch_assoc()) { if ($tripsResult->num_rows > 0) {
$tripId = $trip['trip_id']; while ($trip = $tripsResult->fetch_assoc()) {
$tripName = htmlspecialchars($trip['trip_name']); $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 "<div class='trip-booking' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>";
echo "<h4>{$tripName}</h4>"; 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, // Fetch bookings for the current trip
u.first_name, u.last_name, $bookingsSql = "SELECT b.user_id, b.num_vehicles, b.num_adults, b.num_children, b.num_pensioners, b.radio, b.status,
(b.total_amount - b.discount_amount) AS paid u.first_name, u.last_name,
FROM bookings b (b.total_amount - b.discount_amount) AS paid
INNER JOIN users u ON b.user_id = u.user_id FROM bookings b
WHERE b.trip_id = ?"; INNER JOIN users u ON b.user_id = u.user_id
$stmt = $conn->prepare($bookingsSql); WHERE b.trip_id = ?";
$stmt->bind_param('i', $tripId); $stmt = $conn->prepare($bookingsSql);
$stmt->execute(); $stmt->bind_param('i', $tripId);
$bookingsResult = $stmt->get_result(); $stmt->execute();
$bookingsResult = $stmt->get_result();
if ($bookingsResult->num_rows > 0) {
echo '<input type="text" class="filter-input" placeholder="Filter results...">'; if ($bookingsResult->num_rows > 0) {
echo '<table> echo '<input type="text" class="filter-input" placeholder="Filter results...">';
<thead> echo '<table>
<tr> <thead>
<th></th> <tr>
<th>Name</th> <th></th>
<th>Vehicles</th> <th>Name</th>
<th>Adults</th> <th>Vehicles</th>
<th>Children</th> <th>Adults</th>
<th>Pensioners</th> <th>Children</th>
<th>Radio</th> <th>Pensioners</th>
<th>Status</th> <th>Radio</th>
<th>Amount</th> <th>Status</th>
</tr> <th>Amount</th>
</thead> </tr>
<tbody>'; </thead>
while ($booking = $bookingsResult->fetch_assoc()) { <tbody>';
$userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']); while ($booking = $bookingsResult->fetch_assoc()) {
$numVehicles = htmlspecialchars($booking['num_vehicles']); $userName = htmlspecialchars($booking['first_name'] . ' ' . $booking['last_name']);
$numAdults = htmlspecialchars($booking['num_adults']); $numVehicles = htmlspecialchars($booking['num_vehicles']);
$numPensioners = htmlspecialchars($booking['num_pensioners']); $numAdults = htmlspecialchars($booking['num_adults']);
$numChildren = htmlspecialchars($booking['num_children']); $numPensioners = htmlspecialchars($booking['num_pensioners']);
$radio = $booking['radio'] == 1 ? "YES" : "NO"; $numChildren = htmlspecialchars($booking['num_children']);
$status = htmlspecialchars($booking['status']); $radio = $booking['radio'] == 1 ? "YES" : "NO";
$paid = "R " . number_format($booking['paid'], 2); $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> echo "<tr>
<td>{$userName}</td> <td><img src=".$booking['profile_pic']." alt='Profile Picture' class='profile-pic'></td>
<td>{$numVehicles}</td> <td>{$userName}</td>
<td>{$numAdults}</td> <td>{$numVehicles}</td>
<td>{$numChildren}</td> <td>{$numAdults}</td>
<td>{$numPensioners}</td> <td>{$numChildren}</td>
<td>{$radio}</td> <td>{$numPensioners}</td>
<td>{$status}</td> <td>{$radio}</td>
<td>{$paid}</td> <td>{$status}</td>
</tr>"; <td>{$paid}</td>
} </tr>";
echo '</tbody></table>'; }
} else { echo '</tbody></table>';
echo '<p>No bookings found for this trip.</p>'; } else {
} echo '<p>No bookings found for this trip.</p>';
echo "</div>"; }
echo "</div>"; echo "</div>";
} echo "</div>";
} else { }
echo '<p>No trips found.</p>'; } else {
} echo '<p>No trips found.</p>';
?> }
</div> ?>
</section> </div>
<?php include_once("insta_footer.php"); ?> </section>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,203 +1,204 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(__DIR__));
checkAdmin(); include_once($rootPath . '/header.php');
// SQL query to fetch data checkAdmin();
$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"; // 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);
?> $result = $conn->query($sql);
<style> ?>
table { <style>
width: 100%; table {
border-collapse: separate; width: 100%;
border-spacing: 0; border-collapse: separate;
margin: 10px 0; border-spacing: 0;
} margin: 10px 0;
}
thead th {
cursor: pointer; thead th {
text-align: left; cursor: pointer;
padding: 10px; text-align: left;
font-weight: bold; padding: 10px;
position: relative; font-weight: bold;
} position: relative;
}
thead th::after {
content: '\25B2'; thead th::after {
/* Up arrow */ content: '\25B2';
font-size: 0.8em; /* Up arrow */
position: absolute; font-size: 0.8em;
right: 10px; position: absolute;
opacity: 0; right: 10px;
transition: opacity 0.2s; opacity: 0;
} transition: opacity 0.2s;
}
thead th.asc::after {
content: '\25B2'; thead th.asc::after {
/* Up arrow */ content: '\25B2';
opacity: 1; /* Up arrow */
} opacity: 1;
}
thead th.desc::after {
content: '\25BC'; thead th.desc::after {
/* Down arrow */ content: '\25BC';
opacity: 1; /* Down arrow */
} opacity: 1;
}
tbody tr:nth-child(odd) {
background-color: transparent; tbody tr:nth-child(odd) {
} background-color: transparent;
}
tbody tr:nth-child(even) {
background-color: rgb(255, 255, 255); tbody tr:nth-child(even) {
border-radius: 10px; background-color: rgb(255, 255, 255);
} border-radius: 10px;
}
tbody td {
padding: 5px; tbody td {
} padding: 5px;
}
tbody tr:nth-child(even) td:first-child {
border-top-left-radius: 10px; tbody tr:nth-child(even) td:first-child {
border-bottom-left-radius: 10px; border-top-left-radius: 10px;
} border-bottom-left-radius: 10px;
}
tbody tr:nth-child(even) td:last-child {
border-top-right-radius: 10px; tbody tr:nth-child(even) td:last-child {
border-bottom-right-radius: 10px; border-top-right-radius: 10px;
} border-bottom-right-radius: 10px;
}
.filter-input {
width: 100%; .filter-input {
padding: 5px; width: 100%;
/* margin-bottom: 20px; */ padding: 5px;
font-size: 16px; /* margin-bottom: 20px; */
background-color: rgb(255, 255, 255); font-size: 16px;
border-radius: 25px; background-color: rgb(255, 255, 255);
} border-radius: 25px;
}
.infobox {
color: #484848; .infobox {
background: #f9f9f7; color: #484848;
border: 1px solid #d8d8d8; background: #f9f9f7;
border-radius: 10px; border: 1px solid #d8d8d8;
margin-top: 15px; border-radius: 10px;
margin-bottom: 15px; margin-top: 15px;
} margin-bottom: 15px;
</style> }
<script> </style>
document.addEventListener("DOMContentLoaded", function() { <script>
const table = document.querySelector("table"); document.addEventListener("DOMContentLoaded", function() {
const headers = table.querySelectorAll("thead th"); const table = document.querySelector("table");
const rows = Array.from(table.querySelectorAll("tbody tr")); const headers = table.querySelectorAll("thead th");
const filterInput = document.getElementById("filterInput"); const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = document.getElementById("filterInput");
headers.forEach((header, index) => {
header.addEventListener("click", () => { headers.forEach((header, index) => {
const sortedRows = rows.sort((a, b) => { header.addEventListener("click", () => {
const aText = a.cells[index].textContent.trim().toLowerCase(); const sortedRows = rows.sort((a, b) => {
const bText = b.cells[index].textContent.trim().toLowerCase(); 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; if (aText < bText) return -1;
return 0; if (aText > bText) return 1;
}); return 0;
});
if (header.classList.contains("asc")) {
header.classList.remove("asc"); if (header.classList.contains("asc")) {
header.classList.add("desc"); header.classList.remove("asc");
sortedRows.reverse(); header.classList.add("desc");
} else { sortedRows.reverse();
headers.forEach(h => h.classList.remove("asc", "desc")); } else {
header.classList.add("asc"); headers.forEach(h => h.classList.remove("asc", "desc"));
} header.classList.add("asc");
}
const tbody = table.querySelector("tbody");
tbody.innerHTML = ""; const tbody = table.querySelector("tbody");
sortedRows.forEach(row => tbody.appendChild(row)); tbody.innerHTML = "";
}); sortedRows.forEach(row => tbody.appendChild(row));
}); });
});
filterInput.addEventListener("input", function() {
const filterValue = filterInput.value.trim().toLowerCase(); filterInput.addEventListener("input", function() {
rows.forEach(row => { const filterValue = filterInput.value.trim().toLowerCase();
const rowText = row.textContent.trim().toLowerCase(); rows.forEach(row => {
row.style.display = rowText.includes(filterValue) ? "" : "none"; const rowText = row.textContent.trim().toLowerCase();
}); row.style.display = rowText.includes(filterValue) ? "" : "none";
}); });
}); });
</script> });
<!-- Page Banner Start --> </script>
<?php <!-- Page Banner Start -->
$bannerFolder = 'assets/images/banners/'; <?php
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $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 = 'assets/images/base4/camping.jpg'; // default fallback
$randomBanner = $bannerImages[array_rand($bannerImages)]; 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> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="banner-overlay"></div>
<div class="banner-inner text-white mb-50"> <div class="container">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Visitor Logs</h2> <div class="banner-inner text-white mb-50">
<nav aria-label="breadcrumb"> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Visitor Logs</h2>
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50"> <nav aria-label="breadcrumb">
<li class="breadcrumb-item"><a href="index.php">Home</a></li> <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 active">4WDCSA Visitor Logs</li> <li class="breadcrumb-item"><a href="index.php">Home</a></li>
</ol> <li class="breadcrumb-item active">4WDCSA Visitor Logs</li>
</nav> </ol>
</div> </nav>
</div> </div>
</section> </div>
</section>
<!-- Tour List Area start -->
<section class="tour-list-page py-10 rel z-1"> <!-- Tour List Area start -->
<div class="container"> <section class="tour-list-page py-10 rel z-1">
<div class="row"> <div class="container">
<div class="col-lg-12"> <div class="row">
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'> <div class="col-lg-12">
<div style='padding:10px;'> <div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results..."> <div style='padding:10px;'>
<table> <input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
<thead> <table>
<tr> <thead>
<th>Country</th> <tr>
<th>IP Address</th> <th>Country</th>
<th>User ID</th> <th>IP Address</th>
<th>Page URL</th> <th>User ID</th>
<th>Referrer</th> <th>Page URL</th>
<th>Timestamp</th> <th>Referrer</th>
</tr> <th>Timestamp</th>
</thead> </tr>
<tbody> </thead>
<?php <tbody>
if ($result->num_rows > 0) { <?php
while ($row = $result->fetch_assoc()) { if ($result->num_rows > 0) {
echo "<tr> while ($row = $result->fetch_assoc()) {
<td>" . ($row['country']) . "</td> echo "<tr>
<td>" . htmlspecialchars($row['ip_address']) . "</td> <td>" . ($row['country']) . "</td>
<td>" . ($row['user_id'] !== null ? htmlspecialchars(getFullName($row['user_id'])) : '-') . "</td> <td>" . htmlspecialchars($row['ip_address']) . "</td>
<td>" . htmlspecialchars($row['page_url']) . "</td> <td>" . ($row['user_id'] !== null ? htmlspecialchars(getFullName($row['user_id'])) : '-') . "</td>
<td>" . ($row['referrer_url'] ? htmlspecialchars($row['referrer_url']) : '-') . "</td> <td>" . htmlspecialchars($row['page_url']) . "</td>
<td>" . htmlspecialchars($row['visit_time']) . "</td> <td>" . ($row['referrer_url'] ? htmlspecialchars($row['referrer_url']) : '-') . "</td>
</tr>"; <td>" . htmlspecialchars($row['visit_time']) . "</td>
} </tr>";
} else { }
echo '<tr><td colspan="5">No logs found</td></tr>'; } else {
} echo '<tr><td colspan="5">No logs found</td></tr>';
?> }
</tbody> ?>
</table> </tbody>
</div> </table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<!-- Tour List Area end --> </section>
<!-- Tour List Area end -->
<?php include_once("insta_footer.php"); ?>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,283 +1,284 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(__DIR__));
checkSuperAdmin(); include_once($rootPath . '/header.php');
// SQL query to fetch data checkAdmin();
$sql = "SELECT user_id, first_name, last_name, email, member, date_joined, token, is_verified, profile_pic FROM users"; // SQL query to fetch data
$result = $conn->query($sql); $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 { <style>
width: 100%; table {
border-collapse: separate; width: 100%;
border-spacing: 0; border-collapse: separate;
margin: 10px 0; border-spacing: 0;
} margin: 10px 0;
}
thead th {
cursor: pointer; thead th {
text-align: left; cursor: pointer;
padding: 10px; text-align: left;
font-weight: bold; padding: 10px;
position: relative; font-weight: bold;
} position: relative;
}
thead th::after {
content: '\25B2'; thead th::after {
/* Up arrow */ content: '\25B2';
font-size: 0.8em; /* Up arrow */
position: absolute; font-size: 0.8em;
right: 10px; position: absolute;
opacity: 0; right: 10px;
transition: opacity 0.2s; opacity: 0;
} transition: opacity 0.2s;
}
thead th.asc::after {
content: '\25B2'; thead th.asc::after {
/* Up arrow */ content: '\25B2';
opacity: 1; /* Up arrow */
} opacity: 1;
}
thead th.desc::after {
content: '\25BC'; thead th.desc::after {
/* Down arrow */ content: '\25BC';
opacity: 1; /* Down arrow */
} opacity: 1;
}
tbody tr:nth-child(odd) {
background-color: transparent; tbody tr:nth-child(odd) {
} background-color: transparent;
}
tbody tr:nth-child(even) {
background-color: rgb(255, 255, 255); tbody tr:nth-child(even) {
border-radius: 10px; background-color: rgb(255, 255, 255);
} border-radius: 10px;
}
tbody td {
padding: 5px; tbody td {
} padding: 5px;
}
tbody tr:nth-child(even) td:first-child {
border-top-left-radius: 10px; tbody tr:nth-child(even) td:first-child {
border-bottom-left-radius: 10px; border-top-left-radius: 10px;
} border-bottom-left-radius: 10px;
}
tbody tr:nth-child(even) td:last-child {
border-top-right-radius: 10px; tbody tr:nth-child(even) td:last-child {
border-bottom-right-radius: 10px; border-top-right-radius: 10px;
} border-bottom-right-radius: 10px;
}
.filter-input {
width: 100%; .filter-input {
padding: 5px; width: 100%;
/* margin-bottom: 20px; */ padding: 5px;
font-size: 16px; /* margin-bottom: 20px; */
background-color: rgb(255, 255, 255); font-size: 16px;
border-radius: 25px; background-color: rgb(255, 255, 255);
} border-radius: 25px;
}
.infobox {
color: #484848; .infobox {
background: #f9f9f7; color: #484848;
border: 1px solid #d8d8d8; background: #f9f9f7;
border-radius: 10px; border: 1px solid #d8d8d8;
margin-top: 15px; border-radius: 10px;
margin-bottom: 15px; margin-top: 15px;
} margin-bottom: 15px;
</style> }
<script> </style>
document.addEventListener("DOMContentLoaded", function() { <script>
const table = document.querySelector("table"); document.addEventListener("DOMContentLoaded", function() {
const headers = table.querySelectorAll("thead th"); const table = document.querySelector("table");
const rows = Array.from(table.querySelectorAll("tbody tr")); const headers = table.querySelectorAll("thead th");
const filterInput = document.getElementById("filterInput"); const rows = Array.from(table.querySelectorAll("tbody tr"));
const filterInput = document.getElementById("filterInput");
headers.forEach((header, index) => {
header.addEventListener("click", () => { headers.forEach((header, index) => {
const sortedRows = rows.sort((a, b) => { header.addEventListener("click", () => {
const aText = a.cells[index].textContent.trim().toLowerCase(); const sortedRows = rows.sort((a, b) => {
const bText = b.cells[index].textContent.trim().toLowerCase(); 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; if (aText < bText) return -1;
return 0; if (aText > bText) return 1;
}); return 0;
});
if (header.classList.contains("asc")) {
header.classList.remove("asc"); if (header.classList.contains("asc")) {
header.classList.add("desc"); header.classList.remove("asc");
sortedRows.reverse(); header.classList.add("desc");
} else { sortedRows.reverse();
headers.forEach(h => h.classList.remove("asc", "desc")); } else {
header.classList.add("asc"); headers.forEach(h => h.classList.remove("asc", "desc"));
} header.classList.add("asc");
}
const tbody = table.querySelector("tbody");
tbody.innerHTML = ""; const tbody = table.querySelector("tbody");
sortedRows.forEach(row => tbody.appendChild(row)); tbody.innerHTML = "";
}); sortedRows.forEach(row => tbody.appendChild(row));
}); });
});
filterInput.addEventListener("input", function() {
const filterValue = filterInput.value.trim().toLowerCase(); filterInput.addEventListener("input", function() {
rows.forEach(row => { const filterValue = filterInput.value.trim().toLowerCase();
const rowText = row.textContent.trim().toLowerCase(); rows.forEach(row => {
row.style.display = rowText.includes(filterValue) ? "" : "none"; const rowText = row.textContent.trim().toLowerCase();
}); row.style.display = rowText.includes(filterValue) ? "" : "none";
}); });
}); });
</script> });
<!-- Page Banner Start --> </script>
<?php <!-- Page Banner Start -->
$bannerFolder = 'assets/images/banners/'; <?php
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $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 = 'assets/images/base4/camping.jpg'; // default fallback
$randomBanner = $bannerImages[array_rand($bannerImages)]; 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> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="banner-overlay"></div>
<div class="banner-inner text-white mb-50"> <div class="container">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Site Users</h2> <div class="banner-inner text-white mb-50">
<nav aria-label="breadcrumb"> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">4WDCSA Site Users</h2>
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50"> <nav aria-label="breadcrumb">
<li class="breadcrumb-item"><a href="index.php">Home</a></li> <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 active">4WDCSA Site Users</li> <li class="breadcrumb-item"><a href="index.php">Home</a></li>
</ol> <li class="breadcrumb-item active">4WDCSA Site Users</li>
</nav> </ol>
</div> </nav>
</div> </div>
</section> </div>
<?php if (isset($_SESSION['message'])): ?> </section>
<div class="alert alert-warning message-box"> <?php if (isset($_SESSION['message'])): ?>
<?php echo $_SESSION['message']; ?> <div class="alert alert-warning message-box">
<span class="close-btn" onclick="this.parentElement.style.display='none'">&times;</span> <?php echo $_SESSION['message']; ?>
</div> <span class="close-btn" onclick="this.parentElement.style.display='none'">&times;</span>
<?php unset($_SESSION['message']); ?> </div>
<?php endif; ?> <?php unset($_SESSION['message']); ?>
<?php endif; ?>
<!-- Tour List Area start -->
<section class="tour-list-page py-10 rel z-1"> <!-- Tour List Area start -->
<div class="container"> <section class="tour-list-page py-10 rel z-1">
<div class="row"> <div class="container">
<div id="response-message" style="margin-top: 1rem;"></div> <div class="row">
<div class="col-lg-12"> <div id="response-message" style="margin-top: 1rem;"></div>
<div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'> <div class="col-lg-12">
<div style='padding:10px;'> <div class='infobox' data-aos='fade-up' data-aos-duration='1500' data-aos-offset='50'>
<input type="text" id="filterInput" class="filter-input" placeholder="Filter results..."> <div style='padding:10px;'>
<table> <input type="text" id="filterInput" class="filter-input" placeholder="Filter results...">
<thead> <table>
<tr> <thead>
<th></th> <tr>
<!-- <th></th> --> <th></th>
<th>First Name</th> <!-- <th></th> -->
<th>Last Name</th> <th>First Name</th>
<th>Email</th> <th>Last Name</th>
<th>Member</th> <th>Email</th>
<th>Indemnity</th> <th>Member</th>
<th>Date Joined</th> <th>Indemnity</th>
<th>Verified</th> <th>Date Joined</th>
<th></th> <th>Verified</th>
</tr> <th></th>
</thead> </tr>
<tbody> </thead>
<?php <tbody>
if ($result->num_rows > 0) { <?php
// Output data of each row if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { // Output data of each row
if (getUserMemberStatus($row['user_id'])) { while ($row = $result->fetch_assoc()) {
$member = "\u{2713}"; if (getUserMemberStatus($row['user_id'])) {
} else { $member = "\u{2713}";
$member = "\u{2717}"; } else {
} $member = "\u{2717}";
}
$indemnityPending = false;
$indemnityPending = false;
$userId = $row['user_id'];
$stmt = $conn->prepare("SELECT user_id FROM membership_application WHERE user_id = ? AND accept_indemnity = 0 LIMIT 1"); $userId = $row['user_id'];
$stmt->bind_param("i", $userId); $stmt = $conn->prepare("SELECT user_id FROM membership_application WHERE user_id = ? AND accept_indemnity = 0 LIMIT 1");
$stmt->execute(); $stmt->bind_param("i", $userId);
$stmt->store_result(); $stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$indemnityPending = true; if ($stmt->num_rows > 0) {
} $indemnityPending = true;
}
$stmt->close();
$stmt->close();
echo "<tr>
<td><img src=" . $row['profile_pic'] . " alt='Profile Picture' class='profile-pic'></td> 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['first_name']) . "</td>
<td>" . htmlspecialchars($row['email']) . "</td> <td>" . htmlspecialchars($row['last_name']) . "</td>
<td>" . $member . "</td> <td>" . htmlspecialchars($row['email']) . "</td>
<td>" . $indemnityPending . "</td> <td>" . $member . "</td>
<td>" . htmlspecialchars($row['date_joined']) . "</td> <td>" . $indemnityPending . "</td>
<td>"; <td>" . htmlspecialchars($row['date_joined']) . "</td>
if ($row['is_verified'] != 1) { <td>";
echo " if ($row['is_verified'] != 1) {
<button class='resend-btn' echo "
data-email=" . htmlspecialchars($row['email'] ?? '') . " <button class='resend-btn'
data-name=" . htmlspecialchars($row['first_name'] ?? '') . " " . htmlspecialchars($row['last_name'] ?? '') . " data-email=" . htmlspecialchars($row['email'] ?? '') . "
data-token=" . htmlspecialchars($row['token'] ?? '') . "> data-name=" . htmlspecialchars($row['first_name'] ?? '') . " " . htmlspecialchars($row['last_name'] ?? '') . "
Resend Email data-token=" . htmlspecialchars($row['token'] ?? '') . ">
</button>"; Resend Email
} else { </button>";
echo "\u{2713}"; } else {
} echo "\u{2713}";
// echo "</td> }
// <td><a href='linkmembership.php?user_id=".$row['user_id']."'>Link Membership</a></td> // echo "</td>
// <td><a href='linkmembership.php?user_id=".$row['user_id']."'>Link Membership</a></td>
// </tr>";
} // </tr>";
} else { }
echo '<tr><td colspan="5">No records found</td></tr>'; } else {
} ?> echo '<tr><td colspan="5">No records found</td></tr>';
} ?>
</tbody>
</table> </tbody>
</div> </table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<!-- Tour List Area end --> </section>
<script> <!-- Tour List Area end -->
document.querySelectorAll('.resend-btn').forEach(button => { <script>
button.addEventListener('click', function() { document.querySelectorAll('.resend-btn').forEach(button => {
const email = this.dataset.email; button.addEventListener('click', function() {
const name = this.dataset.name; const email = this.dataset.email;
const token = this.dataset.token; const name = this.dataset.name;
const token = this.dataset.token;
fetch('resend_verification.php', {
method: 'POST', fetch('resend_verification', {
headers: { method: 'POST',
'Content-Type': 'application/json' headers: {
}, 'Content-Type': 'application/json'
body: JSON.stringify({ },
email, body: JSON.stringify({
name, email,
token name,
}) token
}) })
.then(response => response.json()) })
.then(data => { .then(response => response.json())
const messageDiv = document.getElementById('response-message'); .then(data => {
messageDiv.textContent = data.message; const messageDiv = document.getElementById('response-message');
messageDiv.style.color = data.success ? 'green' : 'red'; messageDiv.textContent = data.message;
}) messageDiv.style.color = data.success ? 'green' : 'red';
.catch(error => { })
console.error('Error:', error); .catch(error => {
}); console.error('Error:', error);
}); });
}); });
</script> });
</script>
<?php include_once("insta_footer.php"); ?>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,35 +1,36 @@
<?php <?php
require_once("session.php"); $rootPath = dirname(dirname(__DIR__));
require_once("connection.php"); require_once($rootPath . "/src/config/session.php");
require_once("functions.php"); require_once($rootPath . "/src/config/connection.php");
require_once($rootPath . "/src/config/functions.php");
// Prepare the SQL query to fetch bar tabs along with user details, including user_id
$sql = " // Prepare the SQL query to fetch bar tabs along with user details, including user_id
SELECT bt.tab_id, u.user_id, u.first_name, u.last_name, u.profile_pic $sql = "
FROM bar_tabs bt SELECT bt.tab_id, u.user_id, u.first_name, u.last_name, u.profile_pic
JOIN users u ON bt.user_id = u.user_id FROM bar_tabs bt
"; JOIN users u ON bt.user_id = u.user_id
";
// Execute the query
$result = mysqli_query($conn, $sql); // Execute the query
$result = mysqli_query($conn, $sql);
// Check if there are results
if (mysqli_num_rows($result) > 0) { // Check if there are results
// Create an array to hold the data if (mysqli_num_rows($result) > 0) {
$barTabs = []; // Create an array to hold the data
$barTabs = [];
// Fetch each row
while ($row = mysqli_fetch_assoc($result)) { // Fetch each row
$barTabs[] = $row; while ($row = mysqli_fetch_assoc($result)) {
} $barTabs[] = $row;
}
// Return the data as JSON
echo json_encode($barTabs); // Return the data as JSON
} else { echo json_encode($barTabs);
echo json_encode([]); } else {
} echo json_encode([]);
}
// Close the database connection
mysqli_close($conn); // Close the database connection
?> mysqli_close($conn);
?>

View File

@@ -1,28 +1,30 @@
<?php <?php
require_once("connection.php"); $rootPath = dirname(dirname(__DIR__));
require_once($rootPath . "/src/config/connection.php");
if (isset($_GET['tab_id'])) {
$tab_id = (int) $_GET['tab_id']; // Convert to integer if (isset($_GET['tab_id'])) {
$tab_id = (int) $_GET['tab_id']; // Convert to integer
if ($tab_id <= 0) {
echo json_encode(['status' => 'error', 'message' => 'Invalid tab ID.']); if ($tab_id <= 0) {
exit(); echo json_encode(['status' => 'error', 'message' => 'Invalid tab ID.']);
} exit();
}
// Fetch drinks available for this tab
$stmt = $conn->prepare("SELECT * FROM bar_items"); // Fetch drinks available for this tab
$stmt->execute(); $stmt = $conn->prepare("SELECT * FROM bar_items");
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
$drinks = [];
while ($row = $result->fetch_assoc()) { $drinks = [];
$drinks[] = $row; while ($row = $result->fetch_assoc()) {
} $drinks[] = $row;
}
echo json_encode($drinks);
} else { echo json_encode($drinks);
echo json_encode(['status' => 'error', 'message' => 'Tab ID is required.']); } else {
} echo json_encode(['status' => 'error', 'message' => 'Tab ID is required.']);
?> }
?>

View File

@@ -1,22 +1,24 @@
<?php <?php
require_once("env.php"); $rootPath = dirname(dirname(__DIR__));
require_once("session.php"); require_once($rootPath . "/src/config/env.php");
require_once("connection.php"); require_once($rootPath . "/src/config/session.php");
require_once("functions.php"); require_once($rootPath . "/src/config/connection.php");
require_once($rootPath . "/src/config/functions.php");
if ($conn->connect_error) {
die(json_encode([])); // Return empty JSON on failure if ($conn->connect_error) {
} die(json_encode([])); // Return empty JSON on failure
}
$stmt = $conn->prepare("SELECT user_id, first_name, last_name FROM users ORDER BY first_name ASC");
$stmt->execute(); $stmt = $conn->prepare("SELECT user_id, first_name, last_name FROM users ORDER BY first_name ASC");
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
$users = [];
while ($row = $result->fetch_assoc()) { $users = [];
$users[] = $row; while ($row = $result->fetch_assoc()) {
} $users[] = $row;
}
echo json_encode($users);
$conn->close(); echo json_encode($users);
?> $conn->close();
?>

View File

@@ -1,37 +1,39 @@
<?php <?php
require_once("env.php"); $rootPath = dirname(dirname(__DIR__));
include_once('connection.php'); require_once($rootPath . "/src/config/env.php");
include_once('functions.php'); include_once('../config/connection.php');
$conn = openDatabaseConnection(); include_once('../config/functions.php');
$conn = openDatabaseConnection();
$stmt = $conn->prepare("SELECT
c.*, $stmt = $conn->prepare("SELECT
u.first_name, c.*,
u.last_name, u.first_name,
u.profile_pic u.last_name,
FROM campsites c u.profile_pic
LEFT JOIN users u ON c.user_id = u.user_id"); FROM campsites c
$stmt->execute(); LEFT JOIN users u ON c.user_id = u.user_id");
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
$campsites = [];
while ($row = $result->fetch_assoc()) { $campsites = [];
$campsites[] = [ while ($row = $result->fetch_assoc()) {
'id' => $row['id'], $campsites[] = [
'name' => $row['name'], 'id' => $row['id'],
'description' => $row['description'], 'name' => $row['name'],
'website' => $row['website'], 'description' => $row['description'],
'telephone' => $row['telephone'], 'website' => $row['website'],
'latitude' => $row['latitude'], 'telephone' => $row['telephone'],
'longitude' => $row['longitude'], 'latitude' => $row['latitude'],
'thumbnail' => $row['thumbnail'], 'longitude' => $row['longitude'],
'user' => [ 'thumbnail' => $row['thumbnail'],
'first_name' => $row['first_name'], 'user' => [
'last_name' => $row['last_name'], 'first_name' => $row['first_name'],
'profile_pic' => $row['profile_pic'] 'last_name' => $row['last_name'],
] 'profile_pic' => $row['profile_pic']
]; ]
} ];
}
header('Content-Type: application/json');
echo json_encode($campsites); header('Content-Type: application/json');
echo json_encode($campsites);

View File

@@ -1,22 +1,24 @@
<?php <?php
require_once("env.php"); $rootPath = dirname(dirname(__DIR__));
require_once("connection.php"); require_once($rootPath . "/src/config/env.php");
require_once($rootPath . "/src/config/connection.php");
if (isset($_POST['tab_id'])) {
$tab_id = (int) $_POST['tab_id']; // Ensure it's an integer if (isset($_POST['tab_id'])) {
$tab_id = (int) $_POST['tab_id']; // Ensure it's an integer
// Get the total from the bar_transactions table
$query = "SELECT SUM(item_price) AS total FROM bar_transactions WHERE tab_id = '$tab_id'"; // Get the total from the bar_transactions table
$result = mysqli_query($conn, $query); $query = "SELECT SUM(item_price) AS total FROM bar_transactions WHERE tab_id = '$tab_id'";
$result = mysqli_query($conn, $query);
if ($result) {
$row = mysqli_fetch_assoc($result); if ($result) {
$total = $row['total'] ? $row['total'] : 0; // If no transactions, total is 0 $row = mysqli_fetch_assoc($result);
echo json_encode(['status' => 'success', 'total' => $total]); $total = $row['total'] ? $row['total'] : 0; // If no transactions, total is 0
} else { echo json_encode(['status' => 'success', 'total' => $total]);
echo json_encode(['status' => 'error', 'message' => 'Failed to fetch total.']); } else {
} echo json_encode(['status' => 'error', 'message' => 'Failed to fetch total.']);
} else { }
echo json_encode(['status' => 'error', 'message' => 'Missing tab ID.']); } else {
} echo json_encode(['status' => 'error', 'message' => 'Missing tab ID.']);
?> }
?>

View File

@@ -1,144 +1,146 @@
<?php <?php
require_once("env.php"); $rootPath = dirname(dirname(__DIR__));
require_once("session.php"); require_once($rootPath . "/src/config/env.php");
require_once("connection.php"); require_once($rootPath . "/src/config/session.php");
require_once("functions.php"); require_once($rootPath . "/src/config/connection.php");
require_once 'google-client/vendor/autoload.php'; // Add this line for Google Client require_once($rootPath . "/src/config/functions.php");
require_once($rootPath . '/google-client/vendor/autoload.php'); // Add this line for Google Client
// Check if connection is established
if (!$conn) { // Check if connection is established
json_encode(['status' => 'error', 'message' => 'Database connection failed.']); if (!$conn) {
exit(); json_encode(['status' => 'error', 'message' => 'Database connection failed.']);
} exit();
}
// Google Client Setup
$client = new Google_Client(); // Google Client Setup
$client->setClientId('948441222188-8qhboq2urr8o9n35mc70s5h2nhd52v0m.apps.googleusercontent.com'); $client = new Google_Client();
$client->setClientSecret('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'); $client->setClientId('948441222188-8qhboq2urr8o9n35mc70s5h2nhd52v0m.apps.googleusercontent.com');
$client->setRedirectUri($_ENV['HOST'] . '/google_validate_login.php'); $client->setClientSecret('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');
$client->addScope("email"); $client->setRedirectUri($_ENV['HOST'] . '/google_validate_login.php');
$client->addScope("profile"); $client->addScope("email");
$client->addScope("profile");
// Check if Google login code is set
if (isset($_GET['code'])) { // Check if Google login code is set
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']); if (isset($_GET['code'])) {
if (!isset($token["error"])) { $token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
$client->setAccessToken($token['access_token']); if (!isset($token["error"])) {
$google_oauth = new Google_Service_Oauth2($client); $client->setAccessToken($token['access_token']);
$google_account_info = $google_oauth->userinfo->get(); $google_oauth = new Google_Service_Oauth2($client);
$google_account_info = $google_oauth->userinfo->get();
// Get user info from Google
$email = $google_account_info->email; // Get user info from Google
$name = $google_account_info->name; $email = $google_account_info->email;
$first_name = $google_account_info->given_name; $name = $google_account_info->name;
$last_name = $google_account_info->family_name; $first_name = $google_account_info->given_name;
$picture = $google_account_info->picture; $last_name = $google_account_info->family_name;
$picture = $google_account_info->picture;
// Check if the user exists in the database
$query = "SELECT * FROM users WHERE email = ?"; // Check if the user exists in the database
$stmt = $conn->prepare($query); $query = "SELECT * FROM users WHERE email = ?";
$stmt->bind_param("s", $email); $stmt = $conn->prepare($query);
$stmt->execute(); $stmt->bind_param("s", $email);
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows == 0) {
// User does not exist, so register them if ($result->num_rows == 0) {
$password = null; // No password for Google login // User does not exist, so register them
$query = "INSERT INTO users (email, first_name, last_name, profile_pic, password, is_verified) VALUES (?, ?, ?, ?, ?, ?)"; $password = null; // No password for Google login
$stmt = $conn->prepare($query); $query = "INSERT INTO users (email, first_name, last_name, profile_pic, password, is_verified) VALUES (?, ?, ?, ?, ?, ?)";
$is_verified = 1; // Assuming Google users are considered verified $stmt = $conn->prepare($query);
$stmt->bind_param("sssssi", $email, $first_name, $last_name, $picture, $password, $is_verified); $is_verified = 1; // Assuming Google users are considered verified
if ($stmt->execute()) { $stmt->bind_param("sssssi", $email, $first_name, $last_name, $picture, $password, $is_verified);
// User successfully registered, set session and redirect if ($stmt->execute()) {
$_SESSION['user_id'] = $conn->insert_id; // User successfully registered, set session and redirect
$_SESSION['first_name'] = $first_name; $_SESSION['user_id'] = $conn->insert_id;
$_SESSION['profile_pic'] = $picture; $_SESSION['first_name'] = $first_name;
// echo json_encode(['status' => 'success', 'message' => 'Google login successful']); $_SESSION['profile_pic'] = $picture;
header("Location: index.php"); // echo json_encode(['status' => 'success', 'message' => 'Google login successful']);
exit(); header("Location: index.php");
} else { exit();
// echo json_encode(['status' => 'error', 'message' => 'Failed to register user.']); } else {
header("Location: index.php"); // echo json_encode(['status' => 'error', 'message' => 'Failed to register user.']);
exit(); header("Location: index.php");
} exit();
} else { }
// User exists, set session and redirect } else {
$row = $result->fetch_assoc(); // User exists, set session and redirect
$_SESSION['user_id'] = $row['user_id']; $row = $result->fetch_assoc();
$_SESSION['first_name'] = $row['first_name']; $_SESSION['user_id'] = $row['user_id'];
$_SESSION['profile_pic'] = $row['profile_pic']; $_SESSION['first_name'] = $row['first_name'];
// echo json_encode(['status' => 'success', 'message' => 'Google login successful']); $_SESSION['profile_pic'] = $row['profile_pic'];
header("Location: index.php"); // echo json_encode(['status' => 'success', 'message' => 'Google login successful']);
exit(); header("Location: index.php");
} exit();
}
$stmt->close();
} else { $stmt->close();
echo "Login failed."; } else {
exit(); echo "Login failed.";
} exit();
} }
}
// Check if email and password login is requested
if (isset($_POST['email']) && isset($_POST['password'])) { // Check if email and password login is requested
// Retrieve and sanitize form data if (isset($_POST['email']) && isset($_POST['password'])) {
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL); // Retrieve and sanitize form data
$password = trim($_POST['password']); // Remove extra spaces $email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
$password = trim($_POST['password']); // Remove extra spaces
// Validate input
if (empty($email) || empty($password)) { // Validate input
echo json_encode(['status' => 'error', 'message' => 'Please enter both email and password.']); if (empty($email) || empty($password)) {
exit(); echo json_encode(['status' => 'error', 'message' => 'Please enter both email and password.']);
} exit();
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo json_encode(['status' => 'error', 'message' => 'Invalid email format.']); if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
exit(); echo json_encode(['status' => 'error', 'message' => 'Invalid email format.']);
} exit();
}
// Prepare SQL statement to fetch user details
$query = "SELECT * FROM users WHERE email = ?"; // Prepare SQL statement to fetch user details
$stmt = $conn->prepare($query); $query = "SELECT * FROM users WHERE email = ?";
$stmt = $conn->prepare($query);
if (!$stmt) {
echo json_encode(['status' => 'error', 'message' => 'Database query preparation failed.']); if (!$stmt) {
exit(); echo json_encode(['status' => 'error', 'message' => 'Database query preparation failed.']);
} exit();
}
$stmt->bind_param("s", $email);
$stmt->execute(); $stmt->bind_param("s", $email);
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
// Check if user exists and verify password
if ($result->num_rows == 1) { // Check if user exists and verify password
$row = $result->fetch_assoc(); if ($result->num_rows == 1) {
$row = $result->fetch_assoc();
// Check if the user is verified
if ($row['is_verified'] == 0) { // Check if the user is verified
echo json_encode(['status' => 'error', 'message' => 'Your account is not verified. Please check your email for the verification link.']); if ($row['is_verified'] == 0) {
exit(); echo json_encode(['status' => 'error', 'message' => 'Your account is not verified. Please check your email for the verification link.']);
} exit();
}
if (password_verify($password, $row['password'])) {
// Password is correct, set up session if (password_verify($password, $row['password'])) {
$_SESSION['user_id'] = $row['user_id']; // Adjust as per your table structure // Password is correct, set up session
$_SESSION['first_name'] = $row['first_name']; // Adjust as per your table structure $_SESSION['user_id'] = $row['user_id']; // Adjust as per your table structure
$_SESSION['profile_pic'] = $row['profile_pic']; $_SESSION['first_name'] = $row['first_name']; // Adjust as per your table structure
echo json_encode(['status' => 'success', 'message' => 'Successful Login']); $_SESSION['profile_pic'] = $row['profile_pic'];
} else { echo json_encode(['status' => 'success', 'message' => 'Successful Login']);
// Password is incorrect } else {
echo json_encode(['status' => 'error', 'message' => 'Invalid password.']); // Password is incorrect
} echo json_encode(['status' => 'error', 'message' => 'Invalid password.']);
} else { }
// User does not exist } else {
echo json_encode(['status' => 'error', 'message' => 'User with that email does not exist.']); // User does not exist
} echo json_encode(['status' => 'error', 'message' => 'User with that email does not exist.']);
}
// Close the statement and connection
$stmt->close(); // Close the statement and connection
} $stmt->close();
}
// Close connection
$conn->close(); // Close connection
exit(); $conn->close();
?> exit();
?>

60
src/bootstrap.php Normal file
View File

@@ -0,0 +1,60 @@
<?php
/**
* Bootstrap - Central configuration loader
*
* All PHP files should include this file first to set up:
* - Path constants
* - Database connection
* - Session management
* - Core functions
*
* Usage:
* <?php require_once(__DIR__ . '/../../bootstrap.php'); ?>
*
* Then use constants:
* - APP_ROOT: Root directory
* - SRC_ROOT: src/ directory
* - CONFIG_PATH: src/config/ directory
* - CLASSES_PATH: src/classes/ directory
* - COMPONENTS_PATH: components/ directory
*
* And use globals:
* - $conn: MySQLi connection
* - $db: DatabaseService instance
*/
// Define root paths - adjust based on file location
if (!defined('APP_ROOT')) {
define('APP_ROOT', dirname(__DIR__));
}
if (!defined('SRC_ROOT')) {
define('SRC_ROOT', APP_ROOT . '/src');
}
if (!defined('CONFIG_PATH')) {
define('CONFIG_PATH', SRC_ROOT . '/config');
}
if (!defined('CLASSES_PATH')) {
define('CLASSES_PATH', SRC_ROOT . '/classes');
}
if (!defined('COMPONENTS_PATH')) {
define('COMPONENTS_PATH', APP_ROOT . '/components');
}
if (!defined('ASSETS_PATH')) {
define('ASSETS_PATH', APP_ROOT . '/assets');
}
// Load environment variables
require_once(CONFIG_PATH . '/env.php');
// Load database connection
require_once(CONFIG_PATH . '/connection.php');
// Load session management
require_once(CONFIG_PATH . '/session.php');
// Load core functions
require_once(CONFIG_PATH . '/functions.php');
// Optional: Set global timezone
date_default_timezone_set($_ENV['TIMEZONE'] ?? 'Africa/Johannesburg');
?>

27
src/config/connection.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
// Disable mysqli exceptions so we can handle connection errors gracefully
mysqli_report(MYSQLI_REPORT_OFF);
$dbhost = $_ENV['DB_HOST'];
$dbuser = $_ENV['DB_USER'];
$dbpass = $_ENV['DB_PASS'];
$dbname = $_ENV['DB_NAME'];
$salt = $_ENV['SALT'];
// echo "hello. ". $dbhost;
if(!$conn = @mysqli_connect($dbhost, $dbuser, $dbpass, $dbname)){
// Log the error to file instead of stderr (no red output)
@error_log("Database Connection Error: " . mysqli_connect_error(), 3, dirname(__DIR__) . "/logs/db_errors.log");
$conn = null;
$db = null;
} else {
date_default_timezone_set('Africa/Johannesburg');
// Initialize DatabaseService for modern queries
require_once(__DIR__ . '/../../classes/DatabaseService.php');
$db = new DatabaseService($conn);
}

6
src/config/env.php Normal file
View File

@@ -0,0 +1,6 @@
<?php
require_once __DIR__ . '/../../vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../../');
$dotenv->load();

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,15 @@
<?php <?php
session_start(); session_start();
function Message(){ function Message(){
if(isset($_SESSION["message"])){ if(isset($_SESSION["message"])){
$output="<div class=\"message\">"; $output="<div class=\"message\">";
$output .= htmlentities($_SESSION['message']); $output .= htmlentities($_SESSION['message']);
$output .="</div>"; $output .="</div>";
$_SESSION['message']=null; $_SESSION['message']=null;
return $output; return $output;
} }
} }
?> ?>

View File

@@ -1,71 +1,72 @@
<?php <?php
require_once("env.php"); $rootPath = dirname(dirname(dirname(__DIR__)));
require_once("session.php"); require_once($rootPath . '/src/config/env.php');
require_once("connection.php"); require_once($rootPath . '/src/config/session.php');
require_once("functions.php"); require_once($rootPath . '/src/config/connection.php');
require_once($rootPath . '/src/config/functions.php');
$response = array('status' => 'error', 'message' => 'Something went wrong');
$response = array('status' => 'error', 'message' => 'Something went wrong');
// Check if the user is logged in
if (!isset($_SESSION['user_id'])) { // Check if the user is logged in
$response['message'] = 'You are not logged in.'; if (!isset($_SESSION['user_id'])) {
echo json_encode($response); $response['message'] = 'You are not logged in.';
exit(); echo json_encode($response);
} exit();
}
$user_id = $_SESSION['user_id'];
$user_id = $_SESSION['user_id'];
// Check if form data is submitted
if (isset($_POST['current_password'], $_POST['new_password'], $_POST['confirm_password'])) { // Check if form data is submitted
$current_password = $_POST['current_password']; if (isset($_POST['current_password'], $_POST['new_password'], $_POST['confirm_password'])) {
$new_password = $_POST['new_password']; $current_password = $_POST['current_password'];
$confirm_password = $_POST['confirm_password']; $new_password = $_POST['new_password'];
$confirm_password = $_POST['confirm_password'];
// Validate new passwords
if ($new_password !== $confirm_password) { // Validate new passwords
$response['message'] = 'New passwords do not match.'; if ($new_password !== $confirm_password) {
echo json_encode($response); $response['message'] = 'New passwords do not match.';
exit(); echo json_encode($response);
} exit();
}
// Fetch the stored hashed password from the database
$sql = "SELECT password FROM users WHERE user_id = ?"; // Fetch the stored hashed password from the database
$stmt = $conn->prepare($sql); $sql = "SELECT password FROM users WHERE user_id = ?";
$stmt->bind_param("i", $user_id); $stmt = $conn->prepare($sql);
$stmt->execute(); $stmt->bind_param("i", $user_id);
$result = $stmt->get_result(); $stmt->execute();
$user = $result->fetch_assoc(); $result = $stmt->get_result();
$user = $result->fetch_assoc();
if (!$user) {
$response['message'] = 'User not found.'; if (!$user) {
echo json_encode($response); $response['message'] = 'User not found.';
exit(); echo json_encode($response);
} exit();
}
// Verify the current password
if (!password_verify($current_password, $user['password'])) { // Verify the current password
$response['message'] = 'Current password is incorrect.'; if (!password_verify($current_password, $user['password'])) {
echo json_encode($response); $response['message'] = 'Current password is incorrect.';
exit(); echo json_encode($response);
} exit();
}
// Hash the new password
$new_password_hash = password_hash($new_password, PASSWORD_BCRYPT); // Hash the new password
$new_password_hash = password_hash($new_password, PASSWORD_BCRYPT);
// Update the new password in the database
$sql = "UPDATE users SET password = ? WHERE user_id = ?"; // Update the new password in the database
$stmt = $conn->prepare($sql); $sql = "UPDATE users SET password = ? WHERE user_id = ?";
$stmt->bind_param("si", $new_password_hash, $user_id); $stmt = $conn->prepare($sql);
$stmt->bind_param("si", $new_password_hash, $user_id);
if ($stmt->execute()) {
$response['status'] = 'success'; if ($stmt->execute()) {
$response['message'] = 'Password changed successfully.'; $response['status'] = 'success';
} else { $response['message'] = 'Password changed successfully.';
$response['message'] = 'Failed to change password.'; } else {
} $response['message'] = 'Failed to change password.';
} else { }
$response['message'] = 'Invalid form submission.'; } else {
} $response['message'] = 'Invalid form submission.';
}
echo json_encode($response);
?> echo json_encode($response);
?>

View File

@@ -1,84 +1,84 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php') ?> include_once(dirname(dirname(dirname(__DIR__))) . '/header.php') ?>
<style> <style>
@media (min-width: 991px) { @media (min-width: 991px) {
.container { .container {
max-width: 720px; max-width: 720px;
padding: 0 15px; /* Ensure padding doesn't cause overflow */ padding: 0 15px; /* Ensure padding doesn't cause overflow */
} }
</style> </style>
<!-- Contact Form Area start --> <!-- Contact Form Area start -->
<section class="contact-form-area py-120 rel z-1"> <section class="contact-form-area py-120 rel z-1">
<div class="container"> <div class="container">
<div class="row align-items-center"> <div class="row align-items-center">
<!-- <div class="col-lg-6"> <!-- <div class="col-lg-6">
<div style="text-align: center;"> <div style="text-align: center;">
<img style="width:400px;" src="assets/images/logos/weblogo.png" alt="About"> <img style="width:400px;" src="assets/images/logos/weblogo.png" alt="About">
</div> </div>
</div> --> </div> -->
<div class=""> <div class="">
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55"> <div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
<form id="loginForm" class="loginForm" name="loginForm" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <form id="loginForm" class="loginForm" name="loginForm" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="section-title"> <div class="section-title">
<h2>Forgot your password?</h2> <h2>Forgot your password?</h2>
<div class="pt-20" style="text-align: center;" id="responseMessage"></div> <!-- Message display area --> <div class="pt-20" style="text-align: center;" id="responseMessage"></div> <!-- Message display area -->
</div> </div>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label for="email">Email Address</label> <label for="email">Email Address</label>
<input type="email" id="email" name="email" class="form-control" placeholder="Enter Email" value="" required data-error="Please enter a valid Email address"> <input type="email" id="email" name="email" class="form-control" placeholder="Enter Email" value="" required data-error="Please enter a valid Email address">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
</div> </div>
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
<button type="submit" class="theme-btn style-two" style="width:100%;">Send Link</button> <button type="submit" class="theme-btn style-two" style="width:100%;">Send Link</button>
</div> </div>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Contact Form Area end --> <!-- Contact Form Area end -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
$('#loginForm').on('submit', function(event) { $('#loginForm').on('submit', function(event) {
event.preventDefault(); // Prevent the default form submission event.preventDefault(); // Prevent the default form submission
$.ajax({ $.ajax({
url: 'send_reset_link.php', url: 'send_reset_link',
type: 'POST', type: 'POST',
data: $(this).serialize(), data: $(this).serialize(),
dataType: 'json', dataType: 'json',
success: function(response) { success: function(response) {
// Parse response if needed // Parse response if needed
if (typeof response === "string") { if (typeof response === "string") {
response = JSON.parse(response); response = JSON.parse(response);
} }
if (response.status === 'success') { if (response.status === 'success') {
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>'); $('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
} else { } else {
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>'); $('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
} }
}, },
error: function() { error: function() {
$('#responseMessage').html('<div class="alert alert-danger">Error sending link. Please contact support.</div>'); $('#responseMessage').html('<div class="alert alert-danger">Error sending link. Please contact support.</div>');
} }
}); });
}); });
}); });
</script> </script>
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,124 +1,126 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); // Determine the correct path to header.php based on file location
// Include Google login PHP logic $rootPath = dirname(dirname(dirname(__DIR__)));
require_once 'google-client/vendor/autoload.php'; include_once($rootPath . '/header.php');
// Include Google login PHP logic
$client = new Google_Client(); require_once $rootPath . '/google-client/vendor/autoload.php';
$client->setClientId('948441222188-8qhboq2urr8o9n35mc70s5h2nhd52v0m.apps.googleusercontent.com');
$client->setClientSecret('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'); $client = new Google_Client();
$client->setRedirectUri($_ENV['HOST'] . '/validate_login.php'); $client->setClientId('948441222188-8qhboq2urr8o9n35mc70s5h2nhd52v0m.apps.googleusercontent.com');
$client->addScope("email"); $client->setClientSecret('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');
$client->addScope("profile"); $client->setRedirectUri($_ENV['HOST'] . '/validate_login.php');
$client->addScope("email");
// 👇 Add this to force the account picker $client->addScope("profile");
$client->setPrompt('select_account');
// 👇 Add this to force the account picker
$login_url = $client->createAuthUrl(); $client->setPrompt('select_account');
?>
$login_url = $client->createAuthUrl();
<style> ?>
@media (min-width: 991px) {
.container { <style>
max-width: 720px; @media (min-width: 991px) {
padding: 0 15px; /* Ensure padding doesn't cause overflow */ .container {
} max-width: 720px;
} padding: 0 15px; /* Ensure padding doesn't cause overflow */
</style> }
}
</style>
<!-- Contact Form Area start -->
<!-- Contact Form Area start -->
<section class="contact-form-area py-120 rel z-1">
<div class="container">
<div class="row align-items-center"> <section class="contact-form-area py-120 rel z-1">
<!-- <div class="col-lg-6"> <div class="container">
<div style="text-align: center;"> <div class="row align-items-center">
<img style="width:400px;" src="assets/images/logos/weblogo.png" alt="About"> <!-- <div class="col-lg-6">
</div> <div style="text-align: center;">
</div> --> <img style="width:400px;" src="assets/images/logos/weblogo.png" alt="About">
</div>
<div class=""> </div> -->
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
<form id="loginForm" class="loginForm" name="loginForm" action="assets/php/form-process.php" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <div class="">
<div class="section-title"> <div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
<h2>Log in</h2> <form id="loginForm" class="loginForm" name="loginForm" action="validate_login" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div style="text-align: center;" id="responseMessage"></div> <!-- Message display area --> <div class="section-title">
</div> <h2>Log in</h2>
<div style="text-align: center;" id="responseMessage"></div> <!-- Message display area -->
<!-- Google login button --> </div>
<div class="row mt-35">
<div class="col-md-12"> <!-- Google login button -->
<div class="form-group"> <div class="row mt-35">
<a href="<?php echo $login_url; ?>" style="width:100%;" class="theme-btn style-three"> <div class="col-md-12">
<img src="/assets/images/google.png" alt="Google Icon" style="width:20px; height:20px; margin-right: 10px; vertical-align: middle;"> <div class="form-group">
Login with Google <a href="<?php echo $login_url; ?>" style="width:100%;" class="theme-btn style-three">
</a> <img src="/assets/images/google.png" alt="Google Icon" style="width:20px; height:20px; margin-right: 10px; vertical-align: middle;">
</div> Login with Google
</div> </a>
</div> </div>
<div style="text-align: center; margin: 20px 0;"> </div>
<!-- <hr style="border: 1px solid #ddd; width: 50%; margin: 0 auto;"> --> </div>
<span style="top: -10px; padding: 0 10px;">or</span> <div style="text-align: center; margin: 20px 0;">
</div> <!-- <hr style="border: 1px solid #ddd; width: 50%; margin: 0 auto;"> -->
<span style="top: -10px; padding: 0 10px;">or</span>
<!-- Email login fields --> </div>
<div class="row mt-35">
<div class="col-md-12"> <!-- Email login fields -->
<div class="form-group"> <div class="row mt-35">
<label for="email">Email Address</label> <div class="col-md-12">
<input type="email" id="email" name="email" class="form-control" placeholder="Enter Email" value="" required data-error="Please enter a valid Email address"> <div class="form-group">
<div class="help-block with-errors"></div> <label for="email">Email Address</label>
</div> <input type="email" id="email" name="email" class="form-control" placeholder="Enter Email" value="" required data-error="Please enter a valid Email address">
</div> <div class="help-block with-errors"></div>
<div class="col-md-12"></div> </div>
<div class="form-group"> </div>
<label for="password">Password</label> <div class="col-md-12"></div>
<input type="password" id="password" name="password" class="form-control" placeholder="Enter Password" value="" required data-error="Please enter your password"> <div class="form-group">
<div class="help-block with-errors"></div> <label for="password">Password</label>
</div> <input type="password" id="password" name="password" class="form-control" placeholder="Enter Password" value="" required data-error="Please enter your password">
</div> <div class="help-block with-errors"></div>
</div>
<div class="col-md-12"> </div>
<div class="form-group mb-0">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <div class="col-md-12">
<button type="submit" class="theme-btn style-two" style="width:100%;">Log In</button> <div class="form-group mb-0">
</div> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
</div> <button type="submit" class="theme-btn style-two" style="width:100%;">Log In</button>
<div class="pt-20" style="text-align: center;">Don't have an account? <a href="register.php"><b>Register here.</b> </a>| <a href="forgot_password.php"><b>Forgot your password?</b></a></div> </div>
</form> </div>
</div> <div class="pt-20" style="text-align: center;">Don't have an account? <a href="register"><b>Register here.</b> </a>| <a href="forgot_password"><b>Forgot your password?</b></a></div>
</div> </form>
</div> </div>
</div> </div>
</section> </div>
<!-- Contact Form Area end --> </div>
</section>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <!-- Contact Form Area end -->
<script>
$(document).ready(function() { <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
$('#loginForm').on('submit', function(event) { <script>
event.preventDefault(); // Prevent the default form submission $(document).ready(function() {
$('#loginForm').on('submit', function(event) {
$.ajax({ event.preventDefault(); // Prevent the default form submission
url: 'validate_login.php',
type: 'POST', $.ajax({
data: $(this).serialize(), url: '<?= url("validate_login") ?>',
dataType: 'json', type: 'POST',
success: function(response) { data: $(this).serialize(),
if (response.status === 'success') { dataType: 'json',
window.location.href = 'index.php'; success: function(response) {
} else { if (response.status === 'success') {
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>'); window.location.href = '<?= url("index") ?>';
} } else {
}, $('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
error: function() { }
$('#responseMessage').html('<div class="alert alert-danger">An error occurred while processing your request.</div>'); },
} error: function() {
}); $('#responseMessage').html('<div class="alert alert-danger">An error occurred while processing your request.</div>');
}); }
}); });
</script> });
});
<?php include_once("insta_footer.php"); ?> </script>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,174 +1,174 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php') ?> include_once(dirname(dirname(dirname(__DIR__))) . '/header.php') ?>
<style> <style>
@media (min-width: 991px) { @media (min-width: 991px) {
.container { .container {
max-width: 720px; max-width: 720px;
padding: 0 15px; padding: 0 15px;
} }
} }
#passwordRequirements li { #passwordRequirements li {
transition: color 0.3s; transition: color 0.3s;
} }
.text-success { .text-success {
color: green !important; color: green !important;
} }
.text-danger { .text-danger {
color: red !important; color: red !important;
} }
</style> </style>
<!-- Contact Form Area start --> <!-- Contact Form Area start -->
<section class="contact-form-area py-70 rel z-1"> <section class="contact-form-area py-70 rel z-1">
<div class="container"> <div class="container">
<div class="row align-items-center"> <div class="row align-items-center">
<div class=""> <div class="">
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55"> <div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
<form id="registerForm" name="registerForm" action="register_user.php" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <form id="registerForm" name="registerForm" action="register_user" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="section-title"> <div class="section-title">
<h2>Register</h2> <h2>Register</h2>
</div> </div>
<p>Register to create your 4WDCSA.co.za user profile.</p> <p>Register to create your 4WDCSA.co.za user profile.</p>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="first_name">First Name</label> <label for="first_name">First Name</label>
<input type="text" id="first_name" name="first_name" class="form-control" placeholder="John" value="" required data-error="Please enter your Name"> <input type="text" id="first_name" name="first_name" class="form-control" placeholder="John" value="" required data-error="Please enter your Name">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="last_name">Last Name</label> <label for="last_name">Last Name</label>
<input type="text" id="last_name" name="last_name" class="form-control" placeholder="Smith" value="" required data-error="Please enter your Last Name"> <input type="text" id="last_name" name="last_name" class="form-control" placeholder="Smith" value="" required data-error="Please enter your Last Name">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label for="phone_number">Phone Number</label> <label for="phone_number">Phone Number</label>
<input type="text" id="phone_number" name="phone_number" class="form-control" placeholder="Phone" value="" required data-error="Please enter your Phone"> <input type="text" id="phone_number" name="phone_number" class="form-control" placeholder="Phone" value="" required data-error="Please enter your Phone">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label for="email">Email Address</label> <label for="email">Email Address</label>
<input type="email" id="email" name="email" class="form-control" placeholder="Enter email" value="" required data-error="Please enter your Email"> <input type="email" id="email" name="email" class="form-control" placeholder="Enter email" value="" required data-error="Please enter your Email">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label for="password">Password</label> <label for="password">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Enter password" value="" required data-error="Please enter your password"> <input type="password" id="password" name="password" class="form-control" placeholder="Enter password" value="" required data-error="Please enter your password">
<ul id="passwordRequirements" class="small mt-2" style="list-style: none; padding-left: 0;"> <ul id="passwordRequirements" class="small mt-2" style="list-style: none; padding-left: 0;">
<li id="length" class="text-danger"> At least 8 characters</li> <li id="length" class="text-danger"> At least 8 characters</li>
<li id="uppercase" class="text-danger"> At least one uppercase letter</li> <li id="uppercase" class="text-danger"> At least one uppercase letter</li>
<li id="lowercase" class="text-danger"> At least one lowercase letter</li> <li id="lowercase" class="text-danger"> At least one lowercase letter</li>
<li id="number" class="text-danger"> At least one number</li> <li id="number" class="text-danger"> At least one number</li>
<li id="special" class="text-danger"> At least one special character</li> <li id="special" class="text-danger"> At least one special character</li>
</ul> </ul>
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label for="password_confirm">Confirm Password</label> <label for="password_confirm">Confirm Password</label>
<input type="password" id="password_confirm" name="password_confirm" class="form-control" placeholder="Enter password" value="" required data-error="Please enter your password"> <input type="password" id="password_confirm" name="password_confirm" class="form-control" placeholder="Enter password" value="" required data-error="Please enter your password">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<button type="submit" class="theme-btn style-two" style="width:100%;">Register</button> <button type="submit" class="theme-btn style-two" style="width:100%;">Register</button>
<div id="msgSubmit" class="hidden"></div> <div id="msgSubmit" class="hidden"></div>
</div> </div>
<div id="responseMessage"></div> <!-- Message display area --> <div id="responseMessage"></div> <!-- Message display area -->
</div> </div>
<div class="pt-20">Already have an account? <a href="login.php"><b>Log in here.</b></a></div> <div class="pt-20">Already have an account? <a href="login"><b>Log in here.</b></a></div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Contact Form Area end --> <!-- Contact Form Area end -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script> <script>
function updatePasswordFeedback(password) { function updatePasswordFeedback(password) {
const length = password.length >= 8; const length = password.length >= 8;
const uppercase = /[A-Z]/.test(password); const uppercase = /[A-Z]/.test(password);
const lowercase = /[a-z]/.test(password); const lowercase = /[a-z]/.test(password);
const number = /[0-9]/.test(password); const number = /[0-9]/.test(password);
const special = /[\W_]/.test(password); const special = /[\W_]/.test(password);
$('#length').toggleClass('text-success', length).toggleClass('text-danger', !length).html(`${length ? '✓' : '✗'} At least 8 characters`); $('#length').toggleClass('text-success', length).toggleClass('text-danger', !length).html(`${length ? '✓' : '✗'} At least 8 characters`);
$('#uppercase').toggleClass('text-success', uppercase).toggleClass('text-danger', !uppercase).html(`${uppercase ? '✓' : '✗'} At least one uppercase letter`); $('#uppercase').toggleClass('text-success', uppercase).toggleClass('text-danger', !uppercase).html(`${uppercase ? '✓' : '✗'} At least one uppercase letter`);
$('#lowercase').toggleClass('text-success', lowercase).toggleClass('text-danger', !lowercase).html(`${lowercase ? '✓' : '✗'} At least one lowercase letter`); $('#lowercase').toggleClass('text-success', lowercase).toggleClass('text-danger', !lowercase).html(`${lowercase ? '✓' : '✗'} At least one lowercase letter`);
$('#number').toggleClass('text-success', number).toggleClass('text-danger', !number).html(`${number ? '✓' : '✗'} At least one number`); $('#number').toggleClass('text-success', number).toggleClass('text-danger', !number).html(`${number ? '✓' : '✗'} At least one number`);
$('#special').toggleClass('text-success', special).toggleClass('text-danger', !special).html(`${special ? '✓' : '✗'} At least one special character`); $('#special').toggleClass('text-success', special).toggleClass('text-danger', !special).html(`${special ? '✓' : '✗'} At least one special character`);
} }
$('#password').on('input', function() { $('#password').on('input', function() {
const password = $(this).val(); const password = $(this).val();
updatePasswordFeedback(password); updatePasswordFeedback(password);
}); });
$(document).ready(function() { $(document).ready(function() {
$('#registerForm').on('submit', function(event) { $('#registerForm').on('submit', function(event) {
event.preventDefault(); // Prevent default form submission event.preventDefault(); // Prevent default form submission
const password = $('#password').val(); const password = $('#password').val();
const confirmPassword = $('#password_confirm').val(); const confirmPassword = $('#password_confirm').val();
const passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/; const passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/;
if (!passwordPattern.test(password)) { if (!passwordPattern.test(password)) {
$('#responseMessage').html(` $('#responseMessage').html(`
<div class="alert alert-danger"> <div class="alert alert-danger">
Password must be at least 8 characters long, include uppercase and lowercase letters, a number, and a special character. Password must be at least 8 characters long, include uppercase and lowercase letters, a number, and a special character.
</div> </div>
`); `);
return; return;
} }
if (password !== confirmPassword) { if (password !== confirmPassword) {
$('#responseMessage').html(` $('#responseMessage').html(`
<div class="alert alert-danger">Passwords do not match.</div> <div class="alert alert-danger">Passwords do not match.</div>
`); `);
return; return;
} }
// If validation passes, proceed with AJAX // If validation passes, proceed with AJAX
$.ajax({ $.ajax({
url: 'register_user.php', url: 'register_user',
type: 'POST', type: 'POST',
data: $(this).serialize(), data: $(this).serialize(),
dataType: 'json', dataType: 'json',
success: function(response) { success: function(response) {
if (response.status === 'success') { if (response.status === 'success') {
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>'); $('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
$('#registerForm')[0].reset(); // Optionally reset the form $('#registerForm')[0].reset(); // Optionally reset the form
} else { } else {
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>'); $('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
} }
}, },
error: function() { error: function() {
$('#responseMessage').html('<div class="alert alert-danger">An error occurred while processing your request.</div>'); $('#responseMessage').html('<div class="alert alert-danger">An error occurred while processing your request.</div>');
} }
}); });
}); });
}); });
</script> </script>
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,40 +1,41 @@
<?php <?php
header('Content-Type: application/json'); header('Content-Type: application/json');
require_once("connection.php"); $rootPath = dirname(dirname(dirname(__DIR__)));
require_once("functions.php"); require_once($rootPath . '/src/config/connection.php');
require_once "vendor/autoload.php"; require_once($rootPath . '/src/config/functions.php');
require_once($rootPath . '/vendor/autoload.php');
use GuzzleHttp\Client;
use GuzzleHttp\Client;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents('php://input'), true); if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
if (!isset($data['email'], $data['name'], $data['token'])) {
echo json_encode([ if (!isset($data['email'], $data['name'], $data['token'])) {
'success' => false, echo json_encode([
'message' => 'Missing required fields.' 'success' => false,
]); 'message' => 'Missing required fields.'
exit; ]);
} exit;
}
$email = $data['email'];
$name = $data['name']; $email = $data['email'];
$token = $data['token']; $name = $data['name'];
$token = $data['token'];
if (sendVerificationEmail($email, $name, $token)) {
$_SESSION['message'] = "Verification mail resend successful!"; if (sendVerificationEmail($email, $name, $token)) {
echo json_encode([ $_SESSION['message'] = "Verification mail resend successful!";
'success' => true, echo json_encode([
'message' => "Verification email sent to $email." 'success' => true,
]); 'message' => "Verification email sent to $email."
} else { ]);
$_SESSION['message'] = "Verification mail resend FAILED!"; } else {
echo json_encode([ $_SESSION['message'] = "Verification mail resend FAILED!";
'success' => false, echo json_encode([
'message' => "Failed to send verification email to $email." 'success' => false,
]); 'message' => "Failed to send verification email to $email."
} ]);
} }
}

View File

@@ -1,113 +1,113 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); include_once(dirname(dirname(dirname(__DIR__))) . '/header.php');
$token = $_GET['token'] ?? ''; $token = $_GET['token'] ?? '';
if (empty($token)) { if (empty($token)) {
die("Invalid token."); die("Invalid token.");
} }
// Verify the token // Verify the token
$sql = "SELECT user_id FROM password_resets WHERE token = ? AND expires_at > NOW()"; $sql = "SELECT user_id FROM password_resets WHERE token = ? AND expires_at > NOW()";
$stmt = $conn->prepare($sql); $stmt = $conn->prepare($sql);
$stmt->bind_param("s", $token); $stmt->bind_param("s", $token);
$stmt->execute(); $stmt->execute();
$result = $stmt->get_result(); $result = $stmt->get_result();
if ($result->num_rows === 0) { if ($result->num_rows === 0) {
die("Token is invalid or expired."); die("Token is invalid or expired.");
} }
$user = $result->fetch_assoc(); $user = $result->fetch_assoc();
$user_id = $user['user_id']; $user_id = $user['user_id'];
// Display the reset password form // Display the reset password form
?> ?>
<style> <style>
@media (min-width: 991px) { @media (min-width: 991px) {
.container { .container {
max-width: 720px; max-width: 720px;
padding: 0 15px; /* Ensure padding doesn't cause overflow */ padding: 0 15px; /* Ensure padding doesn't cause overflow */
} }
</style> </style>
<!-- Contact Form Area start --> <!-- Contact Form Area start -->
<section class="contact-form-area py-120 rel z-1"> <section class="contact-form-area py-120 rel z-1">
<div class="container"> <div class="container">
<div class="row align-items-center"> <div class="row align-items-center">
<div class=""> <div class="">
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55"> <div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
<form id="changePasswordForm" class="loginForm" name="changePasswordForm" action="update_password.php" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <form id="changePasswordForm" class="loginForm" name="changePasswordForm" action="update_password" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="section-title"> <div class="section-title">
<h2>Reset Password</h2> <h2>Reset Password</h2>
<div class="pt-20" style="text-align: center;" id="responseMessage"></div> <!-- Message display area --> <div class="pt-20" style="text-align: center;" id="responseMessage"></div> <!-- Message display area -->
</div> </div>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label for="new_password">New Password</label> <label for="new_password">New Password</label>
<input type="password" id="new_password" name="new_password" class="form-control" placeholder="Enter password" value="" required data-error="Please enter your password"> <input type="password" id="new_password" name="new_password" class="form-control" placeholder="Enter password" value="" required data-error="Please enter your password">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<label for="confirm_password">Confirm Password</label> <label for="confirm_password">Confirm Password</label>
<input type="password" id="confirm_password" name="confirm_password" class="form-control" placeholder="Confirm password" value="" required data-error="Please confirm your password"> <input type="password" id="confirm_password" name="confirm_password" class="form-control" placeholder="Confirm password" value="" required data-error="Please confirm your password">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
<input type="hidden" name="token" value="<?php echo htmlspecialchars($token); ?>"> <input type="hidden" name="token" value="<?php echo htmlspecialchars($token); ?>">
<button type="submit" class="theme-btn style-two" style="width:100%;">Reset Password</button> <button type="submit" class="theme-btn style-two" style="width:100%;">Reset Password</button>
</div> </div>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Contact Form Area end --> <!-- Contact Form Area end -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
// Change Password // Change Password
$('#changePasswordForm').on('submit', function(event) { $('#changePasswordForm').on('submit', function(event) {
event.preventDefault(); // Prevent default form submission event.preventDefault(); // Prevent default form submission
$.ajax({ $.ajax({
url: 'update_password.php', url: 'update_password',
type: 'POST', type: 'POST',
data: $(this).serialize(), data: $(this).serialize(),
success: function(response) { success: function(response) {
// Parse response if needed // Parse response if needed
if (typeof response === "string") { if (typeof response === "string") {
response = JSON.parse(response); response = JSON.parse(response);
} }
if (response.status === 'success') { if (response.status === 'success') {
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>'); $('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
} else { } else {
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>'); $('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
} }
}, },
error: function() { error: function() {
$('#responseMessage2').html('<div class="alert alert-danger">Error changing password.</div>'); $('#responseMessage2').html('<div class="alert alert-danger">Error changing password.</div>');
} }
}); });
}); });
}); });
</script> </script>
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,60 +1,61 @@
<?php <?php
require_once("env.php"); $rootPath = dirname(dirname(dirname(__DIR__)));
require_once("connection.php"); require_once($rootPath . '/src/config/env.php');
require_once("functions.php"); require_once($rootPath . '/src/config/connection.php');
require_once($rootPath . '/src/config/functions.php');
$response = array('status' => 'error', 'message' => 'Something went wrong');
$response = array('status' => 'error', 'message' => 'Something went wrong');
if (isset($_POST['token'], $_POST['new_password'], $_POST['confirm_password'])) {
$token = $_POST['token']; if (isset($_POST['token'], $_POST['new_password'], $_POST['confirm_password'])) {
$new_password = $_POST['new_password']; $token = $_POST['token'];
$confirm_password = $_POST['confirm_password']; $new_password = $_POST['new_password'];
$confirm_password = $_POST['confirm_password'];
if ($new_password !== $confirm_password) {
$response['message'] = 'Passwords do not match.'; if ($new_password !== $confirm_password) {
echo json_encode($response); $response['message'] = 'Passwords do not match.';
exit(); echo json_encode($response);
} exit();
}
// Verify the token
$sql = "SELECT user_id FROM password_resets WHERE token = ? AND expires_at > NOW()"; // Verify the token
$stmt = $conn->prepare($sql); $sql = "SELECT user_id FROM password_resets WHERE token = ? AND expires_at > NOW()";
$stmt->bind_param("s", $token); $stmt = $conn->prepare($sql);
$stmt->execute(); $stmt->bind_param("s", $token);
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
$response['message'] = 'Token is invalid or expired.'; if ($result->num_rows === 0) {
echo json_encode($response); $response['message'] = 'Token is invalid or expired.';
exit(); echo json_encode($response);
} exit();
}
$user = $result->fetch_assoc();
$user_id = $user['user_id']; $user = $result->fetch_assoc();
$user_id = $user['user_id'];
// Hash the new password
$new_password_hash = password_hash($new_password, PASSWORD_BCRYPT); // Hash the new password
$new_password_hash = password_hash($new_password, PASSWORD_BCRYPT);
// Update the new password in the database
$sql = "UPDATE users SET password = ? WHERE user_id = ?"; // Update the new password in the database
$stmt = $conn->prepare($sql); $sql = "UPDATE users SET password = ? WHERE user_id = ?";
$stmt->bind_param("si", $new_password_hash, $user_id); $stmt = $conn->prepare($sql);
$stmt->bind_param("si", $new_password_hash, $user_id);
if ($stmt->execute()) {
// Delete the token from the database if ($stmt->execute()) {
$sql = "DELETE FROM password_resets WHERE token = ?"; // Delete the token from the database
$stmt = $conn->prepare($sql); $sql = "DELETE FROM password_resets WHERE token = ?";
$stmt->bind_param("s", $token); $stmt = $conn->prepare($sql);
$stmt->execute(); $stmt->bind_param("s", $token);
$stmt->execute();
$response['status'] = 'success';
$response['message'] = 'Password has been successfully reset.'; $response['status'] = 'success';
} else { $response['message'] = 'Password has been successfully reset.';
$response['message'] = 'Failed to reset password.'; } else {
} $response['message'] = 'Failed to reset password.';
} else { }
$response['message'] = 'Invalid form submission.'; } else {
} $response['message'] = 'Invalid form submission.';
}
echo json_encode($response);
?> echo json_encode($response);
?>

View File

@@ -1,38 +1,39 @@
<?php <?php
require_once("env.php"); $rootPath = dirname(dirname(dirname(__DIR__)));
require_once("connection.php"); require_once($rootPath . '/src/config/env.php');
require_once("functions.php"); require_once($rootPath . '/src/config/connection.php');
require_once($rootPath . '/src/config/functions.php');
// Create connection
$conn = openDatabaseConnection(); // Create connection
$conn = openDatabaseConnection();
// Check connection
if ($conn->connect_error) { // Check connection
die("Connection failed: " . $conn->connect_error); if ($conn->connect_error) {
} die("Connection failed: " . $conn->connect_error);
}
// Verify token
if (isset($_GET['token'])) { // Verify token
$token = $conn->real_escape_string($_GET['token']); if (isset($_GET['token'])) {
$token = $conn->real_escape_string($_GET['token']);
// Prepare and execute query
$stmt = $conn->prepare('UPDATE users SET is_verified = 1 WHERE token = ?'); // Prepare and execute query
$stmt->bind_param('s', $token); $stmt = $conn->prepare('UPDATE users SET is_verified = 1 WHERE token = ?');
$stmt->bind_param('s', $token);
if ($stmt->execute()) {
if ($stmt->affected_rows > 0) { if ($stmt->execute()) {
header('Location: login.php'); if ($stmt->affected_rows > 0) {
} else { header('Location: login.php');
header('Location: login.php'); } else {
} header('Location: login.php');
} else { }
echo 'Error: ' . $stmt->error; } else {
} echo 'Error: ' . $stmt->error;
}
$stmt->close();
} else { $stmt->close();
echo 'No token provided.'; } else {
} echo 'No token provided.';
}
$conn->close();
?> $conn->close();
?>

View File

@@ -1,324 +1,325 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
checkUserSession(); include_once($rootPath . '/header.php');
$user_id = $_SESSION['user_id']; checkUserSession();
$user_id = $_SESSION['user_id'];
?>
<style> ?>
.image { <style>
width: 400px; .image {
/* Set your desired width */ width: 400px;
height: 350px; /* Set your desired width */
/* Set your desired height */ height: 350px;
overflow: hidden; /* Set your desired height */
/* Hide any overflow */ overflow: hidden;
display: block; /* Hide any overflow */
/* Ensure proper block behavior */ display: block;
} /* Ensure proper block behavior */
}
.image img {
width: 100%; .image img {
/* Image scales to fill the container */ width: 100%;
height: 100%; /* Image scales to fill the container */
/* Image scales to fill the container */ height: 100%;
object-fit: cover; /* Image scales to fill the container */
/* Fills the container while maintaining aspect ratio */ object-fit: cover;
object-position: top; /* Fills the container while maintaining aspect ratio */
/* Aligns the top of the image with the top of the container */ object-position: top;
display: block; /* Aligns the top of the image with the top of the container */
/* Prevents inline whitespace issues */ display: block;
} /* Prevents inline whitespace issues */
}
.message-box {
text-align: center; .message-box {
position: relative; text-align: center;
padding: 10px; position: relative;
padding-right: 35px; padding: 10px;
/* Ensures text doesn't overlap with the close button */ padding-right: 35px;
} /* Ensures text doesn't overlap with the close button */
}
.close-btn {
position: absolute; .close-btn {
right: 10px; position: absolute;
top: 50%; right: 10px;
transform: translateY(-50%); top: 50%;
/* Centers vertically */ transform: translateY(-50%);
cursor: pointer; /* Centers vertically */
font-size: 20px; cursor: pointer;
font-weight: bold; font-size: 20px;
color: #333; font-weight: bold;
background: none; color: #333;
border: none; background: none;
} border: none;
}
.close-btn:hover {
color: red; .close-btn:hover {
} color: red;
}
</style>
</style> </style>
<?php </style>
$pageTitle = 'My Bookings'; <?php
$breadcrumbs = [['Home' => 'index.php']]; $pageTitle = 'My Bookings';
require_once('components/banner.php'); $breadcrumbs = [['Home' => 'index.php']];
?> require_once($rootPath . '/components/banner.php');
?>
<!-- Tour List Area start -->
<section class="tour-list-page py-100 rel z-1"> <!-- Tour List Area start -->
<div class="container"> <section class="tour-list-page py-100 rel z-1">
<div class="row"> <div class="container">
<div class="row">
<div class="col-lg-12">
<?php if (isset($_SESSION['message'])): ?> <div class="col-lg-12">
<div class="alert alert-warning message-box"> <?php if (isset($_SESSION['message'])): ?>
<?php echo $_SESSION['message']; ?> <div class="alert alert-warning message-box">
<span class="close-btn" onclick="this.parentElement.style.display='none'">&times;</span> <?php echo $_SESSION['message']; ?>
</div> <span class="close-btn" onclick="this.parentElement.style.display='none'">&times;</span>
<?php unset($_SESSION['message']); ?> </div>
<?php endif; ?> <?php unset($_SESSION['message']); ?>
<?php endif; ?>
<div class="shop-shorter rel z-3 mb-20">
<!-- <ul class="grid-list mb-15 me-2"> <div class="shop-shorter rel z-3 mb-20">
<li><a href="#"><i class="fal fa-border-all"></i></a></li> <!-- <ul class="grid-list mb-15 me-2">
<li><a href="#"><i class="far fa-list"></i></a></li> <li><a href="#"><i class="fal fa-border-all"></i></a></li>
</ul> --> <li><a href="#"><i class="far fa-list"></i></a></li>
<div class="sort-text mb-15 me-4 me-xl-auto"> </ul> -->
<?php echo countUpcomingBookings($user_id); ?> Upcoming Bookings <div class="sort-text mb-15 me-4 me-xl-auto">
</div> <?php echo countUpcomingBookings($user_id); ?> Upcoming Bookings
<label> </div>
<input type="checkbox" id="togglePastBookings" onchange="togglePastBookings()"> Show Past Bookings <label>
</label> <input type="checkbox" id="togglePastBookings" onchange="togglePastBookings()"> Show Past Bookings
<!-- <div class="sort-text mb-15 me-4"> </label>
Sort By <!-- <div class="sort-text mb-15 me-4">
</div> --> Sort By
<!-- <select> </div> -->
<option value="default" selected="">Sort By</option> <!-- <select>
<option value="new">Newness</option> <option value="default" selected="">Sort By</option>
<option value="old">Oldest</option> <option value="new">Newness</option>
<option value="hight-to-low">High To Low</option> <option value="old">Oldest</option>
<option value="low-to-high">Low To High</option> <option value="hight-to-low">High To Low</option>
</select> --> <option value="low-to-high">Low To High</option>
</div> </select> -->
<?php </div>
// Query to retrieve data from the bookings table <?php
$sql = "SELECT * FROM bookings WHERE user_id = ? ORDER BY to_date DESC"; // Query to retrieve data from the bookings table
$sql = "SELECT * FROM bookings WHERE user_id = ? ORDER BY to_date DESC";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $user_id); $stmt = $conn->prepare($sql);
$stmt->execute(); $stmt->bind_param("i", $user_id);
$result = $stmt->get_result(); $stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
// Loop through each row if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { // Loop through each row
$booking_id = $row['booking_id']; while ($row = $result->fetch_assoc()) {
$booking_type = $row['booking_type']; $booking_id = $row['booking_id'];
$from_date = $row['from_date']; $booking_type = $row['booking_type'];
$to_date = $row['to_date']; $from_date = $row['from_date'];
$num_vehicles = $row['num_vehicles']; $to_date = $row['to_date'];
$num_adults = $row['num_adults']; $num_vehicles = $row['num_vehicles'];
$num_children = $row['num_children']; $num_adults = $row['num_adults'];
$add_firewood = $row['add_firewood']; $num_children = $row['num_children'];
$total_amount = $row['total_amount']; $add_firewood = $row['add_firewood'];
$discount_amount = $row['discount_amount']; $total_amount = $row['total_amount'];
$status = $row['status']; $discount_amount = $row['discount_amount'];
$trip_id = $row['trip_id']; $status = $row['status'];
$course_id = $row['course_id']; $trip_id = $row['trip_id'];
$course_nonmembers = $row['course_non_members']; $course_id = $row['course_id'];
$radio = $row['radio']; $course_nonmembers = $row['course_non_members'];
$amount = $total_amount - $discount_amount; $radio = $row['radio'];
$total_adults = $num_adults + $course_nonmembers; $amount = $total_amount - $discount_amount;
$total_adults = $num_adults + $course_nonmembers;
if (!is_null($trip_id)) {
// Prepare a SQL statement to retrieve trip details if (!is_null($trip_id)) {
$sql_trip = "SELECT trip_name, location, short_description, start_date, end_date FROM trips WHERE trip_id = ?"; // Prepare a SQL statement to retrieve trip details
$stmt_trip = $conn->prepare($sql_trip); $sql_trip = "SELECT trip_name, location, short_description, start_date, end_date FROM trips WHERE trip_id = ?";
$stmt_trip->bind_param("i", $trip_id); $stmt_trip = $conn->prepare($sql_trip);
$stmt_trip->bind_param("i", $trip_id);
if ($stmt_trip->execute()) {
$result_trip = $stmt_trip->get_result(); if ($stmt_trip->execute()) {
$result_trip = $stmt_trip->get_result();
if ($result_trip->num_rows > 0) {
// Fetch trip details if ($result_trip->num_rows > 0) {
$trip_data = $result_trip->fetch_assoc(); // Fetch trip details
$trip_name = $trip_data['trip_name'] ?? "Trip Name Placeholder"; $trip_data = $result_trip->fetch_assoc();
$location = $trip_data['location'] ?? "Location Placeholder"; $trip_name = $trip_data['trip_name'] ?? "Trip Name Placeholder";
$short_description = $trip_data['short_description'] ?? "Short description of the trip."; $location = $trip_data['location'] ?? "Location Placeholder";
$start_date = $trip_data['start_date'] ?? $from_date; // Default to booking start date if not set $short_description = $trip_data['short_description'] ?? "Short description of the trip.";
$end_date = $trip_data['end_date'] ?? $to_date; // Default to booking end date if not set $start_date = $trip_data['start_date'] ?? $from_date; // Default to booking start date if not set
$end_date = $trip_data['end_date'] ?? $to_date; // Default to booking end date if not set
} else {
// Set default values if no trip data found } else {
$trip_name = "Trip Name Placeholder"; // Set default values if no trip data found
$location = "Location Placeholder"; $trip_name = "Trip Name Placeholder";
$short_description = "Short description of the trip."; $location = "Location Placeholder";
$start_date = $from_date; // Default to booking start date $short_description = "Short description of the trip.";
$end_date = $to_date; // Default to booking end date $start_date = $from_date; // Default to booking start date
} $end_date = $to_date; // Default to booking end date
} else { }
// Handle SQL execution error } else {
echo "Error retrieving trip information: " . $stmt_trip->error; // Handle SQL execution error
} echo "Error retrieving trip information: " . $stmt_trip->error;
}
// Close the statement
$stmt_trip->close(); // Close the statement
} elseif (!is_null($course_id)) { $stmt_trip->close();
// Prepare a SQL statement to retrieve trip details } elseif (!is_null($course_id)) {
$sql_course = "SELECT course_type, date FROM courses WHERE course_id = ?"; // Prepare a SQL statement to retrieve trip details
$stmt_course = $conn->prepare($sql_course); $sql_course = "SELECT course_type, date FROM courses WHERE course_id = ?";
$stmt_course->bind_param("i", $course_id); $stmt_course = $conn->prepare($sql_course);
$stmt_course->bind_param("i", $course_id);
if ($stmt_course->execute()) {
$result_course = $stmt_course->get_result(); if ($stmt_course->execute()) {
$result_course = $stmt_course->get_result();
if ($result_course->num_rows > 0) {
// Fetch trip details if ($result_course->num_rows > 0) {
$trip_data = $result_course->fetch_assoc(); // Fetch trip details
$date = $trip_data['date'] ?? "Location Placeholder"; $trip_data = $result_course->fetch_assoc();
$type = $trip_data['course_type'] ?? "Trip Name Placeholder"; $date = $trip_data['date'] ?? "Location Placeholder";
if ($type === "driver_training") { $type = $trip_data['course_type'] ?? "Trip Name Placeholder";
$trip_name = "Basic 4X4 Driver Training Course"; if ($type === "driver_training") {
} elseif ($type === "bush_mechanics") { $trip_name = "Basic 4X4 Driver Training Course";
$trip_name = "Bush Mechanics Course"; } elseif ($type === "bush_mechanics") {
} elseif ($type === "rescue_recovery") { $trip_name = "Bush Mechanics Course";
$trip_name = "Rescue & Recovery Training Course"; } elseif ($type === "rescue_recovery") {
} else { $trip_name = "Rescue & Recovery Training Course";
$trip_name = "General Course"; // Default fallback description } else {
} $trip_name = "General Course"; // Default fallback description
$start_date = $date; }
$end_date = $date; $start_date = $date;
$location = "BASE4, Hennops"; $end_date = $date;
$short_description = getDetail($type); $location = "BASE4, Hennops";
} else { $short_description = getDetail($type);
// Set default values if no trip data found } else {
$trip_name = "Trip Name Placeholder"; // Set default values if no trip data found
$location = "BASE4, Hennops"; $trip_name = "Trip Name Placeholder";
$short_description = getDetail($type); $location = "BASE4, Hennops";
$start_date = $from_date; // Default to booking start date $short_description = getDetail($type);
$end_date = $to_date; // Default to booking end date $start_date = $from_date; // Default to booking start date
} $end_date = $to_date; // Default to booking end date
} else { }
// Handle SQL execution error } else {
echo "Error retrieving trip information: " . $stmt_course->error; // Handle SQL execution error
} echo "Error retrieving trip information: " . $stmt_course->error;
}
// Close the statement
$stmt_course->close(); // Close the statement
} else { $stmt_course->close();
// Set default values if trip_id is null } else {
$trip_name = "BASE4 Camping"; // Set default values if trip_id is null
$location = "BASE4, Hennops"; $trip_name = "BASE4 Camping";
$short_description = "Please remember to bring 2 bags of firewood and drinking water for personal use."; $location = "BASE4, Hennops";
$start_date = $from_date; // Default to booking start date $short_description = "Please remember to bring 2 bags of firewood and drinking water for personal use.";
$end_date = $to_date; // Default to booking end date $start_date = $from_date; // Default to booking start date
} $end_date = $to_date; // Default to booking end date
}
// Get today's date
$today = date("Y-m-d"); // Get today's date
$today = date("Y-m-d");
// Determine if the date is past or future
if ($end_date < $today) { // Determine if the date is past or future
$tense = 'past'; if ($end_date < $today) {
} else { $tense = 'past';
$tense = 'future'; } else {
} $tense = 'future';
}
// Output the HTML structure with dynamic data
echo ' // Output the HTML structure with dynamic data
<div class="destination-item style-three bgc-lighter booking ' . $tense . '" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> echo '
<div class="image">'; <div class="destination-item style-three bgc-lighter booking ' . $tense . '" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
if ($booking_type === 'trip') { <div class="image">';
echo '<img src="assets/images/trips/' . $trip_id . '_01.jpg" alt="' . htmlspecialchars($trip_name) . '">'; if ($booking_type === 'trip') {
} elseif ($booking_type === 'course') { echo '<img src="assets/images/trips/' . $trip_id . '_01.jpg" alt="' . htmlspecialchars($trip_name) . '">';
echo '<img src="assets/images/courses/' . $type . '.png" alt="' . htmlspecialchars($trip_name) . '">'; } elseif ($booking_type === 'course') {
} else { echo '<img src="assets/images/courses/' . $type . '.png" alt="' . htmlspecialchars($trip_name) . '">';
echo '<img style="width:450px;" src="assets/images/base4/base4.jpg" alt="Base4">'; } else {
} echo '<img style="width:450px;" src="assets/images/base4/base4.jpg" alt="Base4">';
echo ' }
</div> echo '
<div class="content"> </div>
<div class="destination-header"> <div class="content">
<span class="location"><i class="fal fa-map-marker-alt"></i> ' . htmlspecialchars($location) . '</span> <div class="destination-header">
<span class="location"><i class="fal fa-map-marker-alt"></i> ' . htmlspecialchars($location) . '</span>
</div>
<h5>' . htmlspecialchars($trip_name) . '</a></h5> </div>
<p>' . htmlspecialchars($short_description) . '</p> <h5>' . htmlspecialchars($trip_name) . '</a></h5>
<ul class="blog-meta">'; <p>' . htmlspecialchars($short_description) . '</p>
if ($booking_type === 'course') { <ul class="blog-meta">';
echo '<li><i class="far fa-calendar"></i> ' . convertDate($start_date) . '</li>'; if ($booking_type === 'course') {
} else { echo '<li><i class="far fa-calendar"></i> ' . convertDate($start_date) . '</li>';
echo '<li><i class="far fa-calendar"></i> ' . convertDate($start_date) . ' - ' . convertDate($end_date) . '</li> } else {
<li><i class="far fa-clock"></i> ' . calculateDaysAndNights($start_date, $end_date) . '</li>'; echo '<li><i class="far fa-calendar"></i> ' . convertDate($start_date) . ' - ' . convertDate($end_date) . '</li>
} ?> <li><i class="far fa-clock"></i> ' . calculateDaysAndNights($start_date, $end_date) . '</li>';
<li><i class="far fa-user"></i> } ?>
<?php <li><i class="far fa-user"></i>
echo $num_vehicles . ' ' . ($num_vehicles > 1 ? 'vehicles' : 'vehicle') . ' ' . <?php
$total_adults . ' ' . ($total_adults > 1 ? 'adults' : 'adult'); echo $num_vehicles . ' ' . ($num_vehicles > 1 ? 'vehicles' : 'vehicle') . ' ' .
if ($num_children > 0) { $total_adults . ' ' . ($total_adults > 1 ? 'adults' : 'adult');
echo ' ' . $num_children . ' ' . ($num_children > 1 ? 'children' : 'child'); if ($num_children > 0) {
} echo ' ' . $num_children . ' ' . ($num_children > 1 ? 'children' : 'child');
?> }
</li> ?>
</li>
<?php echo '
</ul> <?php echo '
<div class="destination-footer"> </ul>
<span class="price"><span>Booking Total: R ' . number_format($amount, 2) . '</span></span>'; <div class="destination-footer">
if ($status == "AWAITING PAYMENT") { <span class="price"><span>Booking Total: R ' . number_format($amount, 2) . '</span></span>';
echo '<a href="payment_confirmation.php?token=' . encryptData($booking_id, $salt) . '" class="theme-btn style-two style-three"> if ($status == "AWAITING PAYMENT") {
<span data-hover="PAYMENT INFO">' . $status . '</span> echo '<a href="' . url('payment_confirmation') . '?token=' . encryptData($booking_id, $salt) . '" class="theme-btn style-two style-three">
</a>'; <span data-hover="PAYMENT INFO">' . $status . '</span>
} else { </a>';
echo '<a href="" class="theme-btn style-two style-three"> } else {
<span data-hover="' . $status . '">' . $status . '</span> echo '<a href="" class="theme-btn style-two style-three">
</a>'; <span data-hover="' . $status . '">' . $status . '</span>
} </a>';
echo ' }
echo '
</div>
</div> </div>
</div>'; </div>
} </div>';
} else { }
echo '<p>You have no upcoming bookings.</p>'; } else {
} echo '<p>You have no upcoming bookings.</p>';
}
// Close connection
$conn->close(); // Close connection
?> $conn->close();
?>
</div>
</div> </div>
</div> </div>
</section> </div>
<!-- Tour List Area end --> </section>
<script> <!-- Tour List Area end -->
function togglePastBookings() { <script>
// Get the checkbox element function togglePastBookings() {
const checkbox = document.getElementById('togglePastBookings'); // Get the checkbox element
const checkbox = document.getElementById('togglePastBookings');
// Select all elements with the class 'past'
const pastBookings = document.querySelectorAll('.booking.past'); // Select all elements with the class 'past'
const pastBookings = document.querySelectorAll('.booking.past');
// Show or hide past bookings based on the checkbox state
pastBookings.forEach(booking => { // Show or hide past bookings based on the checkbox state
booking.style.display = checkbox.checked ? '' : 'none'; pastBookings.forEach(booking => {
}); booking.style.display = checkbox.checked ? '' : 'none';
} });
// Run the function on page load }
document.addEventListener('DOMContentLoaded', () => { // Run the function on page load
// Set the initial state of the checkbox if needed document.addEventListener('DOMContentLoaded', () => {
const checkbox = document.getElementById('togglePastBookings'); // Set the initial state of the checkbox if needed
checkbox.checked = false; // Optional: Start with checkbox unchecked const checkbox = document.getElementById('togglePastBookings');
checkbox.checked = false; // Optional: Start with checkbox unchecked
// Call the function to set the initial state of past bookings
togglePastBookings(); // Call the function to set the initial state of past bookings
}); togglePastBookings();
</script> });
</script>
<?php include_once("insta_footer.php"); ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,217 +1,217 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); include_once(dirname(dirname(dirname(__DIR__))) . '/header.php');
checkUserSession(); checkUserSession();
?> ?>
<!-- Gallery Area start --> <!-- Gallery Area start -->
<section class="gallery-slider-area pt-100 rel z-1"> <section class="gallery-slider-area pt-100 rel z-1">
<div class="gallery-slider-active"> <div class="gallery-slider-active">
<div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="image"> <div class="image">
<img src="assets/images/gallery/gallery-slider1.jpg" alt="Gallery"> <img src="assets/images/gallery/gallery-slider1.jpg" alt="Gallery">
</div> </div>
<div class="content"> <div class="content">
<span class="category">Tour & Travel</span> <span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Brown Concrete Building</a></h5> <h5><a href="destination-details.html">Brown Concrete Building</a></h5>
</div> </div>
</div> </div>
<div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="image"> <div class="image">
<img src="assets/images/gallery/gallery-slider2.jpg" alt="Gallery"> <img src="assets/images/gallery/gallery-slider2.jpg" alt="Gallery">
</div> </div>
<div class="content"> <div class="content">
<span class="category">Tour & Travel</span> <span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Brown Concrete Building</a></h5> <h5><a href="destination-details.html">Brown Concrete Building</a></h5>
</div> </div>
</div> </div>
<div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="image"> <div class="image">
<img src="assets/images/gallery/gallery-slider3.jpg" alt="Gallery"> <img src="assets/images/gallery/gallery-slider3.jpg" alt="Gallery">
</div> </div>
<div class="content"> <div class="content">
<span class="category">Tour & Travel</span> <span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Brown Concrete Building</a></h5> <h5><a href="destination-details.html">Brown Concrete Building</a></h5>
</div> </div>
</div> </div>
<div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="image"> <div class="image">
<img src="assets/images/gallery/gallery-slider4.jpg" alt="Gallery"> <img src="assets/images/gallery/gallery-slider4.jpg" alt="Gallery">
</div> </div>
<div class="content"> <div class="content">
<span class="category">Tour & Travel</span> <span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Brown Concrete Building</a></h5> <h5><a href="destination-details.html">Brown Concrete Building</a></h5>
</div> </div>
</div> </div>
<div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="gallery-three-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="image"> <div class="image">
<img src="assets/images/gallery/gallery-slider5.jpg" alt="Gallery"> <img src="assets/images/gallery/gallery-slider5.jpg" alt="Gallery">
</div> </div>
<div class="content"> <div class="content">
<span class="category">Tour & Travel</span> <span class="category">Tour & Travel</span>
<h5><a href="destination-details.html">Brown Concrete Building</a></h5> <h5><a href="destination-details.html">Brown Concrete Building</a></h5>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Gallery Area end --> <!-- Gallery Area end -->
<!-- About Us Area start --> <!-- About Us Area start -->
<section class="about-us-area pt-90 pb-100 rel z-1"> <section class="about-us-area pt-90 pb-100 rel z-1">
<div class="container"> <div class="container">
<div class="row gap-100 align-items-center"> <div class="row gap-100 align-items-center">
<div class="col-lg-6"> <div class="col-lg-6">
<div class="destination-details-content rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <div class="destination-details-content rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="section-title mb-25"> <div class="section-title mb-25">
<span class="h2 mb-15">Welcome to </span> <span class="h2 mb-15">Welcome to </span>
<h2>BASE4 Camping</h2> <h2>BASE4 Camping</h2>
</div> </div>
<p>Escape to the ultimate outdoor adventure at BASE4, nestled right next to a tranquil stream. Enjoy the perfect blend of rugged exploration and relaxation with top-notch facilities, including braai areas, hot showers, and clean ablution blocks. Gather with friends under our spacious lapa or take a dip in the refreshing swimming pool after a day of off-road fun. Whether you're conquering trails or kicking back by the fire, our campsite offers the ideal setting for an unforgettable getaway. Book your spot today and experience nature at its finest!</p> <p>Escape to the ultimate outdoor adventure at BASE4, nestled right next to a tranquil stream. Enjoy the perfect blend of rugged exploration and relaxation with top-notch facilities, including braai areas, hot showers, and clean ablution blocks. Gather with friends under our spacious lapa or take a dip in the refreshing swimming pool after a day of off-road fun. Whether you're conquering trails or kicking back by the fire, our campsite offers the ideal setting for an unforgettable getaway. Book your spot today and experience nature at its finest!</p>
</div> </div>
<div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5 class="widget-title">Book your Campsite</h5> <h5 class="widget-title">Book your Campsite</h5>
<form action="process_camp_booking.php" method="POST"> <form action="process_camp_booking" method="POST">
<div class="date mb-25"> <div class="date mb-25">
<b>From Date</b> <b>From Date</b>
<input type="date" id="from_date" name="from_date"> <input type="date" id="from_date" name="from_date">
</div> </div>
<div class="date mb-25"> <div class="date mb-25">
<b>To Date</b> <b>To Date</b>
<input type="date" id="to_date" name="to_date"> <input type="date" id="to_date" name="to_date">
</div> </div>
<hr class="mb-25"> <hr class="mb-25">
<ul class="tickets clearfix"> <ul class="tickets clearfix">
<li> <li>
No. of Vehicles No. of Vehicles
<input style="border-color: #d7d7d7;width:auto;padding:10px;" type="number" id="vehicles" name="vehicles" value="1" min="1"> <input style="border-color: #d7d7d7;width:auto;padding:10px;" type="number" id="vehicles" name="vehicles" value="1" min="1">
</li> </li>
<li> <li>
No. of Adults No. of Adults
<input style="border-color: #d7d7d7;width:auto;padding:10px;" type="number" id="adults" name="adults" value="1" min="1"> <input style="border-color: #d7d7d7;width:auto;padding:10px;" type="number" id="adults" name="adults" value="1" min="1">
</li> </li>
<li> <li>
No. of Children No. of Children
<input style="border-color: #d7d7d7;width:auto;padding:10px;" type="number" id="children" name="children" value="0" min="0"> <input style="border-color: #d7d7d7;width:auto;padding:10px;" type="number" id="children" name="children" value="0" min="0">
</li> </li>
</ul> </ul>
<hr class="mb-25"> <hr class="mb-25">
<h6>Add Extra:</h6> <h6>Add Extra:</h6>
<ul class="radio-filter pt-5"> <ul class="radio-filter pt-5">
<li> <li>
<input class="form-check-input" type="checkbox" name="AddExtra" id="add-extra1" value="50"> <input class="form-check-input" type="checkbox" name="AddExtra" id="add-extra1" value="50">
<label for="add-extra1">2 x 5kg Firewood <span>R 50,00</span></label> <label for="add-extra1">2 x 5kg Firewood <span>R 50,00</span></label>
</li> </li>
</ul> </ul>
<hr> <hr>
<?php if ($is_member) : ?> <?php if ($is_member) : ?>
<div id="discount_section"> <div id="discount_section">
<h6>Discount:</h6> <h6>Discount:</h6>
<ul class="radio-filter pt-5"> <ul class="radio-filter pt-5">
<li> <li>
<label for="add-extra1">4WDCSA Member Discount <span id="discount_amount">R 0,00</span></label> <label for="add-extra1">4WDCSA Member Discount <span id="discount_amount">R 0,00</span></label>
</li> </li>
</ul> </ul>
<hr> <hr>
</div> </div>
<?php endif ?> <?php endif ?>
<h6>Total: <span id="booking_total" class="price">-</span></h6> <h6>Total: <span id="booking_total" class="price">-</span></h6>
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<button type="submit" class="theme-btn style-two w-100 mt-15 mb-5"> <button type="submit" class="theme-btn style-two w-100 mt-15 mb-5">
<span data-hover="Book Now">Book Now</span> <span data-hover="Book Now">Book Now</span>
<i class="fal fa-arrow-right"></i> <i class="fal fa-arrow-right"></i>
</button> </button>
<div class="text-center"> <div class="text-center">
<a href="contact.html">Need some help?</a> | Payments will be redirected to Payfast. <a href="contact.html">Need some help?</a> | Payments will be redirected to Payfast.
</div> </div>
</form> </form>
</div> </div>
</div> </div>
<div class="col-lg-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<div class="destination-map"> <div class="destination-map">
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d667.578212275918!2d28.000752737032542!3d-25.864032288240537!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x1e95794b858a5427%3A0xcdb0a4b0055a9753!2sFour%20Wheel%20Drive%20Club%20of%20Southern%20Africa%20-FWDCSA%20GAUTENG%20-%20BASE%204!5e1!3m2!1sen!2sza!4v1726669599601!5m2!1sen!2sza" width="100%" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe> <iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d667.578212275918!2d28.000752737032542!3d-25.864032288240537!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x1e95794b858a5427%3A0xcdb0a4b0055a9753!2sFour%20Wheel%20Drive%20Club%20of%20Southern%20Africa%20-FWDCSA%20GAUTENG%20-%20BASE%204!5e1!3m2!1sen!2sza!4v1726669599601!5m2!1sen!2sza" width="100%" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- About Us Area end --> <!-- About Us Area end -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
// Function to calculate booking total // Function to calculate booking total
function calculateTotal() { function calculateTotal() {
var fromDate = new Date($('#from_date').val()); var fromDate = new Date($('#from_date').val());
var toDate = new Date($('#to_date').val()); var toDate = new Date($('#to_date').val());
var vehicles = parseInt($('#vehicles').val()) || 1; var vehicles = parseInt($('#vehicles').val()) || 1;
var firewoodCost = $('#add-extra1').is(':checked') ? 50 : 0; var firewoodCost = $('#add-extra1').is(':checked') ? 50 : 0;
var isMember = <?php echo $is_member ? 'true' : 'false'; ?>; var isMember = <?php echo $is_member ? 'true' : 'false'; ?>;
var perNightRate = 200; var perNightRate = 200;
if (isMember) { if (isMember) {
perNightRate = 0; // 100% discount perNightRate = 0; // 100% discount
} }
// Calculate nights // Calculate nights
var timeDifference = toDate.getTime() - fromDate.getTime(); var timeDifference = toDate.getTime() - fromDate.getTime();
var nights = Math.ceil(timeDifference / (1000 * 3600 * 24)); var nights = Math.ceil(timeDifference / (1000 * 3600 * 24));
if (nights < 1) { if (nights < 1) {
nights = 0; // If "To Date" is before "From Date", no charge nights = 0; // If "To Date" is before "From Date", no charge
} }
// Calculate total // Calculate total
var total = (nights * perNightRate * vehicles) + firewoodCost; var total = (nights * perNightRate * vehicles) + firewoodCost;
// Update total in the DOM // Update total in the DOM
$('#booking_total').text('R ' + total.toFixed(2)); $('#booking_total').text('R ' + total.toFixed(2));
// Update discount section // Update discount section
if (isMember) { if (isMember) {
var discountAmount = nights * 200 * vehicles; // Original rate * nights * vehicles var discountAmount = nights * 200 * vehicles; // Original rate * nights * vehicles
$('#discount_amount').text('R ' + discountAmount.toFixed(2)); $('#discount_amount').text('R ' + discountAmount.toFixed(2));
} }
} }
// Function to restrict date selection // Function to restrict date selection
function restrictDates() { function restrictDates() {
var today = new Date().toISOString().split('T')[0]; // Get today's date in YYYY-MM-DD format var today = new Date().toISOString().split('T')[0]; // Get today's date in YYYY-MM-DD format
$('#from_date').attr('min', today); // Set min for from_date $('#from_date').attr('min', today); // Set min for from_date
var fromDate = $('#from_date').val(); var fromDate = $('#from_date').val();
if (fromDate) { if (fromDate) {
$('#to_date').attr('min', fromDate); // Set min for to_date based on from_date $('#to_date').attr('min', fromDate); // Set min for to_date based on from_date
} else { } else {
$('#to_date').attr('min', today); // Default to today's date if no from_date is set $('#to_date').attr('min', today); // Default to today's date if no from_date is set
} }
} }
// Event listeners to trigger recalculation and date restriction // Event listeners to trigger recalculation and date restriction
$('#from_date').on('change', function() { $('#from_date').on('change', function() {
restrictDates(); restrictDates();
calculateTotal(); calculateTotal();
}); });
$('#to_date, #vehicles, #add-extra1').on('change', function() { $('#to_date, #vehicles, #add-extra1').on('change', function() {
calculateTotal(); calculateTotal();
}); });
// Initial setup for date restrictions and calculation // Initial setup for date restrictions and calculation
restrictDates(); restrictDates();
calculateTotal(); calculateTotal();
}); });
</script> </script>
<?php include_once('insta_footer.php') ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php') ?>

View File

@@ -1,194 +1,195 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
include_once($rootPath . '/header.php');
$conn = openDatabaseConnection();
$stmt = $conn->prepare("SELECT * FROM campsites"); $conn = openDatabaseConnection();
$stmt->execute(); $stmt = $conn->prepare("SELECT * FROM campsites");
$result = $stmt->get_result(); $stmt->execute();
$campsites = []; $result = $stmt->get_result();
while ($row = $result->fetch_assoc()) { $campsites = [];
$campsites[] = $row; while ($row = $result->fetch_assoc()) {
} $campsites[] = $row;
?> }
?>
<style>
#map { <style>
height: 600px; #map {
width: 100%; height: 600px;
} width: 100%;
}
.gm-style .info-box {
max-width: 250px; .gm-style .info-box {
} max-width: 250px;
}
.info-box img {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); .info-box img {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
</style>
</style>
<?php
$pageTitle = 'Campsites'; <?php
$breadcrumbs = [['Home' => 'index.php']]; $pageTitle = 'Campsites';
require_once('components/banner.php'); $breadcrumbs = [['Home' => 'index.php']];
?> require_once($rootPath . '/components/banner.php');
?>
<!-- Tour List Area start -->
<section class="tour-list-page py-100 rel z-1"> <!-- Tour List Area start -->
<div class="container"> <section class="tour-list-page py-100 rel z-1">
<div class="row"> <div class="container">
<div class="col-lg-12"> <div class="row">
<div class="col-lg-12">
<div id="map" style="width: 100%; height: 500px;"></div>
<!-- Add Campsite Modal --> <div id="map" style="width: 100%; height: 500px;"></div>
<!-- Add Campsite Modal -->
</div>
</div> </div>
</div> </div>
</section> </div>
<div class="modal fade" id="addCampsiteModal" tabindex="-1"> </section>
<div class="modal-dialog"> <div class="modal fade" id="addCampsiteModal" tabindex="-1">
<form id="addCampsiteForm" method="POST" action="add_campsite.php" enctype="multipart/form-data"> <div class="modal-dialog">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <form id="addCampsiteForm" method="POST" action="add_campsite" enctype="multipart/form-data">
<div class="modal-content"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<div class="modal-header"> <div class="modal-content">
<h5 class="modal-title">Add Campsite</h5> <div class="modal-header">
<button type="button" class="btn-close" data-bs-dismiss="modal"></button> <h5 class="modal-title">Add Campsite</h5>
</div> <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
<div class="modal-body"> </div>
<input type="hidden" name="latitude" id="latitude"> <div class="modal-body">
<input type="hidden" name="longitude" id="longitude"> <input type="hidden" name="latitude" id="latitude">
<div class="mb-3"> <input type="hidden" name="longitude" id="longitude">
<label class="form-label">Campsite Name</label> <div class="mb-3">
<input type="text" class="form-control" name="name" required> <label class="form-label">Campsite Name</label>
</div> <input type="text" class="form-control" name="name" required>
<div class="mb-3"> </div>
<label class="form-label">Description</label> <div class="mb-3">
<textarea class="form-control" name="description" rows="3"></textarea> <label class="form-label">Description</label>
</div> <textarea class="form-control" name="description" rows="3"></textarea>
<div class="mb-3"> </div>
<label class="form-label">Booking URL</label> <div class="mb-3">
<input type="url" class="form-control" name="website"> <label class="form-label">Booking URL</label>
</div> <input type="url" class="form-control" name="website">
<div class="mb-3"> </div>
<label class="form-label">Phone Number</label> <div class="mb-3">
<input type="text" class="form-control" name="telephone"> <label class="form-label">Phone Number</label>
</div> <input type="text" class="form-control" name="telephone">
<div class="mb-3"> </div>
<label class="form-label">Thumbnail Image</label> <div class="mb-3">
<input type="file" class="form-control" name="thumbnail" accept="image/*"> <label class="form-label">Thumbnail Image</label>
</div> <input type="file" class="form-control" name="thumbnail" accept="image/*">
</div> </div>
<div class="modal-footer"> </div>
<button class="btn btn-primary" type="submit">Save Campsite</button> <div class="modal-footer">
<button class="btn btn-secondary" type="button" data-bs-dismiss="modal">Cancel</button> <button class="btn btn-primary" type="submit">Save Campsite</button>
</div> <button class="btn btn-secondary" type="button" data-bs-dismiss="modal">Cancel</button>
</div> </div>
</form> </div>
</form>
</div>
</div> </div>
<script> </div>
let map; <script>
const campsites = <?php echo json_encode($campsites); ?>; let map;
const campsites = <?php echo json_encode($campsites); ?>;
function initMap() {
map = new google.maps.Map(document.getElementById("map"), { function initMap() {
center: { map = new google.maps.Map(document.getElementById("map"), {
lat: -28.0, center: {
lng: 24.0 lat: -28.0,
}, // SA center lng: 24.0
zoom: 6, }, // SA center
}); zoom: 6,
});
map.addListener("click", function(e) {
const lat = e.latLng.lat(); map.addListener("click", function(e) {
const lng = e.latLng.lng(); const lat = e.latLng.lat();
const lng = e.latLng.lng();
document.getElementById("latitude").value = lat;
document.getElementById("longitude").value = lng; document.getElementById("latitude").value = lat;
document.getElementById("longitude").value = lng;
const addModal = new bootstrap.Modal(document.getElementById("addCampsiteModal"));
addModal.show(); const addModal = new bootstrap.Modal(document.getElementById("addCampsiteModal"));
}); addModal.show();
});
// Load existing campsites from PHP
fetch("get_campsites.php") // Load existing campsites from PHP
.then(response => response.json()) fetch("get_campsites.php")
.then(data => { .then(response => response.json())
data.forEach(site => { .then(data => {
const marker = new google.maps.Marker({ data.forEach(site => {
position: { const marker = new google.maps.Marker({
lat: parseFloat(site.latitude), position: {
lng: parseFloat(site.longitude) lat: parseFloat(site.latitude),
}, lng: parseFloat(site.longitude)
map, },
title: site.name, map,
}); title: site.name,
});
const content = `
<div class="info-box"> const content = `
<strong>${site.name}</strong><br> <div class="info-box">
${site.description ? site.description + "<br>" : ""} <strong>${site.name}</strong><br>
${site.website ? `<a href="${site.website}" target="_blank">Visit Website</a><br>` : ""} ${site.description ? site.description + "<br>" : ""}
${site.telephone ? `Phone: ${site.telephone}<br>` : ""} ${site.website ? `<a href="${site.website}" target="_blank">Visit Website</a><br>` : ""}
${site.thumbnail ? `<img src="${site.thumbnail}" style="width: 100%; max-width: 200px; border-radius: 8px; margin-top: 5px;">` : ""} ${site.telephone ? `Phone: ${site.telephone}<br>` : ""}
${site.user && site.user.first_name ? ` ${site.thumbnail ? `<img src="${site.thumbnail}" style="width: 100%; max-width: 200px; border-radius: 8px; margin-top: 5px;">` : ""}
<div class="user-info mt-2 d-flex align-items-center"> ${site.user && site.user.first_name ? `
<img src="${site.user.profile_pic}" style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover; margin-right: 10px;"> <div class="user-info mt-2 d-flex align-items-center">
<div> <img src="${site.user.profile_pic}" style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover; margin-right: 10px;">
<small>Added by:</small><br> <div>
<strong>${site.user.first_name} ${site.user.last_name}</strong> <small>Added by:</small><br>
</div> <strong>${site.user.first_name} ${site.user.last_name}</strong>
</div>` : ""} </div>
<br> </div>` : ""}
<button class="btn btn-sm btn-warning mt-2" onclick='editCampsite(${JSON.stringify(site)})'>Edit</button> <br>
<a href="https://www.google.com/maps/dir/?api=1&destination=${site.latitude},${site.longitude}" target="_blank" class="btn btn-sm btn-outline-primary mt-2 ms-2">Get Directions</a> <button class="btn btn-sm btn-warning mt-2" onclick='editCampsite(${JSON.stringify(site)})'>Edit</button>
</div> <a href="https://www.google.com/maps/dir/?api=1&destination=${site.latitude},${site.longitude}" target="_blank" class="btn btn-sm btn-outline-primary mt-2 ms-2">Get Directions</a>
`; </div>
`;
const infowindow = new google.maps.InfoWindow({
content: content const infowindow = new google.maps.InfoWindow({
}); content: content
});
marker.addListener("click", () => {
infowindow.open(map, marker); marker.addListener("click", () => {
}); infowindow.open(map, marker);
}); });
}) });
.catch(err => console.error("Failed to load campsites:", err)); })
} .catch(err => console.error("Failed to load campsites:", err));
}
function editCampsite(site) {
// Pre-fill form function editCampsite(site) {
document.querySelector("#addCampsiteForm input[name='name']").value = site.name; // Pre-fill form
document.querySelector("#addCampsiteForm textarea[name='description']").value = site.description || ""; document.querySelector("#addCampsiteForm input[name='name']").value = site.name;
document.querySelector("#addCampsiteForm input[name='website']").value = site.website || ""; document.querySelector("#addCampsiteForm textarea[name='description']").value = site.description || "";
document.querySelector("#addCampsiteForm input[name='telephone']").value = site.telephone || ""; document.querySelector("#addCampsiteForm input[name='website']").value = site.website || "";
document.querySelector("#addCampsiteForm input[name='latitude']").value = site.latitude; document.querySelector("#addCampsiteForm input[name='telephone']").value = site.telephone || "";
document.querySelector("#addCampsiteForm input[name='longitude']").value = site.longitude; document.querySelector("#addCampsiteForm input[name='latitude']").value = site.latitude;
document.querySelector("#addCampsiteForm input[name='longitude']").value = site.longitude;
// Add hidden ID input
let idInput = document.querySelector("#addCampsiteForm input[name='id']"); // Add hidden ID input
if (!idInput) { let idInput = document.querySelector("#addCampsiteForm input[name='id']");
idInput = document.createElement("input"); if (!idInput) {
idInput.type = "hidden"; idInput = document.createElement("input");
idInput.name = "id"; idInput.type = "hidden";
document.querySelector("#addCampsiteForm").appendChild(idInput); idInput.name = "id";
} document.querySelector("#addCampsiteForm").appendChild(idInput);
idInput.value = site.id; }
idInput.value = site.id;
// Show the modal
const addModal = new bootstrap.Modal(document.getElementById("addCampsiteModal")); // Show the modal
addModal.show(); const addModal = new bootstrap.Modal(document.getElementById("addCampsiteModal"));
} addModal.show();
</script> }
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC-JuvnbUYc8WGjQBFFVZtKiv5_bFJoWLU&callback=initMap" async defer></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC-JuvnbUYc8WGjQBFFVZtKiv5_bFJoWLU&callback=initMap" async defer></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<?php include_once("insta_footer.php"); ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,302 +1,303 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
include_once($rootPath . '/header.php');
// SQL query to fetch dates for driver training
$stmt = $conn->prepare("SELECT course_id, date FROM courses WHERE course_type = ?"); // SQL query to fetch dates for driver training
$course_type = 'driver_training'; $stmt = $conn->prepare("SELECT course_id, date FROM courses WHERE course_type = ?");
$stmt->bind_param("s", $course_type); $course_type = 'driver_training';
$stmt->execute(); $stmt->bind_param("s", $course_type);
$result = $stmt->get_result(); $stmt->execute();
?> $result = $stmt->get_result();
?>
<?php
$pageTitle = 'Course Details'; <?php
$breadcrumbs = [['Home' => 'index.php']]; $pageTitle = 'Course Details';
require_once('components/banner.php'); $breadcrumbs = [['Home' => 'index.php']];
?> require_once($rootPath . '/components/banner.php');
<!-- Page Banner End --> ?>
<!-- Page Banner End -->
<!-- Product Details Start -->
<section class="product-details pt-100"> <!-- Product Details Start -->
<div class="container"> <section class="product-details pt-100">
<div class="row"> <div class="container">
<div class="col-lg-6"> <div class="row">
<div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6">
<div class="tab-content preview-images"> <div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="tab-pane fade preview-item active show" id="preview1"> <div class="tab-content preview-images">
<img src="assets/images/shop/preview1.png" alt="Perview"> <div class="tab-pane fade preview-item active show" id="preview1">
</div> <img src="assets/images/shop/preview1.png" alt="Perview">
<div class="tab-pane fade preview-item" id="preview2"> </div>
<img src="assets/images/shop/preview1.png" alt="Perview"> <div class="tab-pane fade preview-item" id="preview2">
</div> <img src="assets/images/shop/preview1.png" alt="Perview">
<div class="tab-pane fade preview-item" id="preview3"> </div>
<img src="assets/images/shop/preview1.png" alt="Perview"> <div class="tab-pane fade preview-item" id="preview3">
</div> <img src="assets/images/shop/preview1.png" alt="Perview">
</div> </div>
<div class="nav thumb-images rmb-20"> </div>
<a href="#preview1" data-bs-toggle="tab" class="thumb-item active show"> <div class="nav thumb-images rmb-20">
<img src="assets/images/shop/thumb1.png" alt="Thumb"> <a href="#preview1" data-bs-toggle="tab" class="thumb-item active show">
</a> <img src="assets/images/shop/thumb1.png" alt="Thumb">
<a href="#preview2" data-bs-toggle="tab" class="thumb-item"> </a>
<img src="assets/images/shop/thumb2.png" alt="Thumb"> <a href="#preview2" data-bs-toggle="tab" class="thumb-item">
</a> <img src="assets/images/shop/thumb2.png" alt="Thumb">
<a href="#preview3" data-bs-toggle="tab" class="thumb-item"> </a>
<img src="assets/images/shop/thumb3.png" alt="Thumb"> <a href="#preview3" data-bs-toggle="tab" class="thumb-item">
</a> <img src="assets/images/shop/thumb3.png" alt="Thumb">
</div> </a>
</div> </div>
</div> </div>
<div class="col-lg-6"> </div>
<div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6">
<div class="section-title"> <div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<h2>4X4 Driver Training</h2> <div class="section-title">
</div> <h2>4X4 Driver Training</h2>
<!-- <div class="ratting mb-15"> </div>
<i class="fas fa-star"></i> <!-- <div class="ratting mb-15">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
<span>(5.8k+ reviews)</span> <i class="fas fa-star-half-alt"></i>
</div> --> <span>(5.8k+ reviews)</span>
<span class="price mb-5">R 50,00/member</span> </div> -->
<span class="price mb-25">R 750,00/non-members</span> <span class="price mb-5">R 50,00/member</span>
<p>Our 4x4 Basic Training Course equips you with the essential skills and knowledge to confidently tackle off-road terrains. Learn vehicle mechanics, driving techniques, obstacle navigation, and recovery methods while promoting safe and responsible off-road practices. Perfect for beginners and new 4x4 owners!</p> <span class="price mb-25">R 750,00/non-members</span>
<hr class="mt-40"> <p>Our 4x4 Basic Training Course equips you with the essential skills and knowledge to confidently tackle off-road terrains. Learn vehicle mechanics, driving techniques, obstacle navigation, and recovery methods while promoting safe and responsible off-road practices. Perfect for beginners and new 4x4 owners!</p>
<form action="#" class="add-to-cart pt-15 pb-30"> <hr class="mt-40">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <form action="#" class="add-to-cart pt-15 pb-30">
<label for="course_date">Select a Date:</label> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<select name="course_date" id="course_date" required> <label for="course_date">Select a Date:</label>
<!-- <option value="" disabled selected>-- Select a Date --</option> --> <select name="course_date" id="course_date" required>
<?php <!-- <option value="" disabled selected>-- Select a Date --</option> -->
if ($result->num_rows > 0) { <?php
// Output each course as an option if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { // Output each course as an option
$course_id = htmlspecialchars($row['course_id']); // Escape output for security while ($row = $result->fetch_assoc()) {
$date = htmlspecialchars($row['date']); // Escape output for security $course_id = htmlspecialchars($row['course_id']); // Escape output for security
echo "<option value='$course_id'>$date</option>"; $date = htmlspecialchars($row['date']); // Escape output for security
} echo "<option value='$course_id'>$date</option>";
} else { }
echo "<option value='' disabled>No dates available</option>"; } else {
} echo "<option value='' disabled>No dates available</option>";
?> }
</select> ?>
<button type="submit" class="theme-btn style-two bgc-secondary"> </select>
<span data-hover="Add to Cart">Book Now</span> <button type="submit" class="theme-btn style-two bgc-secondary">
<i class="far fa-arrow-right"></i> <span data-hover="Add to Cart">Book Now</span>
</button> <i class="far fa-arrow-right"></i>
</form> </button>
<hr class="mb-45"> </form>
<a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a> <hr class="mb-45">
</div> <a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a>
</div> </div>
</div> </div>
<ul class="nav nav product-tab mt-70 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div>
<li><a href="#details" data-bs-toggle="tab" class="active show">Course Overview<i class="far fa-arrow-right"></i></a></li> <ul class="nav nav product-tab mt-70 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<li><a href="#information" data-bs-toggle="tab">What to Expect<i class="far fa-arrow-right"></i></a></li> <li><a href="#details" data-bs-toggle="tab" class="active show">Course Overview<i class="far fa-arrow-right"></i></a></li>
<!-- <li><a href="#reviews" data-bs-toggle="tab"> Reviews <i class="far fa-arrow-right"></i></a></li> --> <li><a href="#information" data-bs-toggle="tab">What to Expect<i class="far fa-arrow-right"></i></a></li>
</ul> <!-- <li><a href="#reviews" data-bs-toggle="tab"> Reviews <i class="far fa-arrow-right"></i></a></li> -->
<div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50"> </ul>
<div class="tab-pane fade active show" id="details"> <div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
<p>A 4x4 Basic Training Course is designed to equip participants with the foundational knowledge and practical skills necessary for safe and effective off-road driving. This course covers essential topics such as understanding the mechanics of 4x4 vehicles, selecting the appropriate gear, and engaging various drive modes to tackle different terrains. Participants will learn how to navigate obstacles like mud, sand, and rocky paths while maintaining vehicle control and ensuring safety for themselves and their passengers. The training also includes instruction on tire pressure management, vehicle recovery techniques, and the use of essential recovery equipment like tow straps and shackles.</p> <div class="tab-pane fade active show" id="details">
<p>In addition to practical driving exercises, the course emphasizes responsible off-road driving practices, including respecting the environment and adhering to trail etiquette. Whether you're a novice driver looking to explore off-road adventures or a new 4x4 owner seeking confidence behind the wheel, this training provides a comprehensive introduction to the world of off-roading. By the end of the course, participants will feel prepared to tackle basic off-road challenges with skill and assurance, making their next 4x4 outing a safe and enjoyable experience.</p> <p>A 4x4 Basic Training Course is designed to equip participants with the foundational knowledge and practical skills necessary for safe and effective off-road driving. This course covers essential topics such as understanding the mechanics of 4x4 vehicles, selecting the appropriate gear, and engaging various drive modes to tackle different terrains. Participants will learn how to navigate obstacles like mud, sand, and rocky paths while maintaining vehicle control and ensuring safety for themselves and their passengers. The training also includes instruction on tire pressure management, vehicle recovery techniques, and the use of essential recovery equipment like tow straps and shackles.</p>
<div class="row gap-50 pt-25 pb-20 align-items-center"> <p>In addition to practical driving exercises, the course emphasizes responsible off-road driving practices, including respecting the environment and adhering to trail etiquette. Whether you're a novice driver looking to explore off-road adventures or a new 4x4 owner seeking confidence behind the wheel, this training provides a comprehensive introduction to the world of off-roading. By the end of the course, participants will feel prepared to tackle basic off-road challenges with skill and assurance, making their next 4x4 outing a safe and enjoyable experience.</p>
<div class="col-lg-7 pt-15"> <div class="row gap-50 pt-25 pb-20 align-items-center">
<h5>What this course includes</h5> <div class="col-lg-7 pt-15">
<ul class="list-style-two mt-25"> <h5>What this course includes</h5>
<li>Basic Driver Training Manual.</li> <ul class="list-style-two mt-25">
<li>Theory session and discussion.</li> <li>Basic Driver Training Manual.</li>
<li>Spend the afternoon on the track learning the basic practices of 4X4 driving.</li> <li>Theory session and discussion.</li>
</ul> <li>Spend the afternoon on the track learning the basic practices of 4X4 driving.</li>
</div> </ul>
<div class="col-lg-5"> </div>
<div class="image rmt-45"> <div class="col-lg-5">
<img src="assets/images/shop/product-details.jpg" alt="Product Details"> <div class="image rmt-45">
</div> <img src="assets/images/shop/product-details.jpg" alt="Product Details">
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="information"> </div>
<!-- <p>Circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses</p> --> <div class="tab-pane fade" id="information">
<ul class="list-style-two my-35"> <!-- <p>Circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses</p> -->
<li>Coffee and Welcome: Start the day with a warm cup of coffee, meet the instructors, and get an overview of the training schedule.</li> <ul class="list-style-two my-35">
<li>Theory Session: Learn the fundamentals of 4x4 vehicle mechanics, terrain types, recovery equipment, and off-road safety.</li> <li>Coffee and Welcome: Start the day with a warm cup of coffee, meet the instructors, and get an overview of the training schedule.</li>
<li>Practical Demonstrations: Observe demonstrations of essential techniques like gear selection, tire pressure adjustment, and recovery setups.</li> <li>Theory Session: Learn the fundamentals of 4x4 vehicle mechanics, terrain types, recovery equipment, and off-road safety.</li>
<li>Lunch Break: Bring along a packed lunch or something to braai. Fires will be provided.</li> <li>Practical Demonstrations: Observe demonstrations of essential techniques like gear selection, tire pressure adjustment, and recovery setups.</li>
<li>Track Driving and Practical Training: Put theory into action with hands-on driving exercises on a custom-designed off-road track.</li> <li>Lunch Break: Bring along a packed lunch or something to braai. Fires will be provided.</li>
<li>Debrief and Certificates: Wrap up the day with a recap of key lessons, feedback from instructors, and certificates of completion.</li> <li>Track Driving and Practical Training: Put theory into action with hands-on driving exercises on a custom-designed off-road track.</li>
</ul> <li>Debrief and Certificates: Wrap up the day with a recap of key lessons, feedback from instructors, and certificates of completion.</li>
</div> </ul>
<!-- <div class="tab-pane fade mb-20" id="reviews"> </div>
<h5>2 Reviews</h5> <!-- <div class="tab-pane fade mb-20" id="reviews">
<div class="comments my-30"> <h5>2 Reviews</h5>
<div class="comment-body" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="comments my-30">
<div class="author-thumb"> <div class="comment-body" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/blog/comment-author1.jpg" alt="Author"> <div class="author-thumb">
</div> <img src="assets/images/blog/comment-author1.jpg" alt="Author">
<div class="content"> </div>
<h6>Lonnie B. Horwitz</h6> <div class="content">
<div class="ratting"> <h6>Lonnie B. Horwitz</h6>
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<span class="time">Venice, Rome and Milan 9 Days 8 Nights</span> </div>
<p>Tours and travels play a crucial role in enriching lives by offering unique experiences, cultural exchanges, and the joy of exploration.</p> <span class="time">Venice, Rome and Milan 9 Days 8 Nights</span>
<a class="read-more" href="#">Reply <i class="far fa-angle-right"></i></a> <p>Tours and travels play a crucial role in enriching lives by offering unique experiences, cultural exchanges, and the joy of exploration.</p>
</div> <a class="read-more" href="#">Reply <i class="far fa-angle-right"></i></a>
</div> </div>
<div class="comment-body" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div>
<div class="author-thumb"> <div class="comment-body" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/blog/comment-author3.jpg" alt="Author"> <div class="author-thumb">
</div> <img src="assets/images/blog/comment-author3.jpg" alt="Author">
<div class="content"> </div>
<h6>Jaime B. Wilson</h6> <div class="content">
<div class="ratting"> <h6>Jaime B. Wilson</h6>
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<span class="time">Venice, Rome and Milan 9 Days 8 Nights</span> </div>
<p>Tours and travels play a crucial role in enriching lives by offering unique experiences, cultural exchanges, and the joy of exploration.</p> <span class="time">Venice, Rome and Milan 9 Days 8 Nights</span>
<a class="read-more" href="#">Reply <i class="far fa-angle-right"></i></a> <p>Tours and travels play a crucial role in enriching lives by offering unique experiences, cultural exchanges, and the joy of exploration.</p>
</div> <a class="read-more" href="#">Reply <i class="far fa-angle-right"></i></a>
</div> </div>
</div> --> </div>
</div> -->
<!-- <h5>Add A Reviews</h5>
<form id="comment-form" class="comment-form bgc-lighter z-1 rel mt-30" name="review-form" action="#" method="post" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <!-- <h5>Add A Reviews</h5>
<div class="row gap-20"> <form id="comment-form" class="comment-form bgc-lighter z-1 rel mt-30" name="review-form" action="#" method="post" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="col-md-6"> <div class="row gap-20">
<div class="form-group"> <div class="col-md-6">
<input type="text" id="full-name" name="full-name" class="form-control" placeholder="Name" value="" required=""> <div class="form-group">
</div> <input type="text" id="full-name" name="full-name" class="form-control" placeholder="Name" value="" required="">
</div> </div>
<div class="col-md-6"> </div>
<div class="form-group"> <div class="col-md-6">
<input type="email" id="email-address" name="email" class="form-control" placeholder="Email" value="" required=""> <div class="form-group">
</div> <input type="email" id="email-address" name="email" class="form-control" placeholder="Email" value="" required="">
</div> </div>
<div class="col-md-12"> </div>
<div class="form-group"> <div class="col-md-12">
<textarea name="message" id="message" class="form-control" rows="5" placeholder="Comments" required=""></textarea> <div class="form-group">
</div> <textarea name="message" id="message" class="form-control" rows="5" placeholder="Comments" required=""></textarea>
</div> </div>
<div class="col-md-12"> </div>
<div class="form-group mb-0"> <div class="col-md-12">
<button type="submit" class="theme-btn bgc-secondary style-two"> <div class="form-group mb-0">
<span data-hover="Submit reviews">Submit review</span> <button type="submit" class="theme-btn bgc-secondary style-two">
<i class="fal fa-arrow-right"></i> <span data-hover="Submit reviews">Submit review</span>
</button> <i class="fal fa-arrow-right"></i>
</div> </button>
</div> </div>
</div> </div>
</form> --> </div>
<!-- </div> --> </form> -->
</div> <!-- </div> -->
</div> </div>
</section> </div>
<!-- Product Details End --> </section>
<!-- Product Details End -->
<!-- Shop Details Area start -->
<section class="shop-details-page pt-80 pb-100 rel z-1"> <!-- Shop Details Area start -->
<div class="container"> <section class="shop-details-page pt-80 pb-100 rel z-1">
<div class="section-title text-center mb-40"> <div class="container">
<h2>Other Courses</h2> <div class="section-title text-center mb-40">
</div> <h2>Other Courses</h2>
<div class="product-slider"> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50"> <div class="product-slider">
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/shop/product1.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product1.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Airport Travel Suitcases</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Airport Travel Suitcases</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50">
<img src="assets/images/shop/product2.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product2.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Travel Great blue hat</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Travel Great blue hat</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100">
<img src="assets/images/shop/product3.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product3.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Waistband and Mesh Fashion</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Waistband and Mesh Fashion</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="150"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="150">
<img src="assets/images/shop/product4.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product4.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Sandals for Casual Techies</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Sandals for Casual Techies</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/shop/product5.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product5.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Children With Jute Soles</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Children With Jute Soles</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<!-- Shop Details Area end --> </section>
<!-- Shop Details Area end -->
<?php include_once('insta_footer.php') ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php') ?>

View File

@@ -1,388 +1,389 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
checkUserSession(); include_once($rootPath . '/header.php');
checkUserSession();
// SQL query to fetch dates for driver training
$stmt = $conn->prepare("SELECT course_id, date // SQL query to fetch dates for driver training
FROM courses $stmt = $conn->prepare("SELECT course_id, date
WHERE course_type = ? FROM courses
AND date >= CURDATE()"); WHERE course_type = ?
$course_type = 'driver_training'; AND date >= CURDATE()");
$stmt->bind_param("s", $course_type); $course_type = 'driver_training';
$stmt->execute(); $stmt->bind_param("s", $course_type);
$result = $stmt->get_result(); $stmt->execute();
$page_id = 'driver_training'; $result = $stmt->get_result();
$page_id = 'driver_training';
?>
?>
<style>
.form-group { <style>
margin-bottom: 15px; .form-group {
} margin-bottom: 15px;
}
select {
width: 100%; select {
padding: 8px; width: 100%;
font-size: 16px; padding: 8px;
} font-size: 16px;
</style><?php }
$pageTitle = 'Driver Training'; </style><?php
$breadcrumbs = [['Home' => 'index.php']]; $pageTitle = 'Driver Training';
require_once('components/banner.php'); $breadcrumbs = [['Home' => 'index.php']];
?> require_once($rootPath . '/components/banner.php');
?>
<!-- Product Details Start -->
<section class="product-details pt-100"> <!-- Product Details Start -->
<div class="container"> <section class="product-details pt-100">
<div class="row"> <div class="container">
<div class="col-lg-6"> <div class="row">
<div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6">
<div class="tab-content preview-images"> <div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="tab-pane fade preview-item active show" id="preview1"> <div class="tab-content preview-images">
<img src="assets/images/drivertraining/01.png" alt="Perview"> <div class="tab-pane fade preview-item active show" id="preview1">
</div> <img src="assets/images/drivertraining/01.png" alt="Perview">
<div class="tab-pane fade preview-item" id="preview2"> </div>
<img src="assets/images/drivertraining/07.jpg" alt="Perview"> <div class="tab-pane fade preview-item" id="preview2">
</div> <img src="assets/images/drivertraining/07.jpg" alt="Perview">
<div class="tab-pane fade preview-item" id="preview3"> </div>
<img src="assets/images/drivertraining/02.png" alt="Perview"> <div class="tab-pane fade preview-item" id="preview3">
</div> <img src="assets/images/drivertraining/02.png" alt="Perview">
</div> </div>
<div class="nav thumb-images rmb-20"> </div>
<a href="#preview1" data-bs-toggle="tab" class="thumb-item active show"> <div class="nav thumb-images rmb-20">
<img src="assets/images/drivertraining/01.png" alt="Thumb"> <a href="#preview1" data-bs-toggle="tab" class="thumb-item active show">
</a> <img src="assets/images/drivertraining/01.png" alt="Thumb">
<a href="#preview2" data-bs-toggle="tab" class="thumb-item"> </a>
<img src="assets/images/drivertraining/07.jpg" alt="Thumb"> <a href="#preview2" data-bs-toggle="tab" class="thumb-item">
</a> <img src="assets/images/drivertraining/07.jpg" alt="Thumb">
<a href="#preview3" data-bs-toggle="tab" class="thumb-item"> </a>
<img src="assets/images/drivertraining/02.png" alt="Thumb"> <a href="#preview3" data-bs-toggle="tab" class="thumb-item">
</a> <img src="assets/images/drivertraining/02.png" alt="Thumb">
</div> </a>
</div> </div>
</div> </div>
<div class="col-lg-6"> </div>
<div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6">
<div class="section-title"> <div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<h2>4X4 Driver Training</h2> <div class="section-title">
</div> <h2>4X4 Driver Training</h2>
<!-- <div class="ratting mb-15"> </div>
<i class="fas fa-star"></i> <!-- <div class="ratting mb-15">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
<span>(5.8k+ reviews)</span> <i class="fas fa-star-half-alt"></i>
</div> --> <span>(5.8k+ reviews)</span>
<span class="price mb-5">R <?= getPrice('driver_training', 'member'); ?>/member</span> </div> -->
<span class="price mb-25">R <?= getPrice('driver_training', 'nonmember'); ?>/non-members</span> <span class="price mb-5">R <?= getPrice('driver_training', 'member'); ?>/member</span>
<p>Our 4x4 Basic Training Course equips you with the essential skills and knowledge to confidently tackle off-road terrains. Learn vehicle mechanics, driving techniques, obstacle navigation, and recovery methods while promoting safe and responsible off-road practices. Perfect for beginners and new 4x4 owners!</p> <span class="price mb-25">R <?= getPrice('driver_training', 'nonmember'); ?>/non-members</span>
<hr class="mt-40"> <p>Our 4x4 Basic Training Course equips you with the essential skills and knowledge to confidently tackle off-road terrains. Learn vehicle mechanics, driving techniques, obstacle navigation, and recovery methods while promoting safe and responsible off-road practices. Perfect for beginners and new 4x4 owners!</p>
<div class="blog-sidebar tour-sidebar"> <hr class="mt-40">
<div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="blog-sidebar tour-sidebar">
<form action="process_course_booking.php" method="POST"> <div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul class="tickets clearfix"> <form action="process_course_booking" method="POST">
<li> <ul class="tickets clearfix">
Select Date <li>
<select name="course_id" id="course_id" required> Select Date
<?php <select name="course_id" id="course_id" required>
if ($result && $result->num_rows > 0) { <?php
// Output each course as an option if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { // Output each course as an option
$course_id = htmlspecialchars($row['course_id']); // Escape output for security while ($row = $result->fetch_assoc()) {
$date = htmlspecialchars($row['date']); // Escape output for security $course_id = htmlspecialchars($row['course_id']); // Escape output for security
echo "<option value='$course_id'>$date</option>"; $date = htmlspecialchars($row['date']); // Escape output for security
} echo "<option value='$course_id'>$date</option>";
} else { }
echo "<option value='' disabled>No dates available</option>"; } else {
} echo "<option value='' disabled>No dates available</option>";
?> }
</select> ?>
</select>
</li>
<?php </li>
if ($is_member || $pending_member) { <?php
echo ' if ($is_member || $pending_member) {
<li> echo '
Additional Members <span class="price"></span> <li>
<select name="members" id="members"> Additional Members <span class="price"></span>
<option value="0" selected>00</option> <select name="members" id="members">
<option value="1">01</option> <option value="0" selected>00</option>
<option value="2">02</option> <option value="1">01</option>
<option value="3">03</option> <option value="2">02</option>
</select> <option value="3">03</option>
</li> </select>
'; </li>
} ?> ';
} ?>
<li>
Additional Non-Members <span class="price"></span> <li>
<select name="non-members" id="non-members"> Additional Non-Members <span class="price"></span>
<option value="0" selected>00</option> <select name="non-members" id="non-members">
<option value="1">01</option> <option value="0" selected>00</option>
<option value="2">02</option> <option value="1">01</option>
<option value="3">03</option> <option value="2">02</option>
</select> <option value="3">03</option>
</li> </select>
</li>
</ul>
<hr class="mb-25"> </ul>
<hr class="mb-25">
<h6>Total: <span id="booking_total" class="price">-</span></h6>
<div style="margin: 20px 0;"> <h6>Total: <span id="booking_total" class="price">-</span></h6>
<div id="indemnityBox" style="border: 1px solid #ccc; padding: 10px; height: 150px; overflow-y: scroll; background: #f9f9f9; font-size: 12px;"> <div style="margin: 20px 0;">
<p><strong>INDEMNITY AND WAIVER</strong></p> <div id="indemnityBox" style="border: 1px solid #ccc; padding: 10px; height: 150px; overflow-y: scroll; background: #f9f9f9; font-size: 12px;">
<p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p> <p><strong>INDEMNITY AND WAIVER</strong></p>
<p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p> <p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p>
<p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p> <p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p>
<p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p> <p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p>
<p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p> <p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p>
<p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p> <p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p>
<p><strong>BASE 4 CODE OF CONDUCT</strong></p> <p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p>
<p>1. No motorbikes or quadbikes.</p> <p><strong>BASE 4 CODE OF CONDUCT</strong></p>
<p>2. No loud music (unless authorised by the Committee or its representatives).</p> <p>1. No motorbikes or quadbikes.</p>
<p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p> <p>2. No loud music (unless authorised by the Committee or its representatives).</p>
<p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p> <p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p>
<p>5. No person in the rear of open vehicles when driving on obstacles.</p> <p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p>
<p>6. When driving the obstacles stay on the tracks.</p> <p>5. No person in the rear of open vehicles when driving on obstacles.</p>
<p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p> <p>6. When driving the obstacles stay on the tracks.</p>
<p>8. No alcohol to be consumed while driving the track.</p> <p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p>
<p>9. No littering (please pick up cigarette butts etc.)</p> <p>8. No alcohol to be consumed while driving the track.</p>
<p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p> <p>9. No littering (please pick up cigarette butts etc.)</p>
<p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p> <p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p>
<p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p> <p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p>
</div> <p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p>
<div style="margin-top: 10px;"> </div>
<input type="checkbox" id="agreeCheckbox" name="agree" disabled required> <div style="margin-top: 10px;">
<label for="agreeCheckbox" id="agreeLabel" style="color: #888;">I have read and agree to the indemnity terms</label> <input type="checkbox" id="agreeCheckbox" name="agree" disabled required>
</div> <label for="agreeCheckbox" id="agreeLabel" style="color: #888;">I have read and agree to the indemnity terms</label>
</div> </div>
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> </div>
<?php <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
$button_text = "Book Now"; <?php
$button_disabled = ""; $button_text = "Book Now";
if (!$result || $result->num_rows == 0) { $button_disabled = "";
$button_text = "No booking dates available"; if (!$result || $result->num_rows == 0) {
$button_disabled = "disabled"; $button_text = "No booking dates available";
} $button_disabled = "disabled";
?> }
<button type="submit" class="theme-btn style-two w-100 mt-15 mb-5" <?php echo $button_disabled; ?>> ?>
<span data-hover="<?php echo $button_text; ?>"><?php echo $button_text; ?></span> <button type="submit" class="theme-btn style-two w-100 mt-15 mb-5" <?php echo $button_disabled; ?>>
<i class="fal fa-arrow-right"></i> <span data-hover="<?php echo $button_text; ?>"><?php echo $button_text; ?></span>
</button> <i class="fal fa-arrow-right"></i>
<div class="text-center"> </button>
<a href="contact.php">Need some help?</a> <div class="text-center">
</div> <a href="contact">Need some help?</a>
</form> </div>
</div> </form>
</div>
</div>
<!-- <hr class="mb-45"> --> </div>
<!-- <a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a> --> <!-- <hr class="mb-45"> -->
</div> <!-- <a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a> -->
</div> </div>
</div> </div>
<ul class="nav nav product-tab mt-70 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div>
<li><a href="#details" data-bs-toggle="tab" class="active show">Course Overview<i class="far fa-arrow-right"></i></a></li> <ul class="nav nav product-tab mt-70 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<li><a href="#information" data-bs-toggle="tab">What to Expect<i class="far fa-arrow-right"></i></a></li> <li><a href="#details" data-bs-toggle="tab" class="active show">Course Overview<i class="far fa-arrow-right"></i></a></li>
<li><a href="#reviews" data-bs-toggle="tab"> Reviews <i class="far fa-arrow-right"></i></a></li> <li><a href="#information" data-bs-toggle="tab">What to Expect<i class="far fa-arrow-right"></i></a></li>
</ul> <li><a href="#reviews" data-bs-toggle="tab"> Reviews <i class="far fa-arrow-right"></i></a></li>
<div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50"> </ul>
<div class="tab-pane fade active show" id="details"> <div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
<p>A 4x4 Basic Training Course is designed to equip participants with the foundational knowledge and practical skills necessary for safe and effective off-road driving. This course covers essential topics such as understanding the mechanics of 4x4 vehicles, selecting the appropriate gear, and engaging various drive modes to tackle different terrains. Participants will learn how to navigate obstacles like mud, sand, and rocky paths while maintaining vehicle control and ensuring safety for themselves and their passengers. The training also includes instruction on tire pressure management, vehicle recovery techniques, and the use of essential recovery equipment like tow straps and shackles.</p> <div class="tab-pane fade active show" id="details">
<p>In addition to practical driving exercises, the course emphasizes responsible off-road driving practices, including respecting the environment and adhering to trail etiquette. Whether you're a novice driver looking to explore off-road adventures or a new 4x4 owner seeking confidence behind the wheel, this training provides a comprehensive introduction to the world of off-roading. By the end of the course, participants will feel prepared to tackle basic off-road challenges with skill and assurance, making their next 4x4 outing a safe and enjoyable experience.</p> <p>A 4x4 Basic Training Course is designed to equip participants with the foundational knowledge and practical skills necessary for safe and effective off-road driving. This course covers essential topics such as understanding the mechanics of 4x4 vehicles, selecting the appropriate gear, and engaging various drive modes to tackle different terrains. Participants will learn how to navigate obstacles like mud, sand, and rocky paths while maintaining vehicle control and ensuring safety for themselves and their passengers. The training also includes instruction on tire pressure management, vehicle recovery techniques, and the use of essential recovery equipment like tow straps and shackles.</p>
<div class="row gap-50 pt-25 pb-20 align-items-center"> <p>In addition to practical driving exercises, the course emphasizes responsible off-road driving practices, including respecting the environment and adhering to trail etiquette. Whether you're a novice driver looking to explore off-road adventures or a new 4x4 owner seeking confidence behind the wheel, this training provides a comprehensive introduction to the world of off-roading. By the end of the course, participants will feel prepared to tackle basic off-road challenges with skill and assurance, making their next 4x4 outing a safe and enjoyable experience.</p>
<div class="col-lg-7 pt-15"> <div class="row gap-50 pt-25 pb-20 align-items-center">
<h5>What this course includes</h5> <div class="col-lg-7 pt-15">
<ul class="list-style-two mt-25"> <h5>What this course includes</h5>
<li>Basic Driver Training Manual.</li> <ul class="list-style-two mt-25">
<li>Theory session and discussion.</li> <li>Basic Driver Training Manual.</li>
<li>Spend the afternoon on the track learning the basic practices of 4X4 driving.</li> <li>Theory session and discussion.</li>
</ul> <li>Spend the afternoon on the track learning the basic practices of 4X4 driving.</li>
</div> </ul>
<div class="col-lg-5"> </div>
<div class="image rmt-45"> <div class="col-lg-5">
<img src="assets/images/drivertraining/dt04.jpg" alt="Product Details"> <div class="image rmt-45">
</div> <img src="assets/images/drivertraining/dt04.jpg" alt="Product Details">
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="information"> </div>
<!-- <p>Circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses</p> --> <div class="tab-pane fade" id="information">
<ul class="list-style-two my-35"> <!-- <p>Circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses</p> -->
<li>Coffee and Welcome: Start the day with a warm cup of coffee, meet the instructors, and get an overview of the training schedule.</li> <ul class="list-style-two my-35">
<li>Theory Session: Learn the fundamentals of 4x4 vehicle mechanics, terrain types, recovery equipment, and off-road safety.</li> <li>Coffee and Welcome: Start the day with a warm cup of coffee, meet the instructors, and get an overview of the training schedule.</li>
<li>Practical Demonstrations: Observe demonstrations of essential techniques like gear selection, tire pressure adjustment, and recovery setups.</li> <li>Theory Session: Learn the fundamentals of 4x4 vehicle mechanics, terrain types, recovery equipment, and off-road safety.</li>
<li>Lunch Break: Bring along a packed lunch or something to braai. Fires will be provided.</li> <li>Practical Demonstrations: Observe demonstrations of essential techniques like gear selection, tire pressure adjustment, and recovery setups.</li>
<li>Track Driving and Practical Training: Put theory into action with hands-on driving exercises on a custom-designed off-road track.</li> <li>Lunch Break: Bring along a packed lunch or something to braai. Fires will be provided.</li>
<li>Debrief and Certificates: Wrap up the day with a recap of key lessons, feedback from instructors, and certificates of completion.</li> <li>Track Driving and Practical Training: Put theory into action with hands-on driving exercises on a custom-designed off-road track.</li>
</ul> <li>Debrief and Certificates: Wrap up the day with a recap of key lessons, feedback from instructors, and certificates of completion.</li>
</div> </ul>
<div class="tab-pane fade mb-20" id="reviews"> </div>
<?php include_once('review_box.php'); ?> <div class="tab-pane fade mb-20" id="reviews">
</div> <?php include_once('review_box.php'); ?>
</div> </div>
</div> </div>
</section> </div>
<!-- Product Details End --> </section>
<!-- Product Details End -->
<!-- Shop Details Area start -->
<!-- <section class="shop-details-page pt-80 pb-100 rel z-1"> <!-- Shop Details Area start -->
<div class="container"> <!-- <section class="shop-details-page pt-80 pb-100 rel z-1">
<div class="section-title text-center mb-40"> <div class="container">
<h2>Other Courses</h2> <div class="section-title text-center mb-40">
</div> <h2>Other Courses</h2>
<div class="product-slider"> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50"> <div class="product-slider">
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/shop/product1.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product1.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Airport Travel Suitcases</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Airport Travel Suitcases</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50">
<img src="assets/images/shop/product2.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product2.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Travel Great blue hat</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Travel Great blue hat</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100">
<img src="assets/images/shop/product3.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product3.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Waistband and Mesh Fashion</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Waistband and Mesh Fashion</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="150"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="150">
<img src="assets/images/shop/product4.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product4.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Sandals for Casual Techies</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Sandals for Casual Techies</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/shop/product5.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product5.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Children With Jute Soles</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Children With Jute Soles</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
</div> </div>
</div> </div>
</section> --> </div>
<!-- Shop Details Area end --> </section> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <!-- Shop Details Area end -->
<script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
const indemnityBox = document.getElementById('indemnityBox'); <script>
const agreeCheckbox = document.getElementById('agreeCheckbox'); const indemnityBox = document.getElementById('indemnityBox');
const bookingForm = document.querySelector('form'); const agreeCheckbox = document.getElementById('agreeCheckbox');
const bookingForm = document.querySelector('form');
indemnityBox.addEventListener('scroll', function() {
const scrollTop = indemnityBox.scrollTop; indemnityBox.addEventListener('scroll', function() {
const scrollHeight = indemnityBox.scrollHeight; const scrollTop = indemnityBox.scrollTop;
const offsetHeight = indemnityBox.offsetHeight; const scrollHeight = indemnityBox.scrollHeight;
const offsetHeight = indemnityBox.offsetHeight;
// Enable checkbox when scrolled to bottom
if (scrollTop + offsetHeight >= scrollHeight - 1) { // Enable checkbox when scrolled to bottom
agreeCheckbox.disabled = false; if (scrollTop + offsetHeight >= scrollHeight - 1) {
document.getElementById('agreeLabel').style.color = "#000"; // optional: make label active agreeCheckbox.disabled = false;
} document.getElementById('agreeLabel').style.color = "#000"; // optional: make label active
}); }
});
bookingForm.addEventListener('submit', function(e) {
if (agreeCheckbox.disabled || !agreeCheckbox.checked) { bookingForm.addEventListener('submit', function(e) {
alert('Please read and agree to the indemnity terms before booking.'); if (agreeCheckbox.disabled || !agreeCheckbox.checked) {
e.preventDefault(); // stop form submission alert('Please read and agree to the indemnity terms before booking.');
} e.preventDefault(); // stop form submission
}); }
</script> });
<script> </script>
$(document).ready(function() { <script>
// Function to calculate booking total $(document).ready(function() {
function calculateTotal() { // Function to calculate booking total
// Get selected values from the form function calculateTotal() {
var members = parseInt($('#members').val()) || 0; // Default to 1 vehicle if not selected // Get selected values from the form
var nonmembers = parseInt($('#non-members').val()) || 0; // Default to 1 adult if not selected var members = parseInt($('#members').val()) || 0; // Default to 1 vehicle if not selected
var nonmembers = parseInt($('#non-members').val()) || 0; // Default to 1 adult if not selected
// Fetch PHP variables
var isMember = <?php echo $is_member ? 'true' : 'false'; ?>; // Fetch PHP variables
var pendingMember = <?php echo $pending_member ? 'true' : 'false'; ?>; var isMember = <?php echo $is_member ? 'true' : 'false'; ?>;
var cost_members = <?= getPrice('driver_training', 'member'); ?>; var pendingMember = <?php echo $pending_member ? 'true' : 'false'; ?>;
var cost_nonmembers = <?= getPrice('driver_training', 'nonmember'); ?>; var cost_members = <?= getPrice('driver_training', 'member'); ?>;
var cost_nonmembers = <?= getPrice('driver_training', 'nonmember'); ?>;
// Calculate the total cost based on membership
var total = 0; // Calculate the total cost based on membership
var total = 0;
// Calculate cost for members
if (isMember || pendingMember) { // Calculate cost for members
total = (cost_members) + (members * cost_members) + (nonmembers * cost_nonmembers); if (isMember || pendingMember) {
} else { total = (cost_members) + (members * cost_members) + (nonmembers * cost_nonmembers);
// Calculate cost for non-members } else {
total = (cost_nonmembers) + (members * cost_members) + (nonmembers * cost_nonmembers); // Calculate cost for non-members
} total = (cost_nonmembers) + (members * cost_members) + (nonmembers * cost_nonmembers);
}
// Update total price in the DOM
$('#booking_total').text('R ' + total.toFixed(2)); // Update total price in the DOM
$('#booking_total').text('R ' + total.toFixed(2));
}
}
// Event listeners to trigger recalculation when any form field changes
$('#members, #non-members').on('change', function() { // Event listeners to trigger recalculation when any form field changes
calculateTotal(); $('#members, #non-members').on('change', function() {
}); calculateTotal();
});
// Initial calculation on page load
calculateTotal(); // Initial calculation on page load
}); calculateTotal();
</script> });
</script>
<?php include_once('insta_footer.php') ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php') ?>

File diff suppressed because it is too large Load Diff

View File

@@ -1,139 +1,141 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); // Determine the correct path to header.php based on file location
?> $rootPath = dirname(dirname(dirname(__DIR__)));
include_once($rootPath . '/header.php');
<style> ?>
.image {
width: 400px; <style>
/* Set your desired width */ .image {
height: 350px; width: 400px;
/* Set your desired height */ /* Set your desired width */
overflow: hidden; height: 350px;
/* Hide any overflow */ /* Set your desired height */
display: block; overflow: hidden;
/* Ensure proper block behavior */ /* Hide any overflow */
} display: block;
</style> /* Ensure proper block behavior */
}
<?php </style>
$pageTitle = 'Trips';
$breadcrumbs = [['Home' => 'index.php']]; <?php
require_once('components/banner.php'); $pageTitle = 'Trips';
?> $breadcrumbs = [['Home' => 'index.php']];
require_once($rootPath . '/components/banner.php');
<!-- Tour List Area start --> ?>
<section class="tour-list-page py-100 rel z-1">
<div class="container"> <!-- Tour List Area start -->
<div class="row"> <section class="tour-list-page py-100 rel z-1">
<div class="container">
<div class="col-lg-12"> <div class="row">
<div class="shop-shorter rel z-3 mb-20">
<!-- <ul class="grid-list mb-15 me-2"> <div class="col-lg-12">
<li><a href="#"><i class="fal fa-border-all"></i></a></li> <div class="shop-shorter rel z-3 mb-20">
<li><a href="#"><i class="far fa-list"></i></a></li> <!-- <ul class="grid-list mb-15 me-2">
</ul> --> <li><a href="#"><i class="fal fa-border-all"></i></a></li>
<div class="sort-text mb-15 me-4 me-xl-auto"> <li><a href="#"><i class="far fa-list"></i></a></li>
<?php echo getTripCount();?> Trips available </ul> -->
</div> <div class="sort-text mb-15 me-4 me-xl-auto">
<!-- <div class="sort-text mb-15 me-4"> <?php echo getTripCount();?> Trips available
Sort By </div>
</div> <!-- <div class="sort-text mb-15 me-4">
<select> Sort By
<option value="default" selected="">Sort By</option> </div>
<option value="new">Newness</option> <select>
<option value="old">Oldest</option> <option value="default" selected="">Sort By</option>
<option value="hight-to-low">High To Low</option> <option value="new">Newness</option>
<option value="low-to-high">Low To High</option> <option value="old">Oldest</option>
</select> --> <option value="hight-to-low">High To Low</option>
</div> <option value="low-to-high">Low To High</option>
<?php </select> -->
</div>
<?php
// Query to retrieve data from the trips table
$sql = "SELECT trip_id, trip_name, location, short_description, start_date, end_date, vehicle_capacity, cost_members, places_booked FROM trips WHERE published = 1 AND start_date > CURDATE()";
$result = $conn->query($sql); // Query to retrieve data from the trips table
$sql = "SELECT trip_id, trip_name, location, short_description, start_date, end_date, vehicle_capacity, cost_members, places_booked FROM trips WHERE published = 1 AND start_date > CURDATE()";
if ($result->num_rows > 0) { $result = $conn->query($sql);
// Loop through each row
while ($row = $result->fetch_assoc()) { if ($result->num_rows > 0) {
$trip_id = $row['trip_id']; // Loop through each row
$trip_name = $row['trip_name']; while ($row = $result->fetch_assoc()) {
$location = $row['location']; $trip_id = $row['trip_id'];
$short_description = $row['short_description']; $trip_name = $row['trip_name'];
$start_date = $row['start_date']; $location = $row['location'];
$end_date = $row['end_date']; $short_description = $row['short_description'];
$capacity = $row['vehicle_capacity']; $start_date = $row['start_date'];
$cost_members = $row['cost_members']; $end_date = $row['end_date'];
$places_booked = $row['places_booked']; $capacity = $row['vehicle_capacity'];
$remaining_places = getAvailableSpaces($trip_id); $cost_members = $row['cost_members'];
$places_booked = $row['places_booked'];
// Determine the badge text based on the status $remaining_places = getAvailableSpaces($trip_id);
$badge_text = ($remaining_places > 0) ? $remaining_places.' PLACES LEFT!!' : 'FULLY BOOKED';
// Determine the badge text based on the status
// Output the HTML structure with dynamic data $badge_text = ($remaining_places > 0) ? $remaining_places.' PLACES LEFT!!' : 'FULLY BOOKED';
echo '
<div class="destination-item style-three bgc-lighter" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> // Output the HTML structure with dynamic data
<div class="image"> echo '
<span class="badge bgc-pink">' . $badge_text . '</span> <div class="destination-item style-three bgc-lighter" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/trips/' . $trip_id . '_01.jpg" alt="' . $trip_name . '"> <div class="image">
</div> <span class="badge bgc-pink">' . $badge_text . '</span>
<div class="content"> <img src="assets/images/trips/' . $trip_id . '_01.jpg" alt="' . $trip_name . '">
<div class="destination-header"> </div>
<span class="location"><i class="fal fa-map-marker-alt"></i> ' . $location . '</span> <div class="content">
<div class="ratting"> <div class="destination-header">
<i class="fas fa-star"></i> <span class="location"><i class="fal fa-map-marker-alt"></i> ' . $location . '</span>
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star"></i>
</div> <i class="fas fa-star"></i>
<h5><a href="trip-details.php?token=' . encryptData($trip_id, $salt) . '">' . $trip_name . '</a></h5> </div>
<p>' . $short_description . '</p> </div>
<ul class="blog-meta"> <h5><a href="trip-details.php?token=' . encryptData($trip_id, $salt) . '">' . $trip_name . '</a></h5>
<li><i class="far fa-calendar"></i> ' . convertDate($start_date) . ' - ' . convertDate($end_date) . '</li> <p>' . $short_description . '</p>
<li><i class="far fa-clock"></i> '.calculateDaysAndNights($start_date, $end_date).'</li> <ul class="blog-meta">
<li><i class="far fa-user"></i>' . $capacity . ' vehicles max</li> <li><i class="far fa-calendar"></i> ' . convertDate($start_date) . ' - ' . convertDate($end_date) . '</li>
</ul> <li><i class="far fa-clock"></i> '.calculateDaysAndNights($start_date, $end_date).'</li>
<div class="destination-footer"> <li><i class="far fa-user"></i>' . $capacity . ' vehicles max</li>
<span class="price"><span>R ' . $cost_members . '</span>/person</span> </ul>
<a href="trip-details.php?token=' . encryptData($trip_id, $salt) . '" class="theme-btn style-two style-three"> <div class="destination-footer">
<span data-hover="Book Now">Book Now</span> <span class="price"><span>R ' . $cost_members . '</span>/person</span>
<i class="fal fa-arrow-right"></i> <a href="trip-details.php?token=' . encryptData($trip_id, $salt) . '" class="theme-btn style-two style-three">
</a> <span data-hover="Book Now">Book Now</span>
</div> <i class="fal fa-arrow-right"></i>
</div> </a>
</div>'; </div>
} </div>
} </div>';
}
// Close connection }
$conn->close();
?> // Close connection
$conn->close();
<!-- <ul class="pagination pt-15 flex-wrap" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> ?>
<li class="page-item disabled">
<span class="page-link"><i class="far fa-chevron-left"></i></span> <!-- <ul class="pagination pt-15 flex-wrap" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
</li> <li class="page-item disabled">
<li class="page-item active"> <span class="page-link"><i class="far fa-chevron-left"></i></span>
<span class="page-link"> </li>
1 <li class="page-item active">
<span class="sr-only">(current)</span> <span class="page-link">
</span> 1
</li> <span class="sr-only">(current)</span>
<li class="page-item"><a class="page-link" href="#">2</a></li> </span>
<li class="page-item"><a class="page-link" href="#">3</a></li> </li>
<li class="page-item"><a class="page-link" href="#">...</a></li> <li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"> <li class="page-item"><a class="page-link" href="#">3</a></li>
<a class="page-link" href="#"><i class="far fa-chevron-right"></i></a> <li class="page-item"><a class="page-link" href="#">...</a></li>
</li> <li class="page-item">
</ul> --> <a class="page-link" href="#"><i class="far fa-chevron-right"></i></a>
</div> </li>
</div> </ul> -->
</div> </div>
</section> </div>
<!-- Tour List Area end --> </div>
</section>
<!-- Tour List Area end -->
<?php include_once("insta_footer.php"); ?>
<?php include_once($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,257 +1,258 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
$page_id = 'agm_minutes'; include_once($rootPath . '/header.php');
?> $page_id = 'agm_minutes';
?>
<style>
.image { <style>
width: 400px; .image {
/* Set your desired width */ width: 400px;
height: 350px; /* Set your desired width */
/* Set your desired height */ height: 350px;
overflow: hidden; /* Set your desired height */
/* Hide any overflow */ overflow: hidden;
display: block; /* Hide any overflow */
/* Ensure proper block behavior */ display: block;
} /* Ensure proper block behavior */
}
.image img {
width: 100%; .image img {
/* Image scales to fill the container */ width: 100%;
height: 100%; /* Image scales to fill the container */
/* Image scales to fill the container */ height: 100%;
object-fit: cover; /* Image scales to fill the container */
/* Fills the container while maintaining aspect ratio */ object-fit: cover;
object-position: top; /* Fills the container while maintaining aspect ratio */
/* Aligns the top of the image with the top of the container */ object-position: top;
display: block; /* Aligns the top of the image with the top of the container */
/* Prevents inline whitespace issues */ display: block;
} /* Prevents inline whitespace issues */
</style> }
<style> </style>
body { <style>
/* font-family: Arial, sans-serif; */ body {
line-height: 1.6; /* font-family: Arial, sans-serif; */
/* max-width: 800px; */ line-height: 1.6;
margin: auto; /* max-width: 800px; */
/* padding: 20px; */ margin: auto;
} /* padding: 20px; */
}
h1,
h2 { h1,
color: #2c3e50; h2 {
} color: #2c3e50;
}
h2 {
margin-top: 2em; h2 {
} margin-top: 2em;
}
.content {
margin-bottom: 2em; .content {
} margin-bottom: 2em;
}
.img-left,
.img-right { .img-left,
max-width: 30%; .img-right {
margin: 20px; max-width: 30%;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin: 20px;
border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
} border-radius: 10px;
}
.img-left {
float: left; .img-left {
} float: left;
}
.img-right {
float: right; .img-right {
} float: right;
}
</style>
</style>
<?php
$pageTitle = '2025 AGM Minutes'; <?php
$breadcrumbs = [['Home' => 'index.php']]; $pageTitle = '2025 AGM Minutes';
require_once('components/banner.php'); $breadcrumbs = [['Home' => 'index.php']];
?> require_once($rootPath . '/components/banner.php');
?>
<!-- Blog Detaisl Area start -->
<section class="blog-detaisl-page py-100 rel z-1"> <!-- Blog Detaisl Area start -->
<div class="container"> <section class="blog-detaisl-page py-100 rel z-1">
<div class="row"> <div class="container">
<div class="col-lg-8"> <div class="row">
<div class="blog-details-content" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-8">
<a href="blog.html" class="category">Report</a> <div class="blog-details-content" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul class="blog-meta mb-30"> <a href="blog.html" class="category">Report</a>
<li><img src="assets/images/pp/default.png" alt="Admin"> <a href="#">John Runciman</a></li> <ul class="blog-meta mb-30">
<li><i class="far fa-calendar-alt"></i> <a href="#">5 April 2025</a></li> <li><img src="assets/images/pp/default.png" alt="Admin"> <a href="#">John Runciman</a></li>
<li><i class="far fa-comments"></i> <a href="#">Comments (<?= getCommentCount($page_id);?>)</a></li> <li><i class="far fa-calendar-alt"></i> <a href="#">5 April 2025</a></li>
</ul> <li><i class="far fa-comments"></i> <a href="#">Comments (<?= getCommentCount($page_id);?>)</a></li>
<h2>2025 AGM Minutes & Chairman's Report</h2> </ul>
<?php include_once('agm_content.php');?> <h2>2025 AGM Minutes & Chairman's Report</h2>
<?php include_once('agm_content.php');?>
</div>
</div>
<hr class="mb-45">
<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"> <div class="tag-share mb-50">
<h6>Tags </h6> <div class="item" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="tag-coulds"> <h6>Tags </h6>
<a href="blog.php">Reports</a> <div class="tag-coulds">
<a href="blog">Reports</a>
</div>
</div> </div>
<!-- <div class="item" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> </div>
<h6>Share </h6> <!-- <div class="item" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<div class="social-style-one"> <h6>Share </h6>
<a href="#"><i class="fab fa-facebook-f"></i></a> <div class="social-style-one">
<a href="#"><i class="fab fa-twitter"></i></a> <a href="#"><i class="fab fa-facebook-f"></i></a>
<a href="#"><i class="fab fa-linkedin-in"></i></a> <a href="#"><i class="fab fa-twitter"></i></a>
<a href="#"><i class="fab fa-instagram"></i></a> <a href="#"><i class="fab fa-linkedin-in"></i></a>
</div> <a href="#"><i class="fab fa-instagram"></i></a>
</div> --> </div>
</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="admin-comment bgc-lighter" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="author-thumb"> <div class="comment-body">
<img src="assets/images/blog/admin-comment.jpg" alt="Author"> <div class="author-thumb">
</div> <img src="assets/images/blog/admin-comment.jpg" alt="Author">
<div class="content"> </div>
<h4>Richard M. Fudge</h4> <div class="content">
<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> <h4>Richard M. Fudge</h4>
<div class="social-icons"> <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>
<a href="contact.html"><i class="fab fa-facebook-f"></i></a> <div class="social-icons">
<a href="contact.html"><i class="fab fa-twitter"></i></a> <a href="contact.html"><i class="fab fa-facebook-f"></i></a>
<a href="contact.html"><i class="fab fa-linkedin-in"></i></a> <a href="contact.html"><i class="fab fa-twitter"></i></a>
<a href="contact.html"><i class="fab fa-instagram"></i></a> <a href="contact.html"><i class="fab fa-linkedin-in"></i></a>
</div> <a href="contact.html"><i class="fab fa-instagram"></i></a>
</div> </div>
</div> </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> <!-- <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">
<p>Your email address will not be published. Required fields are marked *</p> <h5>Leave A Comment</h5>
<div class="row gap-20 mt-30"> <p>Your email address will not be published. Required fields are marked *</p>
<div class="col-md-6"> <div class="row gap-20 mt-30">
<div class="form-group"> <div class="col-md-6">
<input type="text" id="full-name" name="full-name" class="form-control" placeholder="Name" value="" required=""> <div class="form-group">
</div> <input type="text" id="full-name" name="full-name" class="form-control" placeholder="Name" value="" required="">
</div> </div>
<div class="col-md-6"> </div>
<div class="form-group"> <div class="col-md-6">
<input type="email" id="email-address" name="email" class="form-control" placeholder="Email" value="" required=""> <div class="form-group">
</div> <input type="email" id="email-address" name="email" class="form-control" placeholder="Email" value="" required="">
</div> </div>
<div class="col-md-12"> </div>
<div class="form-group"> <div class="col-md-12">
<textarea name="message" id="message" class="form-control" rows="5" placeholder="Message" required=""></textarea> <div class="form-group">
</div> <textarea name="message" id="message" class="form-control" rows="5" placeholder="Message" required=""></textarea>
</div> </div>
<div class="col-md-12"> </div>
<div class="form-group mb-0"> <div class="col-md-12">
<ul class="radio-filter mb-25"> <div class="form-group mb-0">
<li> <ul class="radio-filter mb-25">
<input class="form-check-input" type="radio" name="terms-condition" id="terms-condition"> <li>
<label for="terms-condition">Save my name, email, and website in this browser for the next time I comment.</label> <input class="form-check-input" type="radio" name="terms-condition" id="terms-condition">
</li> <label for="terms-condition">Save my name, email, and website in this browser for the next time I comment.</label>
</ul> </li>
<button type="submit" class="theme-btn style-two"> </ul>
<span data-hover="Send Comments">Send Comments</span> <button type="submit" class="theme-btn style-two">
<i class="fal fa-arrow-right"></i> <span data-hover="Send Comments">Send Comments</span>
</button> <i class="fal fa-arrow-right"></i>
</div> </button>
</div> </div>
</div> </div>
</form> --> </div>
<?php include_once('comment_box.php'); ?> </form> -->
</div> <?php include_once('comment_box.php'); ?>
<div class="col-lg-4 col-md-8 col-sm-10 rmt-75"> </div>
<div class="blog-sidebar"> <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"> <!-- <div class="widget widget-search" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<input type="text" placeholder="Search" required=""> <form action="#" class="default-search-form">
<button type="submit" class="searchbutton far fa-search"></button> <input type="text" placeholder="Search" required="">
</form> <button type="submit" class="searchbutton far fa-search"></button>
</div> --> </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> <!-- <div class="widget widget-category" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul class="list-style-three"> <h5 class="widget-title">Category</h5>
<li><a href="blog.html">Adventure</a></li> <ul class="list-style-three">
<li><a href="blog.html">Hiking & Trekking</a></li> <li><a href="blog.html">Adventure</a></li>
<li><a href="blog.html">Cycling Tours</a></li> <li><a href="blog.html">Hiking & Trekking</a></li>
<li><a href="blog.html">Family Tours</a></li> <li><a href="blog.html">Cycling Tours</a></li>
<li><a href="blog.html">Mountain Hiking</a></li> <li><a href="blog.html">Family Tours</a></li>
<li><a href="blog.html">Rafting Excursion</a></li> <li><a href="blog.html">Mountain Hiking</a></li>
<li><a href="blog.html">Coastal Paragliding</a></li> <li><a href="blog.html">Rafting Excursion</a></li>
</ul> <li><a href="blog.html">Coastal Paragliding</a></li>
</div> --> </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> <!-- <div class="widget widget-news" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul> <h5 class="widget-title">Recent News</h5>
<li> <ul>
<div class="image"> <li>
<img src="assets/images/widgets/news1.jpg" alt="News"> <div class="image">
</div> <img src="assets/images/widgets/news1.jpg" alt="News">
<div class="content"> </div>
<h6><a href="blog-details.html">Unique Destinations an tolded Stories ways</a></h6> <div class="content">
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <h6><a href="blog-details.html">Unique Destinations an tolded Stories ways</a></h6>
</div> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
</li> </div>
<li> </li>
<div class="image"> <li>
<img src="assets/images/widgets/news2.jpg" alt="News"> <div class="image">
</div> <img src="assets/images/widgets/news2.jpg" alt="News">
<div class="content"> </div>
<h6><a href="blog-details.html">Immersive Experiences from Around Globe</a></h6> <div class="content">
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <h6><a href="blog-details.html">Immersive Experiences from Around Globe</a></h6>
</div> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
</li> </div>
<li> </li>
<div class="image"> <li>
<img src="assets/images/widgets/news3.jpg" alt="News"> <div class="image">
</div> <img src="assets/images/widgets/news3.jpg" alt="News">
<div class="content"> </div>
<h6><a href="blog-details.html">Journey to Inspire Your Next Adventure</a></h6> <div class="content">
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <h6><a href="blog-details.html">Journey to Inspire Your Next Adventure</a></h6>
</div> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
</li> </div>
</ul> </li>
</div> --> </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="widget widget-gallery" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="gallery"> <h5 class="widget-title">Gallery</h5>
<?php <div class="gallery">
$folder = 'assets/images/blog/2/'; <?php
$files = glob($folder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $folder = 'assets/images/blog/2/';
shuffle($files); // Randomize the order $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;">'; foreach ($files as $file) {
echo '<img src="' . $file . '" alt="Gallery" style="width: 100%; height: 100%; object-fit: cover; display: block;">'; echo '<a href="' . $file . '" style="width: 110px; height: 110px; overflow: hidden; display: inline-block; margin: 2px;">';
echo '</a>'; echo '<img src="' . $file . '" alt="Gallery" style="width: 100%; height: 100%; object-fit: cover; display: block;">';
} echo '</a>';
?> }
</div> ?>
</div> </div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<!-- Blog Detaisl Area end --> </section>
<!-- Blog Detaisl Area end -->
<?php include_once("insta_footer.php"); ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,384 +1,384 @@
<style> <style>
.dropcap { .dropcap {
float: left; float: left;
font-size: 3em; font-size: 3em;
line-height: 1; line-height: 1;
padding-right: 0.1em; padding-right: 0.1em;
font-weight: bold; font-weight: bold;
} }
</style> </style>
<p><strong>DATE:</strong> 05 April 2025 at 10h00<br> <p><strong>DATE:</strong> 05 April 2025 at 10h00<br>
<strong>VENUE:</strong> Base 4 <strong>VENUE:</strong> Base 4
</p> </p>
<p> <p>
<h6><strong>NOTICE CONVENING THE MEETING</strong></h6> <h6><strong>NOTICE CONVENING THE MEETING</strong></h6>
<ul> <ul>
<li>Proposed: Peter Hutchison</li> <li>Proposed: Peter Hutchison</li>
<li>Seconded: Doug Timm</li> <li>Seconded: Doug Timm</li>
<li>Attendance register will be available on request</li> <li>Attendance register will be available on request</li>
</ul> </ul>
</p> </p>
<p> <p>
<h6><strong>WELCOME, APOLOGIES AND PROXIES</strong></h6> <h6><strong>WELCOME, APOLOGIES AND PROXIES</strong></h6>
<ul> <ul>
<li>Present: 30</li> <li>Present: 30</li>
<li>Proxies: 15 Total: 45</li> <li>Proxies: 15 Total: 45</li>
<li>Apologies: 2</li> <li>Apologies: 2</li>
<li>Quorum confirmed</li> <li>Quorum confirmed</li>
</ul> </ul>
</p> </p>
<p> <p>
<h6><strong>ACCEPTANCE OF THE AGENDA WITH ANY ADDITIONAL ITEMS FROM THE FLOOR</strong></h6> <h6><strong>ACCEPTANCE OF THE AGENDA WITH ANY ADDITIONAL ITEMS FROM THE FLOOR</strong></h6>
<ul> <ul>
<li>Proposed: Roy Olivier</li> <li>Proposed: Roy Olivier</li>
<li>Seconded: Davin Webster</li> <li>Seconded: Davin Webster</li>
</ul> </ul>
</p> </p>
<p> <p>
<h6><strong>CONFIRMATION OF THE MINUTES OF THE PREVIOUS AGM OF 25 MARCH 2023</strong></h6> <h6><strong>CONFIRMATION OF THE MINUTES OF THE PREVIOUS AGM OF 25 MARCH 2023</strong></h6>
<ul> <ul>
<li>Matters arising from the previous minutes: None</li> <li>Matters arising from the previous minutes: None</li>
<li>Proposed: Dave Nixon</li> <li>Proposed: Dave Nixon</li>
<li>Seconded: Peter Hutchison</li> <li>Seconded: Peter Hutchison</li>
</ul> </ul>
</p> </p>
<h3><strong>CHAIRMANS REPORT</strong></h3> <h3><strong>CHAIRMANS 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 wont drag this out. <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 wont 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> 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> <h6><strong>FIRE</strong></h6>
<p class="content"> <p class="content">
<img style="max-width: 45%;" src="assets/images/blog/2/agm.jpg" alt="Base 4 Fire" class="img-left"> <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 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. <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> 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>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> </p>
<h6><strong>SPECIAL GENERAL MEETING</strong></h6> <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>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>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>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> <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> <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>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> <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> <h6><strong>CLUB SECRETARY</strong></h6>
<p>Karl Hoffmans 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>Karl Hoffmans 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>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: <p>Please make a note regarding the Club contact details:
<ul> <ul>
<li>info@4wdcsa.co.za</li> <li>info@4wdcsa.co.za</li>
<li>4wdcsa@gmail.com</li> <li>4wdcsa@gmail.com</li>
<li>079 065 2795</li> <li>079 065 2795</li>
</ul> </ul>
</p> </p>
<h6><strong>THANK YOUS</strong></h6> <h6><strong>THANK YOUS</strong></h6>
<p>I want to thank all those that have put in time and effort this past year</p> <p>I want to thank all those that have put in time and effort this past year</p>
<p><strong>The Committee</strong> <p><strong>The Committee</strong>
<ul> <ul>
<li>Peter Hutchison</li> <li>Peter Hutchison</li>
<li>Chris Pinto</li> <li>Chris Pinto</li>
<li>Doug Timm</li> <li>Doug Timm</li>
<li>Noelene Runciman</li> <li>Noelene Runciman</li>
<li>Dorota Maskowicz</li> <li>Dorota Maskowicz</li>
<li>Noel Thompson</li> <li>Noel Thompson</li>
<li>Dave Nixon</li> <li>Dave Nixon</li>
</ul> </ul>
</p> </p>
<p><strong>The Breakfast brigade</strong> <p><strong>The Breakfast brigade</strong>
<ul> <ul>
<li>Linda Hutchison</li> <li>Linda Hutchison</li>
<li>Clara Hitge</li> <li>Clara Hitge</li>
<li>Lesley Joubert</li> <li>Lesley Joubert</li>
<li>Louise Blignaut</li> <li>Louise Blignaut</li>
<li>Carol Corlett</li> <li>Carol Corlett</li>
<li>Stan Salida</li> <li>Stan Salida</li>
<li>Ashley Salida</li> <li>Ashley Salida</li>
</ul> </ul>
</p> </p>
<p><strong>Event organisation</strong> <p><strong>Event organisation</strong>
<ul> <ul>
<li>Noelene Runciman</li> <li>Noelene Runciman</li>
<li>Dorota Maskowicz</li> <li>Dorota Maskowicz</li>
</ul> </ul>
</p> </p>
<p><strong>Base 4 maintenance</strong> <p><strong>Base 4 maintenance</strong>
<ul> <ul>
<li>Dave Nixon</li> <li>Dave Nixon</li>
<li>Peter Hutchison</li> <li>Peter Hutchison</li>
<li>Dave Bell</li> <li>Dave Bell</li>
<li>Andre Botha</li> <li>Andre Botha</li>
<li>Andrew Maier</li> <li>Andrew Maier</li>
<li>Davin Webster</li> <li>Davin Webster</li>
<li>Clive Murray</li> <li>Clive Murray</li>
<li>Doug Galloway</li> <li>Doug Galloway</li>
<li>Jenny Crickmore-Thompson</li> <li>Jenny Crickmore-Thompson</li>
<li>John Franklin</li> <li>John Franklin</li>
<li>Marion Nichols</li> <li>Marion Nichols</li>
<li>Richard Carter</li> <li>Richard Carter</li>
<li>Chas Dean</li> <li>Chas Dean</li>
<li>Rudolf Engelmann</li> <li>Rudolf Engelmann</li>
<li>Nelson Larangeira</li> <li>Nelson Larangeira</li>
<li><strong>Base 4</strong>: Kingsley Mankhusu</li> <li><strong>Base 4</strong>: Kingsley Mankhusu</li>
</ul> </ul>
</p> </p>
<p>If I have left anyone out, please forgive me!</p> <p>If I have left anyone out, please forgive me!</p>
<p> <p>
<h6><strong>OUTINGS</strong></h6> <h6><strong>OUTINGS</strong></h6>
<p>This has been a bumper year for outings, 11 in total. <p>This has been a bumper year for outings, 11 in total.
<ul> <ul>
<li>Best of the Eastern Cape (February 2024)</li> <li>Best of the Eastern Cape (February 2024)</li>
<li>Parys Dome Extended Trip (March 2024)</li> <li>Parys Dome Extended Trip (March 2024)</li>
<li>Piesangskloof Day Trip (May 2024)</li> <li>Piesangskloof Day Trip (May 2024)</li>
<li>Botsalano Game Reserve extended trip (June)</li> <li>Botsalano Game Reserve extended trip (June)</li>
<li>Groenkloof Day Trip (June 2024)</li> <li>Groenkloof Day Trip (June 2024)</li>
<li>Hobby Park Krugersdorp (August). Sadly no one turned up</li> <li>Hobby Park Krugersdorp (August). Sadly no one turned up</li>
<li>Old Mill Drift Extended Trip (September)</li> <li>Old Mill Drift Extended Trip (September)</li>
<li>Rust de Winter Weekend Trip (October 2024)</li> <li>Rust de Winter Weekend Trip (October 2024)</li>
<li>Northern Natal Bush and Beach Extended Trip (November 2024)</li> <li>Northern Natal Bush and Beach Extended Trip (November 2024)</li>
<li>Mabibi Turtle Hatching Extended Trip (February 2025)</li> <li>Mabibi Turtle Hatching Extended Trip (February 2025)</li>
<li>Marakele National Park Extended Trip (March 2025)</li> <li>Marakele National Park Extended Trip (March 2025)</li>
</ul> </ul>
</p> </p>
<p> <p>
<h6><strong>OPEN DAYS</strong></h6> <h6><strong>OPEN DAYS</strong></h6>
<ul> <ul>
<li>February 2024 Chris Dykes on his 650km walk through the Kruger Park</li> <li>February 2024 Chris Dykes on his 650km walk through the Kruger Park</li>
<li>March 2024 Carol Corlett on Coffee</li> <li>March 2024 Carol Corlett on Coffee</li>
<li>April 2024 Anita Musevenzo on Save the Bees</li> <li>April 2024 Anita Musevenzo on Save the Bees</li>
<li>May 2024 4x4 Poker Rally</li> <li>May 2024 4x4 Poker Rally</li>
<li>June 2024 Any pot will do cook-off</li> <li>June 2024 Any pot will do cook-off</li>
<li>July 2024 Rob Milne on Anecdotes of the Boer War</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>August 2024 Bob Boden on Leopards of the Magaliesburg</li>
<li>September 2024 Spring clean</li> <li>September 2024 Spring clean</li>
<li>October 2024 Kevin Davie on Rock Art</li> <li>October 2024 Kevin Davie on Rock Art</li>
<li>November 2925 Tarryn Johnston on Hennops Revival</li> <li>November 2925 Tarryn Johnston on Hennops Revival</li>
<li>February 2025 Jack Kapp on Trip Report to Botswana and Zimbabwe</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> <li>March 2025 Wayne van Onselen on Unchain our Children</li>
</ul> </ul>
</p> </p>
<p> <p>
<h6><strong>EVENTS</strong></h6> <h6><strong>EVENTS</strong></h6>
<ul> <ul>
<li>Annual General Meeting (April)</li> <li>Annual General Meeting (April)</li>
<li>4x4 Poker Trail Fun Rally (May)</li> <li>4x4 Poker Trail Fun Rally (May)</li>
<li>Any pot will do cook-off (June) Winner Sandy Nixon</li> <li>Any pot will do cook-off (June) Winner Sandy Nixon</li>
<li>Potjie cooking competition (July) Winner Muzzy</li> <li>Potjie cooking competition (July) Winner Muzzy</li>
<li>Special General Meeting (November 2024)</li> <li>Special General Meeting (November 2024)</li>
<li>Christmas Party (December)</li> <li>Christmas Party (December)</li>
</ul> </ul>
</p> </p>
<p> <p>
<h6><strong>DRIVER TRAINING</strong></h6> <h6><strong>DRIVER TRAINING</strong></h6>
<p>Another great perk of Club Membership is free driver training, make use of it!</p> <p>Another great perk of Club Membership is free driver training, make use of it!</p>
<ul> <ul>
<li>Driver Training Course (March 2024)</li> <li>Driver Training Course (March 2024)</li>
<li>Bush Mechanics Course (April 2024)</li> <li>Bush Mechanics Course (April 2024)</li>
<li>Rescue and Recovery Course (June 2024)</li> <li>Rescue and Recovery Course (June 2024)</li>
<li>Driver Training Course (July 2024)</li> <li>Driver Training Course (July 2024)</li>
<li>Bush Mechanics Course (October 2024)</li> <li>Bush Mechanics Course (October 2024)</li>
<li>Ladies Driver Training (March 2025)</li> <li>Ladies Driver Training (March 2025)</li>
<li>Driver training course (March 2025)</li> <li>Driver training course (March 2025)</li>
</ul> </ul>
</p> </p>
<h3><strong>ADDRESS</strong></h3> <h3><strong>ADDRESS</strong></h3>
<p> <p>
<span class="dropcap">A</span> little later this morning we are going to make some decisions about the future of Base 4. <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. What I want to talk about is the future of The Four Wheel Club of Southern Africa, Gauteng region.
</p> </p>
<p> <p>
The burning down of our Clubhouse and Lapa can be seen as a blessing. This gives us the opportunity of starting afresh: 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. 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, 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. and all the good things we associate with being a member of an Outdoor Adventure Club.
</p> </p>
<p> <p>
The upswing in outings and events this last year show that we are moving in that direction! The upswing in outings and events this last year show that we are moving in that direction!
</p> </p>
<h6>Membership</h6> <h6>Membership</h6>
<p>For members to get the full benefit of membership requires participation.</p> <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>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>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>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><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> <p>
These benefits only start there! Getting or giving advice from knowledgeable people. These benefits only start there! Getting or giving advice from knowledgeable people.
Sharing adventures, enjoying new travel companions. Sharing adventures, enjoying new travel companions.
As I said, getting the benefit of your membership requires your participation. As I said, getting the benefit of your membership requires your participation.
</p> </p>
<h6>Running the Club</h6> <h6>Running the Club</h6>
<p> <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 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 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. 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! 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>
<p> <p>
Historically Committee Members had portfolios that they managed, Outings, Events, Estate management, Driver training and so on. 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 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. 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! 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>
<p> <p>
Going forward, the Committee (or the Management Team) is mandated to run the Club along acceptable company practices, 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 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. and organising outings, events etc. but the responsibility for organising and running of these portfolios will now lie with the Membership.
</p> </p>
<p> <p>
Amongst yourselves volunteer or delegate Members to lead trips, find speakers, organise events. Organise workdays at Base 4. 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. 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. Only one! Come on! We need to share the load.
</p> </p>
<p> <p>
I will stick to my side of the bargain. I will organise and lead at least 1 extended outing this year, 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. and I will conduct driver training for the rest of the year.
</p> </p>
<p><strong>Please get involved!</strong></p> <p><strong>Please get involved!</strong></p>
<h3><strong>GERALD OBRIEN</strong></h3> <h3><strong>GERALD OBRIEN</strong></h3>
<p>I have pleasure in announcing that the Committee after due consideration has decided to bestow Honorary Life Membership on Gerald OBrien.</p> <p>I have pleasure in announcing that the Committee after due consideration has decided to bestow Honorary Life Membership on Gerald OBrien.</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>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 ask Geoff Joubert to give a brief run down on his life and times.</p>
<p><i>Short presentation by Geoff Joubert</i></p> <p><i>Short presentation by Geoff Joubert</i></p>
<h3><strong>TREASURER'S REPORT AND FINANCIAL STATEMENT FOR 2024 / 2025</strong></h3> <h3><strong>TREASURER'S REPORT AND FINANCIAL STATEMENT FOR 2024 / 2025</strong></h3>
<p><strong>FWDCSA February 2025 Financials</strong></p> <p><strong>FWDCSA February 2025 Financials</strong></p>
<p> <p>
<ul> <ul>
<li>Doug Timm, the Club Treasurer, presented the Treasurers report.</li> <li>Doug Timm, the Club Treasurer, presented the Treasurers report.</li>
<li>Any member that requires a copy please contact the Club Secretary</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>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> <li>Proposed: John Runciman Seconded: Peter Hutchison</li>
</ul> </ul>
</p> </p>
<h3><strong>NOMINATION AND ELECTION OF COMMITTEE FOR 2025</strong></h3> <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> <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> <h6>Standing members available for re-election</h6>
<p> <p>
<ul> <ul>
<li>John Runciman</li> <li>John Runciman</li>
<li>Noelene Runciman</li> <li>Noelene Runciman</li>
<li>Doug Timm</li> <li>Doug Timm</li>
<li>Peter Hutchison</li> <li>Peter Hutchison</li>
<li>Chris Pinto</li> <li>Chris Pinto</li>
<li>Proposed: Mike Hitge Seconded: Zita Harber</li> <li>Proposed: Mike Hitge Seconded: Zita Harber</li>
</ul> </ul>
</p> </p>
<h6>Members resigning from the Committee</h6> <h6>Members resigning from the Committee</h6>
<p> <p>
<ul> <ul>
<li>Noel Thompson</li> <li>Noel Thompson</li>
<li>Dorota Maskowicz</li> <li>Dorota Maskowicz</li>
<li>Dave Nixon</li> <li>Dave Nixon</li>
</ul> </ul>
</p> </p>
<h6>New members to the Committee</h6> <h6>New members to the Committee</h6>
<p>No one proposed.</p> <p>No one proposed.</p>
<h3><strong>TRIBUTE TO KARL HOFFMAN</strong></h3> <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. <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> <i>Short presentation by Geoff Joubert</i>
</p> </p>
<h3><strong>MOTIONS FOR VOTING</strong></h3> <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>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>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> <p>Each proposal was presented by the proposer.</p>
<h6><strong>PROPOSAL 1 Andrew Maier</strong></h6> <h6><strong>PROPOSAL 1 Andrew Maier</strong></h6>
<p> <p>
<ul> <ul>
<li>We do not develop Base 4 at all and that we try and sell the property.</li> <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>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> <li>Buy and lease to a company for a caravan park/camping ground with exclusive rights for the Club.</li>
</ul> </ul>
</p> </p>
<h6><strong>PROPOSAL 2 John Runciman</strong></h6> <h6><strong>PROPOSAL 2 John Runciman</strong></h6>
<p> <p>
<ul> <ul>
<li>Demolish remains and build new structure at the camping site (15x12m steel portal).</li> <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>3 containers (kitchen, bar, storage), all under roof.</li>
<li>Use bottom entrance as main entrance. Cost: R1,200,000</li> <li>Use bottom entrance as main entrance. Cost: R1,200,000</li>
</ul> </ul>
</p> </p>
<h6><strong>PROPOSAL 3 John Runciman</strong></h6> <h6><strong>PROPOSAL 3 John Runciman</strong></h6>
<p> <p>
<ul> <ul>
<li>Similar to current configuration: 12x12m gum/steel structure + 1 container (kitchen/bar/storage).</li> <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> <li>Use bottom entrance as main entrance. Cost: R450,000</li>
</ul> </ul>
</p> </p>
<p><em>Proposals 2 and 3 presented together. Proposal 3 seen as a basis for future development.</em></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> <h6><strong>PROPOSAL 4 Alan Exton</strong></h6>
<p> <p>
<ul> <ul>
<li>Minimum build, prioritize security. Gum pole shed with lean-to roof.</li> <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> <li>If Proposal 2 adopted, increase container spacing to 1.5m and include adequate toilets.</li>
</ul> </ul>
</p> </p>
<h6><strong>PROPOSAL 5 Dorota Maskowicz</strong></h6> <h6><strong>PROPOSAL 5 Dorota Maskowicz</strong></h6>
<p> <p>
<ul> <ul>
<li>Sell Base 4 ASAP, invest funds.</li> <li>Sell Base 4 ASAP, invest funds.</li>
<li>Open days/weekends continue at various 4x4 and camping venues.</li> <li>Open days/weekends continue at various 4x4 and camping venues.</li>
</ul> </ul>
</p> </p>
<h6><strong>PROPOSAL 6 Clive Murray</strong></h6> <h6><strong>PROPOSAL 6 Clive Murray</strong></h6>
<p> <p>
<ul> <ul>
<li>Remove old structures, place 4 containers on flat ground, add bow roof structure.</li> <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> <li>Replace camping ablutions with a container. Cost: R1,595,000</li>
</ul> </ul>
</p> </p>
<h6><strong>DISCUSSION</strong></h6> <h6><strong>DISCUSSION</strong></h6>
<p> <p>
<ul> <ul>
<li>Engineer to assess toilet/kitchen block structure</li> <li>Engineer to assess toilet/kitchen block structure</li>
<li>Base 4 is part of a conservancy: building restrictions</li> <li>Base 4 is part of a conservancy: building restrictions</li>
<li>Consider security hub on-site</li> <li>Consider security hub on-site</li>
<li>Maintain swimming pool</li> <li>Maintain swimming pool</li>
</ul> </ul>
</p> </p>
<h6><strong>VOTING</strong></h6> <h6><strong>VOTING</strong></h6>
<p> <p>
<ul> <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 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> <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> </ul>
</p> </p>
<h3><strong>GENERAL</strong></h3> <h3><strong>GENERAL</strong></h3>
<p>Nothing raised</p> <p>Nothing raised</p>
<h3><strong>CLOSING OF MEETING</strong></h3> <h3><strong>CLOSING OF MEETING</strong></h3>
<p><strong>Time:</strong> 12h10</p> <p><strong>Time:</strong> 12h10</p>

View File

@@ -1,434 +1,435 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
$page_id = 'best_0f_ec'; include_once($rootPath . '/header.php');
?> $page_id = 'best_0f_ec';
?>
<style>
.image { <style>
width: 400px; .image {
/* Set your desired width */ width: 400px;
height: 350px; /* Set your desired width */
/* Set your desired height */ height: 350px;
overflow: hidden; /* Set your desired height */
/* Hide any overflow */ overflow: hidden;
display: block; /* Hide any overflow */
/* Ensure proper block behavior */ display: block;
} /* Ensure proper block behavior */
}
.image img {
width: 100%; .image img {
/* Image scales to fill the container */ width: 100%;
height: 100%; /* Image scales to fill the container */
/* Image scales to fill the container */ height: 100%;
object-fit: cover; /* Image scales to fill the container */
/* Fills the container while maintaining aspect ratio */ object-fit: cover;
object-position: top; /* Fills the container while maintaining aspect ratio */
/* Aligns the top of the image with the top of the container */ object-position: top;
display: block; /* Aligns the top of the image with the top of the container */
/* Prevents inline whitespace issues */ display: block;
} /* Prevents inline whitespace issues */
</style> }
<style> </style>
body { <style>
/* font-family: Arial, sans-serif; */ body {
line-height: 1.6; /* font-family: Arial, sans-serif; */
/* max-width: 800px; */ line-height: 1.6;
margin: auto; /* max-width: 800px; */
/* padding: 20px; */ margin: auto;
} /* padding: 20px; */
}
h1,
h2 { h1,
color: #2c3e50; h2 {
} color: #2c3e50;
}
h2 {
margin-top: 2em; h2 {
} margin-top: 2em;
}
.content {
margin-bottom: 2em; .content {
} margin-bottom: 2em;
}
.img-left,
.img-right { .img-left,
max-width: 30%; .img-right {
margin: 20px; max-width: 30%;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin: 20px;
border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
} border-radius: 10px;
}
.img-left {
float: left; .img-left {
} float: left;
}
.img-right {
float: right; .img-right {
} float: right;
}
</style>
</style>
<?php
$pageTitle = 'Best of the Eastern Cape 2024'; <?php
$breadcrumbs = [['Home' => 'index.php']]; $pageTitle = 'Best of the Eastern Cape 2024';
require_once('components/banner.php'); $breadcrumbs = [['Home' => 'index.php']];
?> require_once($rootPath . '/components/banner.php');
?>
<!-- Blog Detaisl Area start -->
<section class="blog-detaisl-page py-100 rel z-1"> <!-- Blog Detaisl Area start -->
<div class="container"> <section class="blog-detaisl-page py-100 rel z-1">
<div class="row"> <div class="container">
<div class="col-lg-8"> <div class="row">
<div class="blog-details-content" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-8">
<a href="blog.html" class="category">Travel</a> <div class="blog-details-content" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul class="blog-meta mb-30"> <a href="blog.html" class="category">Travel</a>
<li><img src="assets/images/pp/default.png" alt="Admin"> <a href="#">John Runciman</a></li> <ul class="blog-meta mb-30">
<li><i class="far fa-calendar-alt"></i> <a href="#">25 Feb 2024</a></li> <li><img src="assets/images/pp/default.png" alt="Admin"> <a href="#">John Runciman</a></li>
<li><i class="far fa-comments"></i> <a href="#">Comments (<?= getCommentCount($page_id);?>)</a></li> <li><i class="far fa-calendar-alt"></i> <a href="#">25 Feb 2024</a></li>
</ul> <li><i class="far fa-comments"></i> <a href="#">Comments (<?= getCommentCount($page_id);?>)</a></li>
</ul>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h2>Best of the Eastern Cape 2024</h2> <div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<p>Every year, Noelene and I organise a trip through the Eastern Cape, with the highlight being traversing Baviaanskloof. Each trip has been slightly different to the previous one, with this trip, in my opinion, being the best one!</p> <h2>Best of the Eastern Cape 2024</h2>
<p class="content"> <p>Every year, Noelene and I organise a trip through the Eastern Cape, with the highlight being traversing Baviaanskloof. Each trip has been slightly different to the previous one, with this trip, in my opinion, being the best one!</p>
<img src="assets/images/blog/1/blog_01.jpeg" alt="Bushman's River" class="img-left"> <p class="content">
The idea was to meet up at the village at the mouth of the Bushmans River, Boesmansriviermond, near Kenton-on-Sea. Mike and Clara arrived a few days early and we enjoyed a ride up the Bushmans River in our little boat and walks on the beach.<br><br> <img src="assets/images/blog/1/blog_01.jpeg" alt="Bushman's River" class="img-left">
The rest of the group—Roy and Naome, Doug and Santie, and Dave and Valery—arrived on the Friday, the day before the official departure. Doug and Dave booked a campsite at Cannon Rocks, 20 or so kilometres from Bushmans. The idea was to meet up at the village at the mouth of the Bushmans River, Boesmansriviermond, near Kenton-on-Sea. Mike and Clara arrived a few days early and we enjoyed a ride up the Bushmans River in our little boat and walks on the beach.<br><br>
</p> The rest of the group—Roy and Naome, Doug and Santie, and Dave and Valery—arrived on the Friday, the day before the official departure. Doug and Dave booked a campsite at Cannon Rocks, 20 or so kilometres from Bushmans.
<p>We arranged a braai for that evening, and I admit that I was shocked to my little toes when I saw that Doug and Dave had brought a caravan and camping trailer along. This is definitely not a caravan or trailer-friendly route and I voiced my hesitation.</p> </p>
<p>The long and the short was that Doug decided to continue despite my fears, and Dave decided to withdraw from the trip. This was not entirely due to my warnings but also to Valery not feeling up to scratch. We also heard that Roger would not be able to make it because of personal problems at home.</p> <p>We arranged a braai for that evening, and I admit that I was shocked to my little toes when I saw that Doug and Dave had brought a caravan and camping trailer along. This is definitely not a caravan or trailer-friendly route and I voiced my hesitation.</p>
<p>The long and the short was that Doug decided to continue despite my fears, and Dave decided to withdraw from the trip. This was not entirely due to my warnings but also to Valery not feeling up to scratch. We also heard that Roger would not be able to make it because of personal problems at home.</p>
</div>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Saturday: Bushmans to Ocean View</h5> <div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Saturday: Bushmans to Ocean View</h5>
<p class="content">
<img src="assets/images/blog/1/blog_05.jpeg" alt="Fish River Lighthouse" class="img-left"> <p class="content">
<p>On Saturday morning, the remaining four vehicles met at Bushmans River with our first destination set for Bathurst for breakfast. We drove via the "poor mans game drive" (the old main road from Port Elizabeth to Port Alfred, now incorporated into the Sibuya Game Reserve) and the winding road through the spectacular Cowie River Valley.</p> <img src="assets/images/blog/1/blog_05.jpeg" alt="Fish River Lighthouse" class="img-left">
<p>After brunch (the trip took longer than expected due to the bad roads), we wandered along to the Fish River Lighthouse, a place worth a visit. This historic building was erected in the late 19th century with the light first shining on 1 July 1898. The warning light has a strength of 5,000,000 candelas and is 85 metres above the high water mark with a shine range of 32 sea miles. Wish I had that on the front of my Hilux!</p> <p>On Saturday morning, the remaining four vehicles met at Bushmans River with our first destination set for Bathurst for breakfast. We drove via the "poor mans game drive" (the old main road from Port Elizabeth to Port Alfred, now incorporated into the Sibuya Game Reserve) and the winding road through the spectacular Cowie River Valley.</p>
<p>The most unique feature about the light is that it has no bearings for the 2 ton light to spin on, but rather it floats in a bed of mercury, ingenious!</p> <p>After brunch (the trip took longer than expected due to the bad roads), we wandered along to the Fish River Lighthouse, a place worth a visit. This historic building was erected in the late 19th century with the light first shining on 1 July 1898. The warning light has a strength of 5,000,000 candelas and is 85 metres above the high water mark with a shine range of 32 sea miles. Wish I had that on the front of my Hilux!</p>
</p> <p>The most unique feature about the light is that it has no bearings for the 2 ton light to spin on, but rather it floats in a bed of mercury, ingenious!</p>
</p>
<p class="content">
<img src="assets/images/blog/1/blog_03.jpeg" alt="Baviaanskloof" class="img-right"> <p class="content">
<p>From there we drove back past the Bushmans River, towards Boknes (small village on the sea shore), and onto the scenic gravel road going to Alexandria that services all the dairy farms in the area. We turned off the gravel onto a farm road and came out at a camping site, Ocean View, where we arranged to spend 2 nights in amongst the dense Eastern Cape bush on the edge of the sand dunes. This made for a snug campsite sheltered from the wind.</p> <img src="assets/images/blog/1/blog_03.jpeg" alt="Baviaanskloof" class="img-right">
<p>Interest. The location of this campsite is on the eastern edge of the area with the largest shifting dunes in the southern hemisphere. Truly spectacular!</p> <p>From there we drove back past the Bushmans River, towards Boknes (small village on the sea shore), and onto the scenic gravel road going to Alexandria that services all the dairy farms in the area. We turned off the gravel onto a farm road and came out at a camping site, Ocean View, where we arranged to spend 2 nights in amongst the dense Eastern Cape bush on the edge of the sand dunes. This made for a snug campsite sheltered from the wind.</p>
</p> <p>Interest. The location of this campsite is on the eastern edge of the area with the largest shifting dunes in the southern hemisphere. Truly spectacular!</p>
</p>
<div style="width:100%; object-fit: cover;" class="image mt-40 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/blog/1/blog_04.jpeg" alt="Blog Details"> <div style="width:100%; object-fit: cover;" class="image mt-40 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
</div> <img src="assets/images/blog/1/blog_04.jpeg" alt="Blog Details">
</div>
<div class="clearfix"></div>
</div> <div class="clearfix"></div>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Sunday: Beach Day</h5>
<h5>Sunday: Beach Day</h5>
<p>The next day was spent exploring the beach—miles and miles of pristine beach where there is not another soul to be seen!</p>
</div> <p>The next day was spent exploring the beach—miles and miles of pristine beach where there is not another soul to be seen!</p>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Monday: To Brakkeduine</h5>
<h5>Monday: To Brakkeduine</h5>
<p class="content">
<img src="assets/images/blog/1/blog_06.jpeg" alt="Sand Dunes" class="img-left"> <p class="content">
<p>Monday morning, bright and early, we set off towards Port Elizabeth where we planned to leave Max, our faithful hound, for the duration of the trip, then on to Humansdorp and finally to a resort called Brakkeduine.</p> <img src="assets/images/blog/1/blog_06.jpeg" alt="Sand Dunes" class="img-left">
<p>Doug and Santie, pulling their caravan, suffered a puncture and stopped in the little town of Alexandria to have the tyre repaired and we decided that the remainder would go on in convoy through the thriving metropolis of Port Elizabeth and meet them there.</p> <p>Monday morning, bright and early, we set off towards Port Elizabeth where we planned to leave Max, our faithful hound, for the duration of the trip, then on to Humansdorp and finally to a resort called Brakkeduine.</p>
<p>Once clear of Port Elizabeth, the three remaining vehicles followed the R102, down the old Van Stadens pass, across the single lane bridge spanning the Gamtoos river and past Jeffereys Bay. At Humansdorp we hit the gravel roads eventually reaching Brakkeduine in the late afternoon.</p> <p>Doug and Santie, pulling their caravan, suffered a puncture and stopped in the little town of Alexandria to have the tyre repaired and we decided that the remainder would go on in convoy through the thriving metropolis of Port Elizabeth and meet them there.</p>
<p>Doug and Santie were already there with Doug trying his hand at fishing in the dam. The campsites are to die for! Set along manicured grassy terraced ledges overlooking the dam, each site separated by neatly trimmed hedges.</p> <p>Once clear of Port Elizabeth, the three remaining vehicles followed the R102, down the old Van Stadens pass, across the single lane bridge spanning the Gamtoos river and past Jeffereys Bay. At Humansdorp we hit the gravel roads eventually reaching Brakkeduine in the late afternoon.</p>
<div class="clearfix"></div> <p>Doug and Santie were already there with Doug trying his hand at fishing in the dam. The campsites are to die for! Set along manicured grassy terraced ledges overlooking the dam, each site separated by neatly trimmed hedges.</p>
</p> <div class="clearfix"></div>
</div> </p>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Tuesday: Dune Adventure</h5>
<h5>Tuesday: Dune Adventure</h5>
<p class="content">
<img style="max-width: 45%;" src="assets/images/blog/1/blog_07.jpeg" alt="Sand Dunes" class="img-left"> <p class="content">
<p>The following morning we met Johan, our guide for the day. After airing down (0.6 bar!), we set off in convoy to attack the dunes. Before we reached the first dune, Doug pulled a tyre off the rim. We all got stuck in to repair the wheel and were on the road again fifteen minutes later. The airjack proved its usefulness!</p> <img style="max-width: 45%;" src="assets/images/blog/1/blog_07.jpeg" alt="Sand Dunes" class="img-left">
<p>We played in the sand for the next few hours, then Roy managed to pull one of his tyres off the rim—on a steep incline and in the boiling heat of the midday sun. This time the airjack did not do so well! We were eventually forced to use Mikes trusty hi-lift jack. Eventually, we changed wheels and headed for camp, then back to Humansdorp to get the wheel repaired.</p> <p>The following morning we met Johan, our guide for the day. After airing down (0.6 bar!), we set off in convoy to attack the dunes. Before we reached the first dune, Doug pulled a tyre off the rim. We all got stuck in to repair the wheel and were on the road again fifteen minutes later. The airjack proved its usefulness!</p>
<p>In the mean time, Doug had also picked up a problem with his Prado, and he and Santie decided to head to the Toyota garage in Joubertina further along the R62 with the plan that we would all meet up again in Kareedouw.</p> <p>We played in the sand for the next few hours, then Roy managed to pull one of his tyres off the rim—on a steep incline and in the boiling heat of the midday sun. This time the airjack did not do so well! We were eventually forced to use Mikes trusty hi-lift jack. Eventually, we changed wheels and headed for camp, then back to Humansdorp to get the wheel repaired.</p>
<p>From there, we headed off north into the mountains. The road was not bad, just rocky and plenty of loose stones: I was concerned about the tyres on Dougs Prado and caravan but I need not have worried and we arrived at our camp as the sun was setting.</p> <p>In the mean time, Doug had also picked up a problem with his Prado, and he and Santie decided to head to the Toyota garage in Joubertina further along the R62 with the plan that we would all meet up again in Kareedouw.</p>
<p>Baviaans Lodge is situated in the Kouga Mountains at the start of the Rus en Vrede trail across the mountains to the Baviaanskloof. The campsite is cosy, set among the trees on the bank of a small stream. There is a hot water shower and toilets, all well maintained and clean.</p> <p>From there, we headed off north into the mountains. The road was not bad, just rocky and plenty of loose stones: I was concerned about the tyres on Dougs Prado and caravan but I need not have worried and we arrived at our camp as the sun was setting.</p>
<p>We enjoyed an evening around the campfire and I must be honest and say that I went to bed concerned about Doug pulling his caravan over the mountains to Baviaanskloof.</p> <p>Baviaans Lodge is situated in the Kouga Mountains at the start of the Rus en Vrede trail across the mountains to the Baviaanskloof. The campsite is cosy, set among the trees on the bank of a small stream. There is a hot water shower and toilets, all well maintained and clean.</p>
</p> <p>We enjoyed an evening around the campfire and I must be honest and say that I went to bed concerned about Doug pulling his caravan over the mountains to Baviaanskloof.</p>
</p>
<div class="clearfix"></div>
</div> <div class="clearfix"></div>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Wednesday: Rus en Vrede Trail</h5>
<h5>Wednesday: Rus en Vrede Trail</h5>
<p>The following morning, I cannot emphasise how important it is to be ready and waiting at the designated time. The day was going to be slow going and I was factoring in time for recovery and vehicle maintenance on the mountain. As it happened, there were no delays of problems whatsoever, just slow going over the rough track. In fact, the only casualty was the awning from Mikes Cruiser which was shaken free and rescued by Roy.</p>
<p>The following morning, I cannot emphasise how important it is to be ready and waiting at the designated time. The day was going to be slow going and I was factoring in time for recovery and vehicle maintenance on the mountain. As it happened, there were no delays of problems whatsoever, just slow going over the rough track. In fact, the only casualty was the awning from Mikes Cruiser which was shaken free and rescued by Roy.</p>
<p class="content">
<img style="max-width: 45%;" src="assets/images/blog/1/blog_08.jpeg" alt="Baviaanskloof" class="img-right"> <p class="content">
<p>The Rus en Vrede trail was originally cut across the mountains by the woodcutters back in eighteen something. Now it crosses over three farms, and is a combination of gravel, loose rocks, mountain rocks and eroded farm tracks. There are also 13 gates that had to be opened and closed, thank you Noelene and Naome!</p> <img style="max-width: 45%;" src="assets/images/blog/1/blog_08.jpeg" alt="Baviaanskloof" class="img-right">
<p>The views cover seven different mountain ranges giving one a panoramic view of the area. We were lucky with the weather, clear skies, no wind, and relatively cool conditions. The proteas were out in full bloom and the famous centuries-old cycads stand guard over the peaks and valleys</p> <p>The Rus en Vrede trail was originally cut across the mountains by the woodcutters back in eighteen something. Now it crosses over three farms, and is a combination of gravel, loose rocks, mountain rocks and eroded farm tracks. There are also 13 gates that had to be opened and closed, thank you Noelene and Naome!</p>
</p> <p>The views cover seven different mountain ranges giving one a panoramic view of the area. We were lucky with the weather, clear skies, no wind, and relatively cool conditions. The proteas were out in full bloom and the famous centuries-old cycads stand guard over the peaks and valleys</p>
<p class="content"> </p>
<img src="assets/images/blog/1/blog_09.jpeg" alt="Sand Dunes" class="img-left"> <p class="content">
<p>The trail ends at the Rus en Vrede farm where you pay the farmer per vehicle and per person(details below). Now, onto the main road through the Kloof and a little further we signed in at the entrance to the Baviaanskloof Nature Reserve.</p> <img src="assets/images/blog/1/blog_09.jpeg" alt="Sand Dunes" class="img-left">
<p>The road twists and turns through the Park with many water crossings, deep ravines and high rugged mountains crossing Holgats Pass, Kombrinks Pass, and the Grootrivier Pass. The roads have not been maintained and the going was slow but the scenery was spectacular. The concrete strip road over the mountain is especially rough with the concrete slabs broken and displaced. This was no problem for our vehicles, in fact this was our preferred route given that we were all driving seriously capable off-road vehicles.</p> <p>The trail ends at the Rus en Vrede farm where you pay the farmer per vehicle and per person(details below). Now, onto the main road through the Kloof and a little further we signed in at the entrance to the Baviaanskloof Nature Reserve.</p>
</p> <p>The road twists and turns through the Park with many water crossings, deep ravines and high rugged mountains crossing Holgats Pass, Kombrinks Pass, and the Grootrivier Pass. The roads have not been maintained and the going was slow but the scenery was spectacular. The concrete strip road over the mountain is especially rough with the concrete slabs broken and displaced. This was no problem for our vehicles, in fact this was our preferred route given that we were all driving seriously capable off-road vehicles.</p>
</p>
<p>Our destination was Kudu Kaya, a working citrus farm where we have stayed before, our chosen campsite up on a hill overlooking the farm. Doug had to do a few running repairs on the caravan and Santie worked a good hour cleaning the debris caused to the food supplies being shaken loose by the rough roads: custard and gunk everywhere!</p>
<p>Again, a great evening around the campfire!</p> <p>Our destination was Kudu Kaya, a working citrus farm where we have stayed before, our chosen campsite up on a hill overlooking the farm. Doug had to do a few running repairs on the caravan and Santie worked a good hour cleaning the debris caused to the food supplies being shaken loose by the rough roads: custard and gunk everywhere!</p>
<p>Again, a great evening around the campfire!</p>
<div class="clearfix"></div>
</div> <div class="clearfix"></div>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Thursday: Into the Kloof</h5> <div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Thursday: Into the Kloof</h5>
<p>Thursday morning saw us on the road to Steytlerville via Antonies Pass, a rugged rock and gravel road with many washaways which takes you down to Antoniesberg and the crossing of the Groot River. Again very slow and careful going.</p>
<p>We stopped at the Royal Hotel in Steytlerville for lunch before pushing on to Kaboega, a private farm in the mountains north of Addo Elephant Park, and sharing a boundary with the Park on the southern border. Here we set up camp at the big dam where we have stayed before. We were met and made welcome by the farm manager, Ian Ritchie and his wife Sandy.</p> <p>Thursday morning saw us on the road to Steytlerville via Antonies Pass, a rugged rock and gravel road with many washaways which takes you down to Antoniesberg and the crossing of the Groot River. Again very slow and careful going.</p>
<p>We stopped at the Royal Hotel in Steytlerville for lunch before pushing on to Kaboega, a private farm in the mountains north of Addo Elephant Park, and sharing a boundary with the Park on the southern border. Here we set up camp at the big dam where we have stayed before. We were met and made welcome by the farm manager, Ian Ritchie and his wife Sandy.</p>
<div style="width:100%; object-fit: cover;" class="image mt-40 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/blog/1/blog_11.jpeg" alt="Blog Details"> <div style="width:100%; object-fit: cover;" class="image mt-40 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
</div> <img src="assets/images/blog/1/blog_11.jpeg" alt="Blog Details">
</div> </div>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Friday: To Kaboega</h5> <div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<p>Friday morning Ian and Sandy arrived in camp in time for coffee and while we sipped, Sandy gave us an insight into the Bushmans paintings in the area and a general history of rock paintings in Southern Africa: very interesting stuff! We had arranged for Ian to lead us around the farm, about 6 000 hectares, where he has an intimate knowledge of the plants, the animals, and the terrain. There are seven biodiversitys present here and these diversities have been allowed to flourish with no human intervention for the past 30 to 40 years. We stopped every few kilometres for Ian to show us something, or to tell us a story, or to point out something interesting.</p> <h5>Friday: To Kaboega</h5>
<p class="content"> <p>Friday morning Ian and Sandy arrived in camp in time for coffee and while we sipped, Sandy gave us an insight into the Bushmans paintings in the area and a general history of rock paintings in Southern Africa: very interesting stuff! We had arranged for Ian to lead us around the farm, about 6 000 hectares, where he has an intimate knowledge of the plants, the animals, and the terrain. There are seven biodiversitys present here and these diversities have been allowed to flourish with no human intervention for the past 30 to 40 years. We stopped every few kilometres for Ian to show us something, or to tell us a story, or to point out something interesting.</p>
<img src="assets/images/blog/1/blog_12.jpeg" alt="Sand Dunes" class="img-left"> <p class="content">
<p>Apart from a locked gate to the neighbours where we had to cut the chain, there were no hitches as we climbed the mountain, crossing stream after stream, over rocks and through the bushes to the summit of the mountain. Here, we had originally intended to walk to some bushmans paintings in the rocks, but the sun was westering and the decision was made to move on and rather have Ian take us to a swimming hole deep in the mountains before heading for home.</p> <img src="assets/images/blog/1/blog_12.jpeg" alt="Sand Dunes" class="img-left">
<p>All in all it was a great and informative day and left us all wanting for more. Thank you Ian!</p> <p>Apart from a locked gate to the neighbours where we had to cut the chain, there were no hitches as we climbed the mountain, crossing stream after stream, over rocks and through the bushes to the summit of the mountain. Here, we had originally intended to walk to some bushmans paintings in the rocks, but the sun was westering and the decision was made to move on and rather have Ian take us to a swimming hole deep in the mountains before heading for home.</p>
</p> <p>All in all it was a great and informative day and left us all wanting for more. Thank you Ian!</p>
<div class="clearfix"></div> </p>
</div> <div class="clearfix"></div>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Saturday & Sunday: Mountain Zebra Park</h5> <div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<p>Saturday, on the road again. I planned on taking the secondary gravel roads as far as possible en route to the Mountain Zebra Park via Somerset East and Cradock. We had a delicious breakfast in Somerset East, then followed the road through a giant conservancy before traversing the Swarthoek and Maraiskloof Passes eventually reaching Cradock where we all filled up with fuel.</p> <h5>Saturday & Sunday: Mountain Zebra Park</h5>
<p>West out of Cradock, it was a short hop to the Mountain Zebra Park where we booked in, found a campsite, and set up for the night. Originally we planned to spend one night here, allowing anyone that needed to return to Johannesburg for work on Monday morning to travel on the Sunday. Fortunately all decided to stay an extra night, allowing for extensive game drives on the Sunday.</p> <p>Saturday, on the road again. I planned on taking the secondary gravel roads as far as possible en route to the Mountain Zebra Park via Somerset East and Cradock. We had a delicious breakfast in Somerset East, then followed the road through a giant conservancy before traversing the Swarthoek and Maraiskloof Passes eventually reaching Cradock where we all filled up with fuel.</p>
<p class="content"> <p>West out of Cradock, it was a short hop to the Mountain Zebra Park where we booked in, found a campsite, and set up for the night. Originally we planned to spend one night here, allowing anyone that needed to return to Johannesburg for work on Monday morning to travel on the Sunday. Fortunately all decided to stay an extra night, allowing for extensive game drives on the Sunday.</p>
<img style="max-width: 45%;" src="assets/images/blog/1/blog_13.jpeg" alt="Baviaanskloof" class="img-right"> <p class="content">
<p>The Reserve has a wide diversity of plains animals that were seen aplenty on the plateau areas, especially the rare and once nearly extinct mountain zebra, with other animals to be seen in the deep valley and gorges in the area. There are three 4X4 routes, none too challenging, but fun to drive.</p> <img style="max-width: 45%;" src="assets/images/blog/1/blog_13.jpeg" alt="Baviaanskloof" class="img-right">
<p>We arranged a night drive for the Sunday evening. The weather was turning, cold winds and overcast, so we prepared ourselves with Old Brown Sherry and blankets. This was the middle (almost!) of summer, for goodness sake! The drive was great, buffalo, eland, kudu, you name it. Of great interest were the springhares bouncing along on their hind legs, and 6 porcupines. Sadly we saw no cats or aardwolves.</p> <p>The Reserve has a wide diversity of plains animals that were seen aplenty on the plateau areas, especially the rare and once nearly extinct mountain zebra, with other animals to be seen in the deep valley and gorges in the area. There are three 4X4 routes, none too challenging, but fun to drive.</p>
<p>The drive that was to finish at 21h00 eventually got back to camp at 23h00: thank you to very knowledgeable and generous driver! By now we were frozen solid, back to our campsite for a whiskey and bed. In the morning the temperature gauge on my bakkie read 6 degrees!</p> <p>We arranged a night drive for the Sunday evening. The weather was turning, cold winds and overcast, so we prepared ourselves with Old Brown Sherry and blankets. This was the middle (almost!) of summer, for goodness sake! The drive was great, buffalo, eland, kudu, you name it. Of great interest were the springhares bouncing along on their hind legs, and 6 porcupines. Sadly we saw no cats or aardwolves.</p>
</div> <p>The drive that was to finish at 21h00 eventually got back to camp at 23h00: thank you to very knowledgeable and generous driver! By now we were frozen solid, back to our campsite for a whiskey and bed. In the morning the temperature gauge on my bakkie read 6 degrees!</p>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Monday: The End</h5> <div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<p>Monday morning we packed up and went our separate ways. As I always say, sad to leave but happy to be on our way home.</p> <h5>Monday: The End</h5>
<p>Thank you all that enjoyed the trip with us for all your help, support, friendship and generosity. I am sad that Dave and Verinica, and Roger missed out on a great adventure. Next time!</p> <p>Monday morning we packed up and went our separate ways. As I always say, sad to leave but happy to be on our way home.</p>
<div class="clearfix"></div> <p>Thank you all that enjoyed the trip with us for all your help, support, friendship and generosity. I am sad that Dave and Verinica, and Roger missed out on a great adventure. Next time!</p>
</div> <div class="clearfix"></div>
</div>
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h5>Trip Information</h5>
<p>All the campsites have the basics of hot water, showers, ablutions etc.</p> <h5>Trip Information</h5>
<ul> <p>All the campsites have the basics of hot water, showers, ablutions etc.</p>
<ul>
<li><strong>Cannon Rocks Caravan Park</strong>
<ul> <li><strong>Cannon Rocks Caravan Park</strong>
<li>Phone: 064 654 0043</li> <ul>
<li>75 wind protected sites</li> <li>Phone: 064 654 0043</li>
<li>Power to each site</li> <li>75 wind protected sites</li>
<li>Basic supply store</li> <li>Power to each site</li>
<li>Rates: R370 (low season) to R620 (high season) for 2 people caravan or tent</li> <li>Basic supply store</li>
<li>Also offer pensioner rates and long-stay rates on request</li> <li>Rates: R370 (low season) to R620 (high season) for 2 people caravan or tent</li>
</ul> <li>Also offer pensioner rates and long-stay rates on request</li>
</li> </ul>
<li><strong>Oceanview Camping</strong> </li>
<ul> <li><strong>Oceanview Camping</strong>
<li>Contact: David & Lynne Cordner</li> <ul>
<li>WhatsApp only: 082 573 3660</li> <li>Contact: David & Lynne Cordner</li>
<li>Power to some campsites</li> <li>WhatsApp only: 082 573 3660</li>
<li>Rates on enquiry</li> <li>Power to some campsites</li>
</ul> <li>Rates on enquiry</li>
</li> </ul>
<li><strong>Brakkeduine camping and adventure park</strong> </li>
<ul> <li><strong>Brakkeduine camping and adventure park</strong>
<li>Contact: Bennie & Tania van Niekerk</li> <ul>
<li>Phone: 083 657 0601</li> <li>Contact: Bennie & Tania van Niekerk</li>
<li>Email: <a href="mailto:bellakarmabt@gmail.com">bellakarmabt@gmail.com</a></li> <li>Phone: 083 657 0601</li>
<li>Rates: R100 per person per night, Children R75 PPPN</li> <li>Email: <a href="mailto:bellakarmabt@gmail.com">bellakarmabt@gmail.com</a></li>
<li>Power to each campsite</li> <li>Rates: R100 per person per night, Children R75 PPPN</li>
<li>Guided trips: R300 per vehicle (min 5 vehicles)</li> <li>Power to each campsite</li>
</ul> <li>Guided trips: R300 per vehicle (min 5 vehicles)</li>
</li> </ul>
<li><strong>Baviaans Lodge</strong> </li>
<ul> <li><strong>Baviaans Lodge</strong>
<li>Phone: 083 491 1009</li> <ul>
<li>Email: <a href="mailto:info@baviaanslodge.co.za">info@baviaanslodge.co.za</a></li> <li>Phone: 083 491 1009</li>
<li>Rates: Camping R100 per person per night</li> <li>Email: <a href="mailto:info@baviaanslodge.co.za">info@baviaanslodge.co.za</a></li>
</ul> <li>Rates: Camping R100 per person per night</li>
</li> </ul>
<li><strong>Rus en Vrede 4X4 Trail</strong> </li>
<ul> <li><strong>Rus en Vrede 4X4 Trail</strong>
<li>Contact: Chris Lamprecht</li> <ul>
<li>Phone: 073 232 8932</li> <li>Contact: Chris Lamprecht</li>
<li>Email: <a href="mailto:clamp@igen.co.za">clamp@igen.co.za</a></li> <li>Phone: 073 232 8932</li>
<li>Website: <a href="http://www.baviaanskloof.co.za">www.baviaanskloof.co.za</a></li> <li>Email: <a href="mailto:clamp@igen.co.za">clamp@igen.co.za</a></li>
<li>Fees: R150 per vehicle and R10 per person</li> <li>Website: <a href="http://www.baviaanskloof.co.za">www.baviaanskloof.co.za</a></li>
</ul> <li>Fees: R150 per vehicle and R10 per person</li>
</li> </ul>
<li><strong>Kudu Kaya</strong> </li>
<ul> <li><strong>Kudu Kaya</strong>
<li>Contact: Heloise & Unola</li> <ul>
<li>Phone: 087 700 8195</li> <li>Contact: Heloise & Unola</li>
<li>Email: <a href="mailto:info@kudukaya.co.za">info@kudukaya.co.za</a></li> <li>Phone: 087 700 8195</li>
<li>Rates: Campsite per night R250 (2 people) plus additional adults R70 PPPN</li> <li>Email: <a href="mailto:info@kudukaya.co.za">info@kudukaya.co.za</a></li>
</ul> <li>Rates: Campsite per night R250 (2 people) plus additional adults R70 PPPN</li>
</li> </ul>
<li><strong>Kaboega</strong> </li>
<ul> <li><strong>Kaboega</strong>
<li>Contacts and rates on enquiry: <a href="mailto:kaboega@jabama.co.za">kaboega@jabama.co.za</a></li> <ul>
</ul> <li>Contacts and rates on enquiry: <a href="mailto:kaboega@jabama.co.za">kaboega@jabama.co.za</a></li>
</li> </ul>
<li><strong>Mountain Zebra National Park</strong> </li>
<ul> <li><strong>Mountain Zebra National Park</strong>
<li>Email: <a href="mailto:reservations@sanparks.org">reservations@sanparks.org</a></li> <ul>
<li>Phone: 012 428 9111</li> <li>Email: <a href="mailto:reservations@sanparks.org">reservations@sanparks.org</a></li>
</ul> <li>Phone: 012 428 9111</li>
</li> </ul>
</ul> </li>
</ul>
</div>
</div> </div>
</div>
<hr class="mb-45">
<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"> <div class="tag-share mb-50">
<h6>Tags </h6> <div class="item" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="tag-coulds"> <h6>Tags </h6>
<a href="blog.html">Travel</a> <div class="tag-coulds">
<a href="blog.html">Hotel</a> <a href="blog.html">Travel</a>
<a href="blog.html">Tour</a> <a href="blog.html">Hotel</a>
</div> <a href="blog.html">Tour</a>
</div> </div>
<!-- <div class="item" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> </div>
<h6>Share </h6> <!-- <div class="item" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<div class="social-style-one"> <h6>Share </h6>
<a href="#"><i class="fab fa-facebook-f"></i></a> <div class="social-style-one">
<a href="#"><i class="fab fa-twitter"></i></a> <a href="#"><i class="fab fa-facebook-f"></i></a>
<a href="#"><i class="fab fa-linkedin-in"></i></a> <a href="#"><i class="fab fa-twitter"></i></a>
<a href="#"><i class="fab fa-instagram"></i></a> <a href="#"><i class="fab fa-linkedin-in"></i></a>
</div> <a href="#"><i class="fab fa-instagram"></i></a>
</div> --> </div>
</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="admin-comment bgc-lighter" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="author-thumb"> <div class="comment-body">
<img src="assets/images/blog/admin-comment.jpg" alt="Author"> <div class="author-thumb">
</div> <img src="assets/images/blog/admin-comment.jpg" alt="Author">
<div class="content"> </div>
<h4>Richard M. Fudge</h4> <div class="content">
<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> <h4>Richard M. Fudge</h4>
<div class="social-icons"> <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>
<a href="contact.php"><i class="fab fa-facebook-f"></i></a> <div class="social-icons">
<a href="contact.php"><i class="fab fa-twitter"></i></a> <a href="contact"><i class="fab fa-facebook-f"></i></a>
<a href="contact.php"><i class="fab fa-linkedin-in"></i></a> <a href="contact"><i class="fab fa-twitter"></i></a>
<a href="contact.php"><i class="fab fa-instagram"></i></a> <a href="contact"><i class="fab fa-linkedin-in"></i></a>
</div> <a href="contact"><i class="fab fa-instagram"></i></a>
</div> </div>
</div> </div>
</div> --> </div>
</div> -->
<?php include_once('comment_box.php'); ?>
<?php include_once('comment_box.php'); ?>
</div>
<div class="col-lg-4 col-md-8 col-sm-10 rmt-75"> </div>
<div class="blog-sidebar"> <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"> <!-- <div class="widget widget-search" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<input type="text" placeholder="Search" required=""> <form action="#" class="default-search-form">
<button type="submit" class="searchbutton far fa-search"></button> <input type="text" placeholder="Search" required="">
</form> <button type="submit" class="searchbutton far fa-search"></button>
</div> --> </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> <!-- <div class="widget widget-category" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul class="list-style-three"> <h5 class="widget-title">Category</h5>
<li><a href="blog.html">Adventure</a></li> <ul class="list-style-three">
<li><a href="blog.html">Hiking & Trekking</a></li> <li><a href="blog.html">Adventure</a></li>
<li><a href="blog.html">Cycling Tours</a></li> <li><a href="blog.html">Hiking & Trekking</a></li>
<li><a href="blog.html">Family Tours</a></li> <li><a href="blog.html">Cycling Tours</a></li>
<li><a href="blog.html">Mountain Hiking</a></li> <li><a href="blog.html">Family Tours</a></li>
<li><a href="blog.html">Rafting Excursion</a></li> <li><a href="blog.html">Mountain Hiking</a></li>
<li><a href="blog.html">Coastal Paragliding</a></li> <li><a href="blog.html">Rafting Excursion</a></li>
</ul> <li><a href="blog.html">Coastal Paragliding</a></li>
</div> --> </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> <!-- <div class="widget widget-news" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul> <h5 class="widget-title">Recent News</h5>
<li> <ul>
<div class="image"> <li>
<img src="assets/images/widgets/news1.jpg" alt="News"> <div class="image">
</div> <img src="assets/images/widgets/news1.jpg" alt="News">
<div class="content"> </div>
<h6><a href="blog-details.html">Unique Destinations an tolded Stories ways</a></h6> <div class="content">
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <h6><a href="blog-details.html">Unique Destinations an tolded Stories ways</a></h6>
</div> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
</li> </div>
<li> </li>
<div class="image"> <li>
<img src="assets/images/widgets/news2.jpg" alt="News"> <div class="image">
</div> <img src="assets/images/widgets/news2.jpg" alt="News">
<div class="content"> </div>
<h6><a href="blog-details.html">Immersive Experiences from Around Globe</a></h6> <div class="content">
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <h6><a href="blog-details.html">Immersive Experiences from Around Globe</a></h6>
</div> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
</li> </div>
<li> </li>
<div class="image"> <li>
<img src="assets/images/widgets/news3.jpg" alt="News"> <div class="image">
</div> <img src="assets/images/widgets/news3.jpg" alt="News">
<div class="content"> </div>
<h6><a href="blog-details.html">Journey to Inspire Your Next Adventure</a></h6> <div class="content">
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <h6><a href="blog-details.html">Journey to Inspire Your Next Adventure</a></h6>
</div> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
</li> </div>
</ul> </li>
</div> --> </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="widget widget-gallery" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="gallery"> <h5 class="widget-title">Gallery</h5>
<?php <div class="gallery">
$folder = 'assets/images/blog/1/'; <?php
$files = glob($folder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $folder = 'assets/images/blog/1/';
shuffle($files); // Randomize the order $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;">'; foreach ($files as $file) {
echo '<img src="' . $file . '" alt="Gallery" style="width: 100%; height: 100%; object-fit: cover; display: block;">'; echo '<a href="' . $file . '" style="width: 110px; height: 110px; overflow: hidden; display: inline-block; margin: 2px;">';
echo '</a>'; echo '<img src="' . $file . '" alt="Gallery" style="width: 100%; height: 100%; object-fit: cover; display: block;">';
} echo '</a>';
?> }
</div> ?>
</div> </div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<!-- Blog Detaisl Area end --> </section>
<!-- Blog Detaisl Area end -->
<?php include_once("insta_footer.php"); ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,226 +1,228 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php') ?> $rootPath = dirname(dirname(dirname(__DIR__)));
include_once($rootPath . '/header.php');
<style> ?>
.image {
width: 400px; <style>
/* Set your desired width */ .image {
height: 350px; width: 400px;
/* Set your desired height */ /* Set your desired width */
overflow: hidden; height: 350px;
/* Hide any overflow */ /* Set your desired height */
display: block; overflow: hidden;
/* Ensure proper block behavior */ /* Hide any overflow */
} display: block;
/* Ensure proper block behavior */
.image img { }
width: 100%;
/* Image scales to fill the container */ .image img {
height: 100%; width: 100%;
/* Image scales to fill the container */ /* Image scales to fill the container */
object-fit: cover; height: 100%;
/* Fills the container while maintaining aspect ratio */ /* Image scales to fill the container */
object-position: top; object-fit: cover;
/* Aligns the top of the image with the top of the container */ /* Fills the container while maintaining aspect ratio */
display: block; object-position: top;
/* Prevents inline whitespace issues */ /* Aligns the top of the image with the top of the container */
display: block;
/* Prevents inline whitespace issues */
}
</style><?php
$pageTitle = 'Blogs'; }
$breadcrumbs = [['Home' => 'index.php']]; </style><?php
require_once('components/banner.php'); $pageTitle = 'Blogs';
?> $breadcrumbs = [['Home' => 'index.php']];
require_once($rootPath . '/components/banner.php');
?>
<!-- Blog List Area start -->
<section class="blog-list-page py-100 rel z-1">
<div class="container"> <!-- Blog List Area start -->
<div class="row"> <section class="blog-list-page py-100 rel z-1">
<div class="col-lg-8"> <div class="container">
<?php <div class="row">
// Query to retrieve data from blogs table <div class="col-lg-8">
$status = 'published'; <?php
$stmt = $conn->prepare("SELECT blog_id, title, date, category, image, description, author, members_only, link FROM blogs WHERE status = ? ORDER BY date DESC"); // Query to retrieve data from blogs table
$stmt->bind_param("s", $status); $status = 'published';
$stmt->execute(); $stmt = $conn->prepare("SELECT blog_id, title, date, category, image, description, author, members_only, link FROM blogs WHERE status = ? ORDER BY date DESC");
$result = $stmt->get_result(); $stmt->bind_param("s", $status);
$stmt->execute();
if ($result->num_rows > 0) { $result = $stmt->get_result();
// Loop through each row
while ($row = $result->fetch_assoc()) { if ($result->num_rows > 0) {
$blog_id = $row['blog_id']; // Loop through each row
$title = $row['title']; while ($row = $result->fetch_assoc()) {
$date = $row['date']; $blog_id = $row['blog_id'];
$category = $row['category']; $title = $row['title'];
$image = $row['image']; $date = $row['date'];
$description = $row['description']; $category = $row['category'];
$author = $row['author']; $image = $row['image'];
$blog_author = $row['author']; $description = $row['description'];
$members_only = $row['members_only']; $author = $row['author'];
if ($members_only) { $blog_author = $row['author'];
if (!isset($_SESSION['user_id'])) { $members_only = $row['members_only'];
$blog_link = "login.php"; if ($members_only) {
$button_hover = "Members Only"; if (!isset($_SESSION['user_id'])) {
$icon = "fa-lock"; $blog_link = "login.php";
} else { $button_hover = "Members Only";
if (getUserMemberStatus($_SESSION['user_id'])) { $icon = "fa-lock";
$blog_link = $row['link']; } else {
$button_hover = "Read More"; if (getUserMemberStatus($_SESSION['user_id'])) {
$icon = "fa-arrow-right"; $blog_link = $row['link'];
} else { $button_hover = "Read More";
$blog_link = "#"; $icon = "fa-arrow-right";
$button_hover = "Members Only"; } else {
$icon = "fa-lock"; $blog_link = "#";
} $button_hover = "Members Only";
} $icon = "fa-lock";
} else { }
$blog_link = $row['link']; }
$button_hover = "Read More"; } else {
$icon = "fa-arrow-right"; $blog_link = $row['link'];
} $button_hover = "Read More";
$icon = "fa-arrow-right";
// Output the HTML structure with dynamic data }
echo '
<div class="blog-item style-three" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> // Output the HTML structure with dynamic data
<div class="image"> echo '
<img style="border-radius:20px;" src="assets/images/blog/' . $blog_id . '/' . $image . '" alt="Blog List"> <div class="blog-item style-three" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
</div> <div class="image">
<div class="content"> <img style="border-radius:20px;" src="assets/images/blog/' . $blog_id . '/' . $image . '" alt="Blog List">
<a href="blog.php" class="category">' . $category . '</a> </div>
<h5><a href="' . $blog_link . '">' . $title . '</a></h5> <div class="content">
<ul class="blog-meta"> <a href="' . url('blog') . '" class="category">' . $category . '</a>
<li><i class="far fa-calendar-alt"></i> <a href="#">' . $date . '</a></li> <h5><a href="' . $blog_link . '">' . $title . '</a></h5>
<li><i class="far fa-user"></i> ' . getFullName($author) . '</li> <ul class="blog-meta">
</ul> <li><i class="far fa-calendar-alt"></i> <a href="#">' . $date . '</a></li>
<p>' . $description . '</p> <li><i class="far fa-user"></i> ' . getFullName($author) . '</li>
<a href="' . $blog_link . '" style="width:100%;" class="theme-btn style-two style-three"> </ul>
<span style="width:100%;" data-hover="'.$button_hover.'">Read More</span> <p>' . $description . '</p>
<i class="fal '.$icon.'"></i> <a href="' . $blog_link . '" style="width:100%;" class="theme-btn style-two style-three">
</a> <span style="width:100%;" data-hover="'.$button_hover.'">Read More</span>
</div> <i class="fal '.$icon.'"></i>
</div> </a>
</div>
'; </div>
}
} ?> ';
}
} ?>
<!-- <ul class="pagination pt-15 flex-wrap" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<li class="page-item disabled">
<span class="page-link"><i class="far fa-chevron-left"></i></span> <!-- <ul class="pagination pt-15 flex-wrap" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
</li> <li class="page-item disabled">
<li class="page-item active"> <span class="page-link"><i class="far fa-chevron-left"></i></span>
<span class="page-link"> </li>
1 <li class="page-item active">
<span class="sr-only">(current)</span> <span class="page-link">
</span> 1
</li> <span class="sr-only">(current)</span>
<li class="page-item"><a class="page-link" href="#">2</a></li> </span>
<li class="page-item"><a class="page-link" href="#">3</a></li> </li>
<li class="page-item"><a class="page-link" href="#">...</a></li> <li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"> <li class="page-item"><a class="page-link" href="#">3</a></li>
<a class="page-link" href="#"><i class="far fa-chevron-right"></i></a> <li class="page-item"><a class="page-link" href="#">...</a></li>
</li> <li class="page-item">
</ul> --> <a class="page-link" href="#"><i class="far fa-chevron-right"></i></a>
</div> </li>
<div class="col-lg-4 col-md-8 col-sm-10 rmt-75"> </ul> -->
<div class="blog-sidebar"> </div>
<div class="col-lg-4 col-md-8 col-sm-10 rmt-75">
<div class="widget widget-search" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="blog-sidebar">
<form action="#" class="default-search-form">
<input type="text" placeholder="Search" required=""> <div class="widget widget-search" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<button type="submit" class="searchbutton far fa-search"></button> <form action="#" class="default-search-form">
</form> <input type="text" placeholder="Search" required="">
</div> <button type="submit" class="searchbutton far fa-search"></button>
</form>
<!-- <div class="widget widget-category" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div>
<h5 class="widget-title">Category</h5>
<ul class="list-style-three"> <!-- <div class="widget widget-category" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<li><a href="blog.html">Adventure</a></li> <h5 class="widget-title">Category</h5>
<li><a href="blog.html">Hiking & Trekking</a></li> <ul class="list-style-three">
<li><a href="blog.html">Cycling Tours</a></li> <li><a href="blog.html">Adventure</a></li>
<li><a href="blog.html">Family Tours</a></li> <li><a href="blog.html">Hiking & Trekking</a></li>
<li><a href="blog.html">Mountain Hiking</a></li> <li><a href="blog.html">Cycling Tours</a></li>
<li><a href="blog.html">Rafting Excursion</a></li> <li><a href="blog.html">Family Tours</a></li>
<li><a href="blog.html">Coastal Paragliding</a></li> <li><a href="blog.html">Mountain Hiking</a></li>
</ul> <li><a href="blog.html">Rafting Excursion</a></li>
</div> --> <li><a href="blog.html">Coastal Paragliding</a></li>
</ul>
<!-- <div class="widget widget-news" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div> -->
<h5 class="widget-title">Recent News</h5>
<ul> <!-- <div class="widget widget-news" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<li> <h5 class="widget-title">Recent News</h5>
<div class="image"> <ul>
<img src="assets/images/widgets/news1.jpg" alt="News"> <li>
</div> <div class="image">
<div class="content"> <img src="assets/images/widgets/news1.jpg" alt="News">
<h6><a href="blog-details.html">Unique Destinations an tolded Stories ways</a></h6> </div>
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <div class="content">
</div> <h6><a href="blog-details.html">Unique Destinations an tolded Stories ways</a></h6>
</li> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
<li> </div>
<div class="image"> </li>
<img src="assets/images/widgets/news2.jpg" alt="News"> <li>
</div> <div class="image">
<div class="content"> <img src="assets/images/widgets/news2.jpg" alt="News">
<h6><a href="blog-details.html">Immersive Experiences from Around Globe</a></h6> </div>
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <div class="content">
</div> <h6><a href="blog-details.html">Immersive Experiences from Around Globe</a></h6>
</li> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
<li> </div>
<div class="image"> </li>
<img src="assets/images/widgets/news3.jpg" alt="News"> <li>
</div> <div class="image">
<div class="content"> <img src="assets/images/widgets/news3.jpg" alt="News">
<h6><a href="blog-details.html">Journey to Inspire Your Next Adventure</a></h6> </div>
<span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span> <div class="content">
</div> <h6><a href="blog-details.html">Journey to Inspire Your Next Adventure</a></h6>
</li> <span class="date"><i class="far fa-calendar-alt"></i> 25 Feb 2024</span>
</ul> </div>
</div> --> </li>
</ul>
<div class="widget widget-gallery" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div> -->
<h5 class="widget-title">Gallery</h5>
<div class="gallery"> <div class="widget widget-gallery" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<?php <h5 class="widget-title">Gallery</h5>
$folder = 'assets/images/blog/1/'; <div class="gallery">
$files = glob($folder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); <?php
shuffle($files); // Randomize the order $folder = 'assets/images/blog/1/';
$files = glob($folder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
foreach ($files as $file) { shuffle($files); // Randomize the order
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;">'; foreach ($files as $file) {
echo '</a>'; 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 class="widget widget-cta" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div>
<div class="content text-white">
<span class="h6">Explore The World</span> <div class="widget widget-cta" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<h3>Become a Member</h3> <div class="content text-white">
<a href="membership.php" class="theme-btn style-two bgc-secondary"> <span class="h6">Explore The World</span>
<span data-hover="Explore Now">Join Now</span> <h3>Become a Member</h3>
<i class="fal fa-arrow-right"></i> <a href="<?= url('membership') ?>" class="theme-btn style-two bgc-secondary">
</a> <span data-hover="Explore Now">Join Now</span>
</div> <i class="fal fa-arrow-right"></i>
<div class="image"> </a>
<img src="assets/images/logos/weblogo.png" alt="CTA"> </div>
</div> <div class="image">
<div class="cta-shape"><img src="assets/images/widgets/cta-shape.png" alt="Shape"></div> <img src="assets/images/logos/weblogo.png" alt="CTA">
</div> </div>
<div class="cta-shape"><img src="assets/images/widgets/cta-shape.png" alt="Shape"></div>
</div> </div>
</div> </div>
</div>
</div> </div>
</section> </div>
<!-- Blog List Area end --> </div>
</section>
<!-- Blog List Area end -->
<?php include_once("insta_footer.php"); ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

File diff suppressed because it is too large Load Diff

View File

@@ -1,194 +1,196 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php') ?> $rootPath = dirname(dirname(dirname(__DIR__)));
include_once($rootPath . '/header.php');
<style> ?>
.image {
width: 400px; <style>
/* Set your desired width */ .image {
height: 320px; width: 400px;
/* Set your desired height */ /* Set your desired width */
overflow: hidden; height: 320px;
/* Hide any overflow */ /* Set your desired height */
display: block; overflow: hidden;
/* Ensure proper block behavior */ /* Hide any overflow */
} display: block;
/* Ensure proper block behavior */
.image img { }
width: 100%;
/* Image scales to fill the container */ .image img {
height: 100%; width: 100%;
/* Image scales to fill the container */ /* Image scales to fill the container */
object-fit: cover; height: 100%;
/* Fills the container while maintaining aspect ratio */ /* Image scales to fill the container */
object-position: top; object-fit: cover;
/* Aligns the top of the image with the top of the container */ /* Fills the container while maintaining aspect ratio */
display: block; object-position: top;
/* Prevents inline whitespace issues */ /* Aligns the top of the image with the top of the container */
} display: block;
/* Prevents inline whitespace issues */
.custom-modal { }
display: none;
position: fixed; .custom-modal {
z-index: 9999; display: none;
left: 0; position: fixed;
top: 0; z-index: 9999;
width: 100%; left: 0;
height: 100%; top: 0;
overflow: auto; width: 100%;
background-color: rgba(0, 0, 0, 0.9); height: 100%;
} overflow: auto;
background-color: rgba(0, 0, 0, 0.9);
.custom-modal-content { }
margin: 5% auto;
padding: 20px; .custom-modal-content {
max-width: 800px; margin: 5% auto;
text-align: center; padding: 20px;
background: #fff; max-width: 800px;
border-radius: 10px; text-align: center;
position: relative; background: #fff;
} border-radius: 10px;
position: relative;
.custom-modal-content img { }
max-width: 100%;
height: auto; .custom-modal-content img {
border-radius: 5px; max-width: 100%;
} height: auto;
</style> border-radius: 5px;
}
<?php </style>
$pageTitle = 'Events';
$breadcrumbs = [['Home' => 'index.php']]; <?php
require_once('components/banner.php'); $pageTitle = 'Events';
?> $breadcrumbs = [['Home' => 'index.php']];
require_once($rootPath . '/components/banner.php');
<!-- Tour List Area start --> ?>
<section class="tour-list-page py-100 rel z-1">
<div class="container"> <!-- Tour List Area start -->
<div class="row"> <section class="tour-list-page py-100 rel z-1">
<div class="container">
<div class="col-lg-12"> <div class="row">
<div class="shop-shorter rel z-3 mb-20">
<!-- <ul class="grid-list mb-15 me-2"> <div class="col-lg-12">
<li><a href="#"><i class="fal fa-border-all"></i></a></li> <div class="shop-shorter rel z-3 mb-20">
<li><a href="#"><i class="far fa-list"></i></a></li> <!-- <ul class="grid-list mb-15 me-2">
</ul> <li><a href="#"><i class="fal fa-border-all"></i></a></li>
<div class="sort-text mb-15 me-4 me-xl-auto"> <li><a href="#"><i class="far fa-list"></i></a></li>
</div> --> </ul>
<div class="sort-text mb-15 me-4"> <div class="sort-text mb-15 me-4 me-xl-auto">
Sort By </div> -->
</div> <div class="sort-text mb-15 me-4">
<select> Sort By
<option value="default" selected="">Sort By</option> </div>
<option value="new">Newness</option> <select>
<option value="old">Oldest</option> <option value="default" selected="">Sort By</option>
<option value="hight-to-low">High To Low</option> <option value="new">Newness</option>
<option value="low-to-high">Low To High</option> <option value="old">Oldest</option>
</select> <option value="hight-to-low">High To Low</option>
</div> <option value="low-to-high">Low To High</option>
</select>
<?php </div>
// Query to retrieve upcoming events
$stmt = $conn->prepare("SELECT event_id, date, time, name, image, description, feature, location, type, promo FROM events WHERE date > CURDATE() ORDER BY date ASC"); <?php
$stmt->execute(); // Query to retrieve upcoming events
$result = $stmt->get_result(); $stmt = $conn->prepare("SELECT event_id, date, time, name, image, description, feature, location, type, promo FROM events WHERE date > CURDATE() ORDER BY date ASC");
$stmt->execute();
if ($result->num_rows > 0) { $result = $stmt->get_result();
// Loop through each row
while ($row = $result->fetch_assoc()) { if ($result->num_rows > 0) {
$event_id = $row['event_id']; // Loop through each row
$date = $row['date']; while ($row = $result->fetch_assoc()) {
$time = $row['time']; $event_id = $row['event_id'];
$name = $row['name']; $date = $row['date'];
$image = $row['image']; $time = $row['time'];
$description = $row['description']; $name = $row['name'];
$feature = $row['feature']; $image = $row['image'];
$location = $row['location']; $description = $row['description'];
$type = $row['type']; $feature = $row['feature'];
$promo = $row['promo']; $location = $row['location'];
$type = $row['type'];
// Determine the badge text based on the status $promo = $row['promo'];
$badge_text = 'OPEN DAY';
// Determine the badge text based on the status
// Output the HTML structure with dynamic data $badge_text = 'OPEN DAY';
echo '
<div class="destination-item style-three bgc-lighter" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> // Output the HTML structure with dynamic data
<div class="image"> echo '
<img src="' . $image . '" alt="' . $name . '"> <div class="destination-item style-three bgc-lighter" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
</div> <div class="image">
<div class="content"> <img src="' . $image . '" alt="' . $name . '">
<div class="destination-header"> </div>
<span class="location"><i class="fal fa-map-marker-alt"></i> ' . $location . '</span> <div class="content">
</div> <div class="destination-header">
<h5>' . $name . '</a></h5> <span class="location"><i class="fal fa-map-marker-alt"></i> ' . $location . '</span>
<p>' . $feature . '</p> </div>
<p>' . $description . '</p> <h5>' . $name . '</a></h5>
<ul class="blog-meta"> <p>' . $feature . '</p>
<li><i class="far fa-calendar"></i> ' . convertDate($date) . '</li> <p>' . $description . '</p>
<li><i class="far fa-clock"></i> ' . $time . '</li> <ul class="blog-meta">
</ul> <li><i class="far fa-calendar"></i> ' . convertDate($date) . '</li>
<button type="button" class="theme-btn style-three view-image-btn" style="padding: 2px 20px" <li><i class="far fa-clock"></i> ' . $time . '</li>
data-image-src="' . $promo . '" </ul>
data-image-title="' . htmlspecialchars($name, ENT_QUOTES) . '"> <button type="button" class="theme-btn style-three view-image-btn" style="padding: 2px 20px"
View Promo data-image-src="' . $promo . '"
</button> data-image-title="' . htmlspecialchars($name, ENT_QUOTES) . '">
View Promo
</div> </button>
</div>';
} </div>
} else { </div>';
echo "No events available."; }
} } else {
echo "No events available.";
// Close connection }
$conn->close();
?> // Close connection
$conn->close();
?>
</div>
</div>
</div> </div>
</section> </div>
<!-- Tour List Area end --> </div>
<!-- Custom Image Modal --> </section>
<div id="customImageModal" class="custom-modal"> <!-- Tour List Area end -->
<div class="custom-modal-content"> <!-- Custom Image Modal -->
<span class="custom-modal-close">&times;</span> <div id="customImageModal" class="custom-modal">
<h5 id="modalImageTitle"></h5> <div class="custom-modal-content">
<img id="modalImageElement" src="" alt="" class="img-fluid"> <span class="custom-modal-close">&times;</span>
</div> <h5 id="modalImageTitle"></h5>
</div> <img id="modalImageElement" src="" alt="" class="img-fluid">
<script> </div>
document.addEventListener("DOMContentLoaded", function() { </div>
const modal = document.getElementById("customImageModal"); <script>
const modalImg = document.getElementById("modalImageElement"); document.addEventListener("DOMContentLoaded", function() {
const modalTitle = document.getElementById("modalImageTitle"); const modal = document.getElementById("customImageModal");
const closeBtn = document.querySelector(".custom-modal-close"); const modalImg = document.getElementById("modalImageElement");
const modalTitle = document.getElementById("modalImageTitle");
document.querySelectorAll(".view-image-btn").forEach(button => { const closeBtn = document.querySelector(".custom-modal-close");
button.addEventListener("click", () => {
const src = button.getAttribute("data-image-src"); document.querySelectorAll(".view-image-btn").forEach(button => {
const title = button.getAttribute("data-image-title"); button.addEventListener("click", () => {
modalImg.src = src; const src = button.getAttribute("data-image-src");
modalTitle.textContent = title; const title = button.getAttribute("data-image-title");
modal.style.display = "block"; modalImg.src = src;
}); modalTitle.textContent = title;
}); modal.style.display = "block";
});
closeBtn.addEventListener("click", () => { });
modal.style.display = "none";
modalImg.src = ""; closeBtn.addEventListener("click", () => {
}); modal.style.display = "none";
modalImg.src = "";
// Optional: click outside modal to close });
window.addEventListener("click", (e) => {
if (e.target === modal) { // Optional: click outside modal to close
modal.style.display = "none"; window.addEventListener("click", (e) => {
modalImg.src = ""; if (e.target === modal) {
} modal.style.display = "none";
}); modalImg.src = "";
}); }
</script> });
});
</script>
<?php include_once("insta_footer.php"); ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,55 +1,55 @@
<?php <?php
// Instagram Access Token // Instagram Access Token
$accessToken = 'IGQWRPZADdZAUGtMM2NyZADJVSERoSUZA6bVVBV3lKY0dJbWlEcGVvaVYySDViMHMwSkFBQXRVWVQ1ZA080MkRJd0pzYndjWFVTRmtrenBvRml6Vy03NGZAPQ1pROWNKVkJoMTZAid0lIM2htejc3czByajYwMmJHWTBMMTgZD'; $accessToken = 'IGQWRPZADdZAUGtMM2NyZADJVSERoSUZA6bVVBV3lKY0dJbWlEcGVvaVYySDViMHMwSkFBQXRVWVQ1ZA080MkRJd0pzYndjWFVTRmtrenBvRml6Vy03NGZAPQ1pROWNKVkJoMTZAid0lIM2htejc3czByajYwMmJHWTBMMTgZD';
// Instagram API URL to fetch recent media posts // Instagram API URL to fetch recent media posts
$apiUrl = 'https://graph.instagram.com/me/media?fields=id,caption,media_url,thumbnail_url,permalink,media_type&limit=6&access_token=' . $accessToken; $apiUrl = 'https://graph.instagram.com/me/media?fields=id,caption,media_url,thumbnail_url,permalink,media_type&limit=6&access_token=' . $accessToken;
// Initialize cURL // Initialize cURL
$ch = curl_init(); $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl); curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch); $response = curl_exec($ch);
curl_close($ch); curl_close($ch);
// Decode the JSON response // Decode the JSON response
$instaFeed = json_decode($response); $instaFeed = json_decode($response);
?> ?>
<style> <style>
.insta-post { .insta-post {
display: inline-block; display: inline-block;
margin: 10px; margin: 10px;
} }
.insta-post img { .insta-post img {
width: 200px; width: 200px;
height: 200px; height: 200px;
overflow: hidden; overflow: hidden;
border-radius: 10px; border-radius: 10px;
} }
</style> </style>
<div class="container"> <div class="container">
<div class="footer-instagram pt-100"> <div class="footer-instagram pt-100">
<div class="row row-cols-xxl-6 row-cols-xl-5 row-cols-lg-4 row-cols-md-3 row-cols-2"> <div class="row row-cols-xxl-6 row-cols-xl-5 row-cols-lg-4 row-cols-md-3 row-cols-2">
<?php <?php
// echo "TEST"; // echo "TEST";
// Loop through the media and display them // Loop through the media and display them
if (!empty($instaFeed->data)) { if (!empty($instaFeed->data)) {
foreach ($instaFeed->data as $post) { foreach ($instaFeed->data as $post) {
// Check if it's an image post // Check if it's an image post
if ($post->media_type == 'IMAGE' || $post->media_type == 'CAROUSEL_ALBUM') { if ($post->media_type == 'IMAGE' || $post->media_type == 'CAROUSEL_ALBUM') {
echo "<div class='col' data-aos='zoom-in-up' data-aos-duration='1500' data-aos-offset='50'>"; echo "<div class='col' data-aos='zoom-in-up' data-aos-duration='1500' data-aos-offset='50'>";
echo "<a class='insta-post' href='" . $post->permalink . "' target='_blank'>"; echo "<a class='insta-post' href='" . $post->permalink . "' target='_blank'>";
echo "<img src='" . $post->media_url . "' alt='" . htmlspecialchars($post->caption) . "'>"; echo "<img src='" . $post->media_url . "' alt='" . htmlspecialchars($post->caption) . "'>";
echo "</a>"; echo "</a>";
echo "</div>"; echo "</div>";
} }
} }
} }
?> ?>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,6 @@
<?php <?php
include_once('header02.php'); $headerStyle = 'light';
include_once(dirname(dirname(dirname(__DIR__))) . '/header.php');
checkAdmin(); checkAdmin();
if (!isset($_GET['token']) || empty($_GET['token'])) { if (!isset($_GET['token']) || empty($_GET['token'])) {
die("Invalid request."); die("Invalid request.");
@@ -277,4 +278,4 @@ $stmt->close();
</script> </script>
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,73 +1,73 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); include_once(dirname(dirname(dirname(__DIR__))) . '/header.php');
// Assuming you have the user ID stored in the session // Assuming you have the user ID stored in the session
if (isset($_SESSION['user_id'])) { if (isset($_SESSION['user_id']) && isset($conn) && $conn !== null) {
$user_id = $_SESSION['user_id']; $user_id = $_SESSION['user_id'];
} // Fetch user data from the database
$sql = "SELECT * FROM users WHERE user_id = ?";
// Fetch user data from the database $stmt = $conn->prepare($sql);
$stmt->bind_param("i", $user_id);
$sql = "SELECT * FROM users WHERE user_id = ?"; $stmt->execute();
$stmt = $conn->prepare($sql); $result = $stmt->get_result();
$stmt->bind_param("i", $user_id); $user = $result->fetch_assoc();
$stmt->execute(); } else {
$result = $stmt->get_result(); $user = null;
$user = $result->fetch_assoc(); }
?><?php ?><?php
$pageTitle = 'Membership'; $pageTitle = 'Membership';
$breadcrumbs = [['Home' => 'index.php']]; $breadcrumbs = [['Home' => 'index.php']];
require_once('components/banner.php'); require_once(dirname(dirname(dirname(__DIR__))) . '/components/banner.php');
?> ?>
<!-- Contact Form Area start --> <!-- Contact Form Area start -->
<section class="about-us-area py-100 rpb-90 rel z-1"> <section class="about-us-area py-100 rpb-90 rel z-1">
<div class="container"> <div class="container">
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col-xl-5 col-lg-6"> <div class="col-xl-5 col-lg-6">
<div class="about-us-content rmb-55" data-aos="fade-left" data-aos-duration="1500" <div class="about-us-content rmb-55" data-aos="fade-left" data-aos-duration="1500"
data-aos-offset="50"> data-aos-offset="50">
<div class="section-title mb-25"> <div class="section-title mb-25">
<h2>Become a member of 4WDCSA</h2> <h2>Become a member of 4WDCSA</h2>
<p>Sign up for an annual membership and receive:</p> <p>Sign up for an annual membership and receive:</p>
<ul class="list-style-two mt-35 mb-30"> <ul class="list-style-two mt-35 mb-30">
<li>Year round access to BASE4</li> <li>Year round access to BASE4</li>
<li>FREE Camping at BASE4</li> <li>FREE Camping at BASE4</li>
<li>Up to 95% Discount on Training Courses</li> <li>Up to 95% Discount on Training Courses</li>
<li>Exclusive Member discounts for all trips and events</li> <li>Exclusive Member discounts for all trips and events</li>
<li>... and many more!</li> <li>... and many more!</li>
</ul> </ul>
</div> </div>
<h2>R 2,500/year</h2> <h2>R 2,500/year</h2>
<p>We go above and beyond to make your travel dreams reality hidden gems and must-see <p>We go above and beyond to make your travel dreams reality hidden gems and must-see
attractions</p> attractions</p>
<a href="membership_application.php" class="theme-btn mt-10 style-two"> <a href="membership_application" class="theme-btn mt-10 style-two">
<span data-hover="Start Application">Start Application</span> <span data-hover="Start Application">Start Application</span>
<i class="fal fa-arrow-right"></i> <i class="fal fa-arrow-right"></i>
</a> </a>
</div> </div>
</div> </div>
<div class="col-xl-7 col-lg-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <div class="col-xl-7 col-lg-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<div class="about-us-image"> <div class="about-us-image">
<!-- <div class="shape"><img src="assets/images/about/shape1.png" alt="Shape"></div> <!-- <div class="shape"><img src="assets/images/about/shape1.png" alt="Shape"></div>
<div class="shape"><img src="assets/images/about/shape2.png" alt="Shape"></div> <div class="shape"><img src="assets/images/about/shape2.png" alt="Shape"></div>
<div class="shape"><img src="assets/images/about/shape3.png" alt="Shape"></div> <div class="shape"><img src="assets/images/about/shape3.png" alt="Shape"></div>
<div class="shape"><img src="assets/images/about/shape4.png" alt="Shape"></div> <div class="shape"><img src="assets/images/about/shape4.png" alt="Shape"></div>
<div class="shape"><img src="assets/images/about/shape5.png" alt="Shape"></div> <div class="shape"><img src="assets/images/about/shape5.png" alt="Shape"></div>
<div class="shape"><img src="assets/images/about/shape6.png" alt="Shape"></div> <div class="shape"><img src="assets/images/about/shape6.png" alt="Shape"></div>
<div class="shape"><img src="assets/images/about/shape7.png" alt="Shape"></div> --> <div class="shape"><img src="assets/images/about/shape7.png" alt="Shape"></div> -->
<img src="assets/images/logos/weblogo.png" alt="About"> <img src="assets/images/logos/weblogo.png" alt="About">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,283 +1,284 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
checkUserSession(); include_once($rootPath . '/header.php');
checkUserSession();
// Assuming you have the user ID stored in the session
if (isset($_SESSION['user_id'])) { // Assuming you have the user ID stored in the session
$user_id = $_SESSION['user_id']; if (isset($_SESSION['user_id'])) {
}else{ $user_id = $_SESSION['user_id'];
header('Location: login.php'); }else{
exit(); // Stop further script execution header('Location: login.php');
} exit(); // Stop further script execution
}
checkMembershipApplication($user_id);
// Fetch user data from the database checkMembershipApplication($user_id);
// Fetch user data from the database
$sql = "SELECT * FROM users WHERE user_id = ?";
$stmt = $conn->prepare($sql); $sql = "SELECT * FROM users WHERE user_id = ?";
$stmt->bind_param("i", $user_id); $stmt = $conn->prepare($sql);
$stmt->execute(); $stmt->bind_param("i", $user_id);
$result = $stmt->get_result(); $stmt->execute();
$user = $result->fetch_assoc(); $result = $stmt->get_result();
$user = $result->fetch_assoc();
?><?php ?><?php
$pageTitle = 'Membership Application'; $pageTitle = 'Membership Application';
$breadcrumbs = [['Home' => 'index.php'], ['Membership' => 'membership.php']]; $breadcrumbs = [['Home' => 'index.php'], ['Membership' => 'membership.php']];
require_once('components/banner.php'); require_once($rootPath . '/components/banner.php');
?> ?>
<section class="contact-form-area py-70 rel z-1"> <section class="contact-form-area py-70 rel z-1">
<div class="container"> <div class="container">
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55"> <div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
<form id="registerForm" name="registerForm" action="process_application.php" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <form id="registerForm" name="registerForm" action="process_application" method="post" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<div class="section-title"> <div class="section-title">
<div id="responseMessage"></div> <!-- Message display area --> <div id="responseMessage"></div> <!-- Message display area -->
</div> </div>
<!-- Personal Details Section --> <!-- Personal Details Section -->
<h3>Main Member</h3> <h3>Main Member</h3>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="first_name">First Name*</label> <label for="first_name">First Name*</label>
<input type="text" id="first_name" name="first_name" class="form-control" placeholder="John" value="<?php echo $user['first_name']; ?>" required> <input type="text" id="first_name" name="first_name" class="form-control" placeholder="John" value="<?php echo $user['first_name']; ?>" required>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="last_name">Surname*</label> <label for="last_name">Surname*</label>
<input type="text" id="last_name" name="last_name" class="form-control" placeholder="Smith" value="<?php echo $user['last_name']; ?>" required> <input type="text" id="last_name" name="last_name" class="form-control" placeholder="Smith" value="<?php echo $user['last_name']; ?>" required>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="id_number">ID Number / Passport Number*</label> <label for="id_number">ID Number / Passport Number*</label>
<input type="text" id="id_number" name="id_number" class="form-control" placeholder="1234567890" required> <input type="text" id="id_number" name="id_number" class="form-control" placeholder="1234567890" required>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="dob">Date of Birth*</label> <label for="dob">Date of Birth*</label>
<input type="date" id="dob" name="dob" class="form-control" required> <input type="date" id="dob" name="dob" class="form-control" required>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="form-group"> <div class="form-group">
<label for="occupation">Occupation*</label> <label for="occupation">Occupation*</label>
<input type="text" id="occupation" name="occupation" class="form-control" placeholder="Occupation" required> <input type="text" id="occupation" name="occupation" class="form-control" placeholder="Occupation" required>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="form-group"> <div class="form-group">
<label for="phone_numbers">Cell Phone*</label> <label for="phone_numbers">Cell Phone*</label>
<input type="text" id="tel_cell" name="tel_cell" class="form-control" placeholder="Cell Phone" value="<?php echo $user['phone_number']; ?>" required> <input type="text" id="tel_cell" name="tel_cell" class="form-control" placeholder="Cell Phone" value="<?php echo $user['phone_number']; ?>" required>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="form-group"> <div class="form-group">
<label for="email">Email Address*</label> <label for="email">Email Address*</label>
<input type="email" id="email" name="email" class="form-control" placeholder="Enter email" value="<?php echo $user['email']; ?>" required> <input type="email" id="email" name="email" class="form-control" placeholder="Enter email" value="<?php echo $user['email']; ?>" required>
</div> </div>
</div> </div>
</div> </div>
<!-- Spouse / Partner Details Section --> <!-- Spouse / Partner Details Section -->
<h3>Spouse / Life Partner / Other Details</h3> <h3>Spouse / Life Partner / Other Details</h3>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="spouse_first_name">First Name</label> <label for="spouse_first_name">First Name</label>
<input type="text" id="spouse_first_name" name="spouse_first_name" class="form-control" placeholder="Jane"> <input type="text" id="spouse_first_name" name="spouse_first_name" class="form-control" placeholder="Jane">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="spouse_last_name">Surname</label> <label for="spouse_last_name">Surname</label>
<input type="text" id="spouse_last_name" name="spouse_last_name" class="form-control" placeholder="Smith"> <input type="text" id="spouse_last_name" name="spouse_last_name" class="form-control" placeholder="Smith">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="spouse_id_number">ID Number / Passport Number</label> <label for="spouse_id_number">ID Number / Passport Number</label>
<input type="text" id="spouse_id_number" name="spouse_id_number" class="form-control" placeholder="1234567890"> <input type="text" id="spouse_id_number" name="spouse_id_number" class="form-control" placeholder="1234567890">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="spouse_dob">Date of Birth</label> <label for="spouse_dob">Date of Birth</label>
<input type="date" id="spouse_dob" name="spouse_dob" class="form-control"> <input type="date" id="spouse_dob" name="spouse_dob" class="form-control">
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="form-group"> <div class="form-group">
<label for="spouse_occupation">Occupation</label> <label for="spouse_occupation">Occupation</label>
<input type="text" id="spouse_occupation" name="spouse_occupation" class="form-control" placeholder="Occupation"> <input type="text" id="spouse_occupation" name="spouse_occupation" class="form-control" placeholder="Occupation">
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="form-group"> <div class="form-group">
<label for="spouse_phone_numbers">Cell Phone</label> <label for="spouse_phone_numbers">Cell Phone</label>
<input type="text" id="spouse_tel_cell" name="spouse_tel_cell" class="form-control" placeholder="Cell Phone"> <input type="text" id="spouse_tel_cell" name="spouse_tel_cell" class="form-control" placeholder="Cell Phone">
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="form-group"> <div class="form-group">
<label for="spouse_email">Email Address</label> <label for="spouse_email">Email Address</label>
<input type="email" id="spouse_email" name="spouse_email" class="form-control" placeholder="Enter email"> <input type="email" id="spouse_email" name="spouse_email" class="form-control" placeholder="Enter email">
</div> </div>
</div> </div>
</div> </div>
<!-- Children Section --> <!-- Children Section -->
<h3>Children's Names</h3> <h3>Children's Names</h3>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="child_name1">Child 1 Name</label> <label for="child_name1">Child 1 Name</label>
<input type="text" id="child_name1" name="child_name1" class="form-control" placeholder="Child 1 Name"> <input type="text" id="child_name1" name="child_name1" class="form-control" placeholder="Child 1 Name">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="child_dob1">Child 1 DOB</label> <label for="child_dob1">Child 1 DOB</label>
<input type="date" id="child_dob1" name="child_dob1" class="form-control"> <input type="date" id="child_dob1" name="child_dob1" class="form-control">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="child_name2">Child 2 Name</label> <label for="child_name2">Child 2 Name</label>
<input type="text" id="child_name2" name="child_name2" class="form-control" placeholder="Child 2 Name"> <input type="text" id="child_name2" name="child_name2" class="form-control" placeholder="Child 2 Name">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="child_dob2">Child 2 DOB</label> <label for="child_dob2">Child 2 DOB</label>
<input type="date" id="child_dob2" name="child_dob2" class="form-control"> <input type="date" id="child_dob2" name="child_dob2" class="form-control">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="child_name3">Child 3 Name</label> <label for="child_name3">Child 3 Name</label>
<input type="text" id="child_name3" name="child_name3" class="form-control" placeholder="Child 3 Name"> <input type="text" id="child_name3" name="child_name3" class="form-control" placeholder="Child 3 Name">
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="child_dob3">Child 3 DOB</label> <label for="child_dob3">Child 3 DOB</label>
<input type="date" id="child_dob3" name="child_dob3" class="form-control"> <input type="date" id="child_dob3" name="child_dob3" class="form-control">
</div> </div>
</div> </div>
<!-- Repeat for other children if needed --> <!-- Repeat for other children if needed -->
</div> </div>
<!-- Address Section --> <!-- Address Section -->
<h3>Address</h3> <h3>Address</h3>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="physical_address">Physical Address</label> <label for="physical_address">Physical Address</label>
<textarea id="physical_address" name="physical_address" class="form-control" placeholder="Enter physical address"></textarea> <textarea id="physical_address" name="physical_address" class="form-control" placeholder="Enter physical address"></textarea>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="postal_address">Postal Address</label> <label for="postal_address">Postal Address</label>
<textarea id="postal_address" name="postal_address" class="form-control" placeholder="Enter postal address"></textarea> <textarea id="postal_address" name="postal_address" class="form-control" placeholder="Enter postal address"></textarea>
</div> </div>
</div> </div>
</div> </div>
<!-- Interests Section --> <!-- Interests Section -->
<h3>Interests and Hobbies</h3> <h3>Interests and Hobbies</h3>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<textarea id="interests_hobbies" name="interests_hobbies" class="form-control" placeholder="Enter interests and hobbies"></textarea> <textarea id="interests_hobbies" name="interests_hobbies" class="form-control" placeholder="Enter interests and hobbies"></textarea>
</div> </div>
</div> </div>
</div> </div>
<!-- Vehicle Section --> <!-- Vehicle Section -->
<h3>Primary Vehicle</h3> <h3>Primary Vehicle</h3>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-3"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label for="vehicle_make">Make</label> <label for="vehicle_make">Make</label>
<input type="text" id="vehicle_make" name="vehicle_make" class="form-control" placeholder="Vehicle Make"> <input type="text" id="vehicle_make" name="vehicle_make" class="form-control" placeholder="Vehicle Make">
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label for="vehicle_model">Model</label> <label for="vehicle_model">Model</label>
<input type="text" id="vehicle_model" name="vehicle_model" class="form-control" placeholder="Vehicle Model"> <input type="text" id="vehicle_model" name="vehicle_model" class="form-control" placeholder="Vehicle Model">
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label for="vehicle_year">Year</label> <label for="vehicle_year">Year</label>
<input type="text" id="vehicle_year" name="vehicle_year" class="form-control" placeholder="Vehicle Year"> <input type="text" id="vehicle_year" name="vehicle_year" class="form-control" placeholder="Vehicle Year">
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label for="vehicle_registration">Registration</label> <label for="vehicle_registration">Registration</label>
<input type="text" id="vehicle_registration" name="vehicle_registration" class="form-control" placeholder="Vehicle Registration"> <input type="text" id="vehicle_registration" name="vehicle_registration" class="form-control" placeholder="Vehicle Registration">
</div> </div>
</div> </div>
</div> </div>
<h3>Secondary Vehicle</h3> <h3>Secondary Vehicle</h3>
<div class="row mt-35"> <div class="row mt-35">
<div class="col-md-3"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label for="secondary_vehicle_make">Make</label> <label for="secondary_vehicle_make">Make</label>
<input type="text" id="secondary_vehicle_make" name="secondary_vehicle_make" class="form-control" placeholder="Vehicle Make"> <input type="text" id="secondary_vehicle_make" name="secondary_vehicle_make" class="form-control" placeholder="Vehicle Make">
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label for="secondary_vehicle_model">Model</label> <label for="secondary_vehicle_model">Model</label>
<input type="text" id="secondary_vehicle_model" name="secondary_vehicle_model" class="form-control" placeholder="Vehicle Model"> <input type="text" id="secondary_vehicle_model" name="secondary_vehicle_model" class="form-control" placeholder="Vehicle Model">
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label for="secondary_vehicle_year">Year</label> <label for="secondary_vehicle_year">Year</label>
<input type="text" id="secondary_vehicle_year" name="secondary_vehicle_year" class="form-control" placeholder="Vehicle Year"> <input type="text" id="secondary_vehicle_year" name="secondary_vehicle_year" class="form-control" placeholder="Vehicle Year">
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label for="secondary_vehicle_registration">Registration</label> <label for="secondary_vehicle_registration">Registration</label>
<input type="text" id="secondary_vehicle_registration" name="secondary_vehicle_registration" class="form-control" placeholder="Vehicle Registration"> <input type="text" id="secondary_vehicle_registration" name="secondary_vehicle_registration" class="form-control" placeholder="Vehicle Registration">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Submit Section --> <!-- Submit Section -->
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
<button type="submit" class="theme-btn style-two" style="width:100%;">Next</button> <button type="submit" class="theme-btn style-two" style="width:100%;">Next</button>
<div id="msgSubmit" class="hidden"></div> <div id="msgSubmit" class="hidden"></div>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Contact Form Area end --> <!-- Contact Form Area end -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,104 +1,105 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
// Assuming you have the user ID stored in the session include_once($rootPath . '/header.php');
if (isset($_SESSION['user_id'])) { // Assuming you have the user ID stored in the session
$user_id = $_SESSION['user_id']; if (isset($_SESSION['user_id'])) {
} else { $user_id = $_SESSION['user_id'];
header('Location: login.php'); } else {
exit(); // Stop further script execution header('Location: login.php');
} exit(); // Stop further script execution
}
// Initialize variables
$payment_amount = null; // Initialize variables
$membership_start_date = null; $payment_amount = null;
$membership_end_date = null; $membership_start_date = null;
$membership_end_date = null;
// Get the user_id from the session
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null; // Get the user_id from the session
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
if ($user_id) {
// Prepare the SQL query to fetch data if ($user_id) {
$query = "SELECT payment_amount, membership_start_date, membership_end_date, payment_id // Prepare the SQL query to fetch data
FROM membership_fees $query = "SELECT payment_amount, membership_start_date, membership_end_date, payment_id
WHERE user_id = ?"; FROM membership_fees
WHERE user_id = ?";
if ($stmt = $conn->prepare($query)) {
// Bind the user_id parameter to the query if ($stmt = $conn->prepare($query)) {
$stmt->bind_param("i", $user_id); // Bind the user_id parameter to the query
$stmt->bind_param("i", $user_id);
// Execute the query
$stmt->execute(); // Execute the query
$stmt->execute();
// Bind the results to variables
$stmt->bind_result($payment_amount, $membership_start_date, $membership_end_date, $eft_id); // Bind the results to variables
$stmt->bind_result($payment_amount, $membership_start_date, $membership_end_date, $eft_id);
// Fetch the data
if ($stmt->fetch()) { // Fetch the data
// Values are now assigned to $payment_amount, $membership_start_date, and $membership_end_date if ($stmt->fetch()) {
} else { // Values are now assigned to $payment_amount, $membership_start_date, and $membership_end_date
// Handle case where no records are found } else {
$error_message = "No records found for the given user ID."; // Handle case where no records are found
} $error_message = "No records found for the given user ID.";
}
// Close the statement
$stmt->close(); // Close the statement
} else { $stmt->close();
// Handle query preparation failure } else {
$error_message = "Query preparation failed: " . $conn->error; // Handle query preparation failure
} $error_message = "Query preparation failed: " . $conn->error;
} else { }
// Handle case where user_id is not found in session } else {
$error_message = "User ID not found in session."; // Handle case where user_id is not found in session
} $error_message = "User ID not found in session.";
}
// Get user's email
$sql = "SELECT email FROM users WHERE user_id = ?"; // Get user's email
$stmt = $conn->prepare($sql); $sql = "SELECT email FROM users WHERE user_id = ?";
$stmt = $conn->prepare($sql);
if (!$stmt) {
die("Prepare failed: " . $conn->error); if (!$stmt) {
} die("Prepare failed: " . $conn->error);
}
$stmt->bind_param("i", $user_id);
$stmt->execute(); $stmt->bind_param("i", $user_id);
$stmt->bind_result($user_email); $stmt->execute();
$stmt->fetch(); $stmt->bind_result($user_email);
$stmt->close(); $stmt->fetch();
$stmt->close();
$conn->close();
$conn->close();
?><?php ?><?php
$pageTitle = 'Membership Payment'; $pageTitle = 'Membership Payment';
$breadcrumbs = [['Home' => 'index.php'], ['Membership' => 'membership.php']]; $breadcrumbs = [['Home' => 'index.php'], ['Membership' => 'membership.php']];
require_once('components/banner.php'); require_once($rootPath . '/components/banner.php');
?> ?>
<!-- Contact Form Area start --> <!-- Contact Form Area start -->
<section class="about-us-area py-100 rpb-90 rel z-1"> <section class="about-us-area py-100 rpb-90 rel z-1">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-lg-6"> <div class="col-lg-6">
<div class="section-title mb-25"> <div class="section-title mb-25">
<span class="h2 mb-15">New Membership Payment:</span> <span class="h2 mb-15">New Membership Payment:</span>
<?php echo <?php echo
'<h5>Membership Start Date: ' . $membership_start_date . '<br>Membership Renewal Date: ' . $membership_end_date . '</h5>'; ?> '<h5>Membership Start Date: ' . $membership_start_date . '<br>Membership Renewal Date: ' . $membership_end_date . '</h5>'; ?>
</div> </div>
<p>Your invoice has been sent to <b><?php echo htmlspecialchars($user_email); ?></b>. Please upload your proof of payment below.</p> <p>Your invoice has been sent to <b><?php echo htmlspecialchars($user_email); ?></b>. Please upload your proof of payment below.</p>
<h5>Payment Details:</h5> <h5>Payment Details:</h5>
<p>The Four Wheel Drive Club of Southern Africa<br>FNB<br>Account Number: 58810022334<br>Branch code: 250655<br>Reference: <?php echo htmlspecialchars($eft_id); ?><br>Amount: R <?php echo number_format($payment_amount, 2); ?></p> <p>The Four Wheel Drive Club of Southern Africa<br>FNB<br>Account Number: 58810022334<br>Branch code: 250655<br>Reference: <?php echo htmlspecialchars($eft_id); ?><br>Amount: R <?php echo number_format($payment_amount, 2); ?></p>
<a href="submit_pop.php" class="theme-btn style-two style-three" style="width:100%;"> <a href="submit_pop" class="theme-btn style-two style-three" style="width:100%;">
<span data-hover="Submit Proof of Payment">Submit Proof of Payment</span> <span data-hover="Submit Proof of Payment">Submit Proof of Payment</span>
<i class="fal fa-arrow-right"></i> <i class="fal fa-arrow-right"></i>
</a> </a>
</div> </div>
<div class="col-lg-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<div class="about-us-image"> <div class="about-us-image">
<img src="assets/images/logos/weblogo.png" alt="About"> <img src="assets/images/logos/weblogo.png" alt="About">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,32 +1,32 @@
<?php <?php
require_once("env.php"); require_once("env.php");
require_once("session.php"); require_once("session.php");
require_once("connection.php"); require_once("connection.php");
require_once("functions.php"); require_once("functions.php");
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null; $user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
$eft_id = strtoupper("SUBS " . date("Y") . " " . getLastName($user_id)); $eft_id = strtoupper("SUBS " . date("Y") . " " . getLastName($user_id));
$status = 'AWAITING PAYMENT'; $status = 'AWAITING PAYMENT';
$description = 'Membership Fees ' . date("Y") . " " . getLastName($user_id); $description = 'Membership Fees ' . date("Y") . " " . getLastName($user_id);
$payment_amount = 2500; // Assuming a fixed membership fee, adjust as needed $payment_amount = 2500; // Assuming a fixed membership fee, adjust as needed
$payment_date = date('Y-m-d'); $payment_date = date('Y-m-d');
$membership_start_date = date('Y-01-01'); $membership_start_date = date('Y-01-01');
$membership_end_date = date('Y-12-31'); $membership_end_date = date('Y-12-31');
$stmt = $conn->prepare("UPDATE membership_fees SET payment_amount = ?, payment_date = ?, membership_start_date = ?, membership_end_date = ?, payment_status = 'PENDING', payment_id = ? WHERE user_id = ?"); $stmt = $conn->prepare("UPDATE membership_fees SET payment_amount = ?, payment_date = ?, membership_start_date = ?, membership_end_date = ?, payment_status = 'PENDING', payment_id = ? WHERE user_id = ?");
$stmt->bind_param("dssssi", $payment_amount, $payment_date, $membership_start_date, $membership_end_date, $eft_id, $user_id); $stmt->bind_param("dssssi", $payment_amount, $payment_date, $membership_start_date, $membership_end_date, $eft_id, $user_id);
if ($stmt->execute()) { if ($stmt->execute()) {
// Commit the transaction // Commit the transaction
$conn->commit(); $conn->commit();
addSubsEFT($eft_id, $user_id, $status, $payment_amount, $description); addSubsEFT($eft_id, $user_id, $status, $payment_amount, $description);
header("Location:membership_payment.php"); header("Location:membership_payment.php");
// Success message // Success message
$response = [ $response = [
'status' => 'success', 'status' => 'success',
'message' => 'Your membership application has been updated successfully!' 'message' => 'Your membership application has been updated successfully!'
]; ];
} else { } else {
throw new Exception("Failed to update membership fee. SQL error: " . $conn->error); throw new Exception("Failed to update membership fee. SQL error: " . $conn->error);
} }

View File

@@ -1,46 +1,46 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); include_once(dirname(dirname(dirname(__DIR__))) . '/header.php');
?> ?>
<!-- 404 Error Area start --> <!-- 404 Error Area start -->
<section class="error-area pt-70 pb-100 rel z-1"> <section class="error-area pt-70 pb-100 rel z-1">
<div class="container"> <div class="container">
<div class="row align-items-center justify-content-between"> <div class="row align-items-center justify-content-between">
<div class="col-xl-5 col-lg-6"> <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"> <div class="error-content rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<h1>OOPS! </h1> <h1>OOPS! </h1>
<div class="section-title mt-15 mb-25"> <div class="section-title mt-15 mb-25">
<h2>This Page Cant be Found</h2> <h2>This Page Cant be Found</h2>
</div> </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> --> <!-- <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="#"> <!-- <form class="newsletter-form mt-40 mb-50" action="#">
<input id="news-email" type="text" placeholder="Search keyword" required> <input id="news-email" type="text" placeholder="Search keyword" required>
<button type="submit" class="theme-btn bgc-secondary style-two"> <button type="submit" class="theme-btn bgc-secondary style-two">
<span data-hover="Search">Search</span> <span data-hover="Search">Search</span>
<i class="fal fa-arrow-right"></i> <i class="fal fa-arrow-right"></i>
</button> </button>
</form> </form>
<div class="keywords"> <div class="keywords">
<a href="blog.html">Travel</a> <a href="blog.html">Travel</a>
<a href="blog.html">Luxury Hotel</a> <a href="blog.html">Luxury Hotel</a>
<a href="blog.html">Indonesia</a> <a href="blog.html">Indonesia</a>
<a href="blog.html">Sea Beach</a> <a href="blog.html">Sea Beach</a>
<a href="blog.html">Camping</a> <a href="blog.html">Camping</a>
<a href="blog.html">Hiking</a> <a href="blog.html">Hiking</a>
<a href="blog.html">Fishing</a> <a href="blog.html">Fishing</a>
</div> --> </div> -->
</div> </div>
</div> </div>
<div class="col-xl-5 col-lg-6"> <div class="col-xl-5 col-lg-6">
<div class="error-images" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <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"> <img src="assets/images/404/lost.jpg" alt="404 Error">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- 404 Error Area end --> <!-- 404 Error Area end -->
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

284
src/pages/other/about.php Normal file
View File

@@ -0,0 +1,284 @@
<?php
$headerStyle = 'light';
// Determine the correct path to header.php based on file location
$rootPath = dirname(dirname(dirname(__DIR__)));
include_once($rootPath . '/header.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>
<?php
$pageTitle = 'About';
$breadcrumbs = [['Home' => 'index.php']];
require_once($rootPath . '/components/banner.php');
?>
<!-- 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. Saturdays Open Day includes breakfast and lunch for sale, plus braai fires ready to go—just bring your tongs! Its 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 = $rootPath . '/assets/images/opendays/';
$images = glob($folder . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
// Convert absolute paths to web-relative paths
$images = array_map(function($path) use ($rootPath) {
return str_replace($rootPath, '', $path);
}, $images);
// 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 its 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 = $rootPath . '/assets/images/memories/';
$images = glob($folder . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
// Convert absolute paths to web-relative paths
$images = array_map(function($path) use ($rootPath) {
return str_replace($rootPath, '', $path);
}, $images);
// 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="<?= url('trips') ?>" 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="<?= url('driver_training') ?>" 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="<?= url('events') ?>" 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($rootPath . '/components/insta_footer.php'); ?>

View File

@@ -1,248 +1,249 @@
<?php <?php
include_once('header02.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']; // Assuming you have the user ID stored in the session
$user_id = $_SESSION['user_id'];
// Fetch user data from the database
// Fetch user data from the database
$sql = "SELECT * FROM users WHERE user_id = ?";
$stmt = $conn->prepare($sql); $sql = "SELECT * FROM users WHERE user_id = ?";
$stmt->bind_param("i", $user_id); $stmt = $conn->prepare($sql);
$stmt->execute(); $stmt->bind_param("i", $user_id);
$result = $stmt->get_result(); $stmt->execute();
$user = $result->fetch_assoc(); $result = $stmt->get_result();
?> $user = $result->fetch_assoc();
?>
<style>
.profile-picture:hover .edit-icon { <style>
display: block; .profile-picture:hover .edit-icon {
} display: block;
}
.profile-picture {
position: relative; .profile-picture {
width: 150px; position: relative;
height: 150px; width: 150px;
margin: 0 auto; height: 150px;
} margin: 0 auto;
}
.profile-pic-display {
width: 100%; .profile-pic-display {
height: 100%; width: 100%;
border-radius: 50%; height: 100%;
object-fit: cover; border-radius: 50%;
} object-fit: cover;
}
.edit-icon {
display: none; .edit-icon {
position: absolute; display: none;
width: 100%; position: absolute;
height: 100%; width: 100%;
top: 50%; height: 100%;
left: 50%; top: 50%;
transform: translate(-50%, -50%); left: 50%;
background-color: rgba(255, 255, 255, 0.5); transform: translate(-50%, -50%);
border: none; background-color: rgba(255, 255, 255, 0.5);
border-radius: 50%; border: none;
cursor: pointer; border-radius: 50%;
} cursor: pointer;
}
.edit-icon i {
color: white; .edit-icon i {
} color: white;
}
</style>
</style>
<!-- Account Settings Area start -->
<section class="account-settings-area py-70 rel z-1"> <!-- Account Settings Area start -->
<div class="container"> <section class="account-settings-area py-70 rel z-1">
<div class="row align-items-center"> <div class="container">
<div class="col-lg-12"> <div class="row align-items-center">
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55"> <div class="col-lg-12">
<form id="accountForm" name="accountForm" method="post" action="update_user.php"> <div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55">
<div class="section-title py-20"> <form id="accountForm" name="accountForm" method="post" action="update_user">
<h2>Account Settings</h2> <div class="section-title py-20">
<div id="responseMessage"></div> <!-- Message display area --> <h2>Account Settings</h2>
</div> <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;"> <!-- Display Profile Picture -->
<img id="profile-pic" src="<?php echo $user['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic-display" <div class="profile-picture" style="position: relative; width: 150px; height: 150px; margin: 0 auto;">
style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;"> <img id="profile-pic" src="<?php echo $user['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic-display"
<button type="button" id="uploadPictureBtn" class="edit-icon"> style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">
<i class="fas fa-pencil-alt"></i> <button type="button" id="uploadPictureBtn" class="edit-icon">
</button> <i class="fas fa-pencil-alt"></i>
<input type="file" id="profile_picture" name="profile_picture" accept="image/*" style="display:none;"> </button>
</div> <input type="file" id="profile_picture" name="profile_picture" accept="image/*" style="display:none;">
</div>
<!-- Form Fields -->
<div class="row mt-35"> <!-- Form Fields -->
<div class="col-md-6"> <div class="row mt-35">
<div class="form-group"> <div class="col-md-6">
<label for="first_name">First Name</label> <div class="form-group">
<input type="text" id="first_name" name="first_name" class="form-control" value="<?php echo $user['first_name']; ?>" required> <label for="first_name">First Name</label>
</div> <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>
<div class="form-group"> <div class="col-md-6">
<label for="last_name">Last Name</label> <div class="form-group">
<input type="text" id="last_name" name="last_name" class="form-control" value="<?php echo $user['last_name']; ?>" required> <label for="last_name">Last Name</label>
</div> <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>
<div class="form-group"> <div class="col-md-12">
<label for="phone_number">Phone Number</label> <div class="form-group">
<input type="text" id="phone_number" name="phone_number" class="form-control" value="<?php echo $user['phone_number']; ?>" required> <label for="phone_number">Phone Number</label>
</div> <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>
<div class="form-group"> <div class="col-md-12">
<label for="email">Email Address</label> <div class="form-group">
<input type="email" id="email" name="email" class="form-control" value="<?php echo $user['email']; ?>" required> <label for="email">Email Address</label>
</div> <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>
<div class="col-md-12"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<div class="form-group mb-0"> <div class="col-md-12">
<button type="submit" class="theme-btn style-two" style="width:100%;">Update Info</button> <div class="form-group mb-0">
</div> <button type="submit" class="theme-btn style-two" style="width:100%;">Update Info</button>
</div> </div>
</div> </div>
</form> </div>
<?php if (getUserType($user_id) !== 'google'){?> </form>
<?php if (getUserType($user_id) !== 'google'){?>
<!-- Change Password Form -->
<form id="changePasswordForm" name="changePasswordForm" action="change_password.php" method="post"> <!-- Change Password Form -->
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <form id="changePasswordForm" name="changePasswordForm" action="change_password" method="post">
<div class="col-md-12 mt-20"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<h4>Change Password</h4> <div class="col-md-12 mt-20">
<div id="responseMessage2"></div> <!-- Message display area --> <h4>Change Password</h4>
<div class="form-group"> <div id="responseMessage2"></div> <!-- Message display area -->
<label for="current_password">Current Password</label> <div class="form-group">
<input type="password" id="current_password" name="current_password" class="form-control" required> <label for="current_password">Current Password</label>
</div> <input type="password" id="current_password" name="current_password" class="form-control" required>
<div class="form-group"> </div>
<label for="new_password">New Password</label> <div class="form-group">
<input type="password" id="new_password" name="new_password" class="form-control" required> <label for="new_password">New Password</label>
</div> <input type="password" id="new_password" name="new_password" class="form-control" required>
<div class="form-group"> </div>
<label for="confirm_password">Confirm New Password</label> <div class="form-group">
<input type="password" id="confirm_password" name="confirm_password" class="form-control" required> <label for="confirm_password">Confirm New Password</label>
</div> <input type="password" id="confirm_password" name="confirm_password" class="form-control" required>
<div class="form-group mb-0"> </div>
<button type="submit" class="theme-btn style-two" style="width:100%;">Change Password</button> <div class="form-group mb-0">
</div> <button type="submit" class="theme-btn style-two" style="width:100%;">Change Password</button>
</div> </div>
</form> </div>
<?php }?> </form>
</div> <?php }?>
</div> </div>
</div>
</div>
</div> </div>
</section> </div>
<!-- Account Settings Area end --> </section>
<!-- Account Settings Area end -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
$(document).ready(function() { <script>
// Clear the responseMessage when the user changes any form input $(document).ready(function() {
$('#accountForm input, #changePasswordForm input').on('input', function() { // Clear the responseMessage when the user changes any form input
$('#responseMessage').html(''); // Clear the message $('#accountForm input, #changePasswordForm input').on('input', function() {
$('#responseMessage2').html(''); // Clear the message $('#responseMessage').html(''); // Clear the message
}); $('#responseMessage2').html(''); // Clear the message
// Profile Picture Upload });
$('#uploadPictureBtn').click(function() { // Profile Picture Upload
$('#profile_picture').click(); $('#uploadPictureBtn').click(function() {
}); $('#profile_picture').click();
});
$('#profile_picture').on('change', function() {
var formData = new FormData(); $('#profile_picture').on('change', function() {
formData.append('profile_picture', $('#profile_picture')[0].files[0]); var formData = new FormData();
formData.append('profile_picture', $('#profile_picture')[0].files[0]);
$.ajax({
url: 'upload_profile_picture.php', $.ajax({
type: 'POST', url: 'upload_profile_picture',
data: formData, type: 'POST',
contentType: false, data: formData,
processData: false, contentType: false,
success: function(response) { processData: false,
// Parse response if needed success: function(response) {
if (typeof response === "string") { // Parse response if needed
response = JSON.parse(response); if (typeof response === "string") {
} response = JSON.parse(response);
}
if (response.status === 'success') {
// Update the profile picture source with cache-busting query string if (response.status === 'success') {
// Reload the current page // Update the profile picture source with cache-busting query string
window.location.reload(); // Reload the current page
window.location.reload();
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
} else { $('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
$('#responseMessage').html('<div class="alert alert-danger">' + 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>'); error: function() {
} $('#responseMessage').html('<div class="alert alert-danger">Error uploading profile picture.</div>');
}); }
}); });
});
// Account Info Update
$('#accountForm').on('submit', function(event) { // Account Info Update
event.preventDefault(); // Prevent default form submission $('#accountForm').on('submit', function(event) {
event.preventDefault(); // Prevent default form submission
$.ajax({
url: 'update_user.php', $.ajax({
type: 'POST', url: 'update_user',
data: $(this).serialize(), type: 'POST',
success: function(response) { data: $(this).serialize(),
// Parse response if needed success: function(response) {
if (typeof response === "string") { // Parse response if needed
response = JSON.parse(response); if (typeof response === "string") {
} response = JSON.parse(response);
}
if (response.status === 'success') {
$('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>'); if (response.status === 'success') {
} else { $('#responseMessage').html('<div class="alert alert-success">' + response.message + '</div>');
$('#responseMessage').html('<div class="alert alert-danger">' + 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>'); error: function() {
} $('#responseMessage').html('<div class="alert alert-danger">Error updating information.</div>');
}); }
}); });
});
// Change Password
$('#changePasswordForm').on('submit', function(event) { // Change Password
event.preventDefault(); // Prevent default form submission $('#changePasswordForm').on('submit', function(event) {
event.preventDefault(); // Prevent default form submission
$.ajax({
url: 'change_password.php', $.ajax({
type: 'POST', url: 'change_password',
data: $(this).serialize(), type: 'POST',
success: function(response) { data: $(this).serialize(),
// Parse response if needed success: function(response) {
if (typeof response === "string") { // Parse response if needed
response = JSON.parse(response); if (typeof response === "string") {
} response = JSON.parse(response);
}
if (response.status === 'success') {
$('#responseMessage2').html('<div class="alert alert-success">' + response.message + '</div>'); if (response.status === 'success') {
} else { $('#responseMessage2').html('<div class="alert alert-success">' + response.message + '</div>');
$('#responseMessage2').html('<div class="alert alert-danger">' + 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>'); error: function() {
} $('#responseMessage2').html('<div class="alert alert-danger">Error changing password.</div>');
}); }
}); });
}); });
</script> });
</script>
<?php include_once("insta_footer.php"); ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -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="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"> <div style="border-radius:20px;" class="carousel-inner">
<?php <?php
$dir = 'assets/images/advertising/'; $dir = 'assets/images/advertising/';
$images = glob($dir . '*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE); $images = glob($dir . '*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE);
foreach ($images as $index => $img) { foreach ($images as $index => $img) {
$active = $index === 0 ? 'active' : ''; $active = $index === 0 ? 'active' : '';
echo "<div class='carousel-item $active'> echo "<div class='carousel-item $active'>
<img src='$img' class='d-block w-100' style='height:394px; object-fit:cover;' alt='Ad $index'> <img src='$img' class='d-block w-100' style='height:394px; object-fit:cover;' alt='Ad $index'>
</div>"; </div>";
} }
?> ?>
<a class="carousel-control-prev" href="#advertisingCarousel" role="button" data-bs-slide="prev"> <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="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span> <span class="visually-hidden">Previous</span>
</a> </a>
<a class="carousel-control-next" href="#advertisingCarousel" role="button" data-bs-slide="next"> <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="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span> <span class="visually-hidden">Next</span>
</a> </a>
<div class="carousel-indicators"> <div class="carousel-indicators">
<?php foreach ($images as $i => $_): ?> <?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> <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; ?> <?php endforeach; ?>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,132 +1,133 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
// Assuming you have the user ID stored in the session include_once($rootPath . '/header.php');
if (isset($_SESSION['user_id'])) { // Assuming you have the user ID stored in the session
$user_id = $_SESSION['user_id']; if (isset($_SESSION['user_id'])) {
} else { $user_id = $_SESSION['user_id'];
header('Location: login.php'); } else {
exit(); // Stop further script execution header('Location: login.php');
} exit(); // Stop further script execution
?> }
?>
<style>
h2 { <style>
text-align: center; h2 {
margin-bottom: 20px; text-align: center;
} margin-bottom: 20px;
}
.indemnitycontainer {
max-width: 800px; .indemnitycontainer {
margin: 0 auto; max-width: 800px;
} margin: 0 auto;
}
.indemnity-text {
text-align: justify; .indemnity-text {
margin-bottom: 20px; text-align: justify;
} margin-bottom: 20px;
}
.signature-container {
margin-top: 30px; .signature-container {
margin-bottom: 100px; margin-top: 30px;
text-align: center; margin-bottom: 100px;
} text-align: center;
}
#signature-pad {
border: 1px solid black; #signature-pad {
border: 1px solid black;
}
</style> }
</style>
<?php <?php
$pageTitle = 'Indemnity'; $pageTitle = 'Indemnity';
$breadcrumbs = [['Home' => 'index.php']]; $breadcrumbs = [['Home' => 'index.php']];
require_once('components/banner.php'); require_once($rootPath . '/components/banner.php');
?> ?>
<!-- Page Banner End --> <!-- Page Banner End -->
<div class="indemnitycontainer pt-20"> <div class="indemnitycontainer pt-20">
<!-- <h2>Indemnity and Waiver</h2> --> <!-- <h2>Indemnity and Waiver</h2> -->
<div class="indemnity-text"> <div class="indemnity-text">
<p><strong>INDEMNITY AND WAIVER</strong></p> <p><strong>INDEMNITY AND WAIVER</strong></p>
<p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p> <p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p>
<p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p> <p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p>
<p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p> <p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p>
<p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p> <p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p>
<p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p> <p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p>
<p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p> <p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p>
<p><strong>BASE 4 CODE OF CONDUCT</strong></p> <p><strong>BASE 4 CODE OF CONDUCT</strong></p>
<p>1. No motorbikes or quadbikes.</p> <p>1. No motorbikes or quadbikes.</p>
<p>2. No loud music (unless authorised by the Committee or its representatives).</p> <p>2. No loud music (unless authorised by the Committee or its representatives).</p>
<p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p> <p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p>
<p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p> <p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p>
<p>5. No person in the rear of open vehicles when driving on obstacles.</p> <p>5. No person in the rear of open vehicles when driving on obstacles.</p>
<p>6. When driving the obstacles stay on the tracks.</p> <p>6. When driving the obstacles stay on the tracks.</p>
<p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p> <p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p>
<p>8. No alcohol to be consumed while driving the track.</p> <p>8. No alcohol to be consumed while driving the track.</p>
<p>9. No littering (please pick up cigarette butts etc.)</p> <p>9. No littering (please pick up cigarette butts etc.)</p>
<p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p> <p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p>
<p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p> <p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p>
<p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p> <p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p>
</div> </div>
<div class="signature-container"> <div class="signature-container">
<div style="text-align: center;" id="responseMessage"></div> <!-- Message display area --> <div style="text-align: center;" id="responseMessage"></div> <!-- Message display area -->
<p><strong>Signature</strong></p> <p><strong>Signature</strong></p>
<canvas id="signature-pad" width=400 height=200></canvas><br> <canvas id="signature-pad" width=400 height=200></canvas><br>
<button type="button" class="theme-btn style-two" id="save">ACCEPT INDEMNITY</button> <button type="button" class="theme-btn style-two" id="save">ACCEPT INDEMNITY</button>
<!-- <div class="pt-20" style="text-align: center;">You will be redirected to Payfast for payment.</div> --> <!-- <div class="pt-20" style="text-align: center;">You will be redirected to Payfast for payment.</div> -->
</div> </div>
</div> </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js"></script>
<script> <script>
var canvas = document.getElementById('signature-pad'); var canvas = document.getElementById('signature-pad');
var signaturePad = new SignaturePad(canvas); var signaturePad = new SignaturePad(canvas);
document.getElementById('save').addEventListener('click', function() { document.getElementById('save').addEventListener('click', function() {
if (signaturePad.isEmpty()) { if (signaturePad.isEmpty()) {
alert("Please provide a signature."); alert("Please provide a signature.");
} else { } else {
var dataUrl = signaturePad.toDataURL(); // Get signature as base64 image var dataUrl = signaturePad.toDataURL(); // Get signature as base64 image
$.ajax({ $.ajax({
url: 'process_signature.php', url: 'process_signature',
type: 'POST', type: 'POST',
data: { data: {
signature: dataUrl // Send the base64 signature image signature: dataUrl // Send the base64 signature image
}, },
success: function(response) { success: function(response) {
// Parse response if needed // Parse response if needed
if (typeof response === "string") { if (typeof response === "string") {
response = JSON.parse(response); response = JSON.parse(response);
} }
if (response.status === 'success') { if (response.status === 'success') {
// Check if the user has paid // Check if the user has paid
if (response.paymentStatus === 'PAID') { if (response.paymentStatus === 'PAID') {
// Redirect to membership_details.php if paid // Redirect to membership_details.php if paid
setTimeout(function() { setTimeout(function() {
window.location.href = 'membership_details.php'; window.location.href = 'membership_details.php';
}, 2000); // 2-second delay before redirecting }, 2000); // 2-second delay before redirecting
} else { } else {
// Redirect to membership_payment.php if not paid // Redirect to membership_payment.php if not paid
setTimeout(function() { setTimeout(function() {
window.location.href = 'membership_payment.php'; window.location.href = 'membership_payment.php';
}, 2000); // 2-second delay before redirecting }, 2000); // 2-second delay before redirecting
} }
} else { } else {
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>'); $('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
} }
}, },
error: function() { error: function() {
$('#responseMessage').html('<div class="alert alert-danger">Error uploading profile picture.</div>'); $('#responseMessage').html('<div class="alert alert-danger">Error uploading profile picture.</div>');
} }
}); });
} }
}); });
</script> </script>
<?php include_once('insta_footer.php') ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php') ?>

View File

@@ -1,384 +1,385 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
checkUserSession(); include_once($rootPath . '/header.php');
checkUserSession();
// SQL query to fetch dates for bush mechanics
$stmt = $conn->prepare("SELECT course_id, date FROM courses WHERE course_type = ? AND date >= CURDATE()"); // SQL query to fetch dates for bush mechanics
$course_type = 'bush_mechanics'; $stmt = $conn->prepare("SELECT course_id, date FROM courses WHERE course_type = ? AND date >= CURDATE()");
$stmt->bind_param("s", $course_type); $course_type = 'bush_mechanics';
$stmt->execute(); $stmt->bind_param("s", $course_type);
$result = $stmt->get_result(); $stmt->execute();
$page_id = 'bush_mechanics'; $result = $stmt->get_result();
?> $page_id = 'bush_mechanics';
?>
<style>
.form-group { <style>
margin-bottom: 15px; .form-group {
} margin-bottom: 15px;
}
select {
width: 100%; select {
padding: 8px; width: 100%;
font-size: 16px; padding: 8px;
} font-size: 16px;
}
</style><?php
$pageTitle = 'Bush Mechanics'; </style><?php
$breadcrumbs = [['Home' => 'index.php']]; $pageTitle = 'Bush Mechanics';
require_once('components/banner.php'); $breadcrumbs = [['Home' => 'index.php']];
?> require_once($rootPath . '/components/banner.php');
?>
<!-- Product Details Start -->
<section class="product-details pt-100"> <!-- Product Details Start -->
<div class="container"> <section class="product-details pt-100">
<div class="row"> <div class="container">
<div class="col-lg-6"> <div class="row">
<div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6">
<div class="tab-content preview-images"> <div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="tab-pane fade preview-item active show" id="preview1"> <div class="tab-content preview-images">
<img src="assets/images/drivertraining/bm01.jpg" alt="Perview"> <div class="tab-pane fade preview-item active show" id="preview1">
</div> <img src="assets/images/drivertraining/bm01.jpg" alt="Perview">
<div class="tab-pane fade preview-item" id="preview2"> </div>
<img src="assets/images/drivertraining/bm02.jpg" alt="Perview"> <div class="tab-pane fade preview-item" id="preview2">
</div> <img src="assets/images/drivertraining/bm02.jpg" alt="Perview">
<div class="tab-pane fade preview-item" id="preview3"> </div>
<img src="assets/images/drivertraining/bm03.jpg" alt="Perview"> <div class="tab-pane fade preview-item" id="preview3">
</div> <img src="assets/images/drivertraining/bm03.jpg" alt="Perview">
</div> </div>
<div class="nav thumb-images rmb-20"> </div>
<a href="#preview1" data-bs-toggle="tab" class="thumb-item active show"> <div class="nav thumb-images rmb-20">
<img src="assets/images/drivertraining/bm01.jpg" alt="Thumb"> <a href="#preview1" data-bs-toggle="tab" class="thumb-item active show">
</a> <img src="assets/images/drivertraining/bm01.jpg" alt="Thumb">
<a href="#preview2" data-bs-toggle="tab" class="thumb-item"> </a>
<img src="assets/images/drivertraining/bm02.jpg" alt="Thumb"> <a href="#preview2" data-bs-toggle="tab" class="thumb-item">
</a> <img src="assets/images/drivertraining/bm02.jpg" alt="Thumb">
<a href="#preview3" data-bs-toggle="tab" class="thumb-item"> </a>
<img src="assets/images/drivertraining/bm03.jpg" alt="Thumb"> <a href="#preview3" data-bs-toggle="tab" class="thumb-item">
</a> <img src="assets/images/drivertraining/bm03.jpg" alt="Thumb">
</div> </a>
</div> </div>
</div> </div>
<div class="col-lg-6"> </div>
<div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6">
<div class="section-title"> <div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<h2>Bush Mechanics</h2> <div class="section-title">
</div> <h2>Bush Mechanics</h2>
<!-- <div class="ratting mb-15"> </div>
<i class="fas fa-star"></i> <!-- <div class="ratting mb-15">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
<span>(5.8k+ reviews)</span> <i class="fas fa-star-half-alt"></i>
</div> --> <span>(5.8k+ reviews)</span>
<span class="price mb-5">R <?= getPrice('bush_mechanics', 'member');?>/member</span> </div> -->
<span class="price mb-25">R <?= getPrice('bush_mechanics', 'nonmember');?>/non-members</span> <span class="price mb-5">R <?= getPrice('bush_mechanics', 'member');?>/member</span>
<p> This Bush Mechanics Course is tailored to help you develop the essential skills for managing vehicle repairs and maintenance in remote, off-grid locations. Learn practical techniques for diagnosing and fixing mechanical issues using limited resources, from tire repairs to engine troubleshooting. The course covers the use of basic tools, improvising solutions in the field, and ensuring your vehicle remains operational even in the most challenging environments. Perfect for off-road adventurers, 4x4 owners, and those who want to be prepared for any mechanical situation while exploring remote areas.</p> <span class="price mb-25">R <?= getPrice('bush_mechanics', 'nonmember');?>/non-members</span>
<hr class="mt-40"> <p> This Bush Mechanics Course is tailored to help you develop the essential skills for managing vehicle repairs and maintenance in remote, off-grid locations. Learn practical techniques for diagnosing and fixing mechanical issues using limited resources, from tire repairs to engine troubleshooting. The course covers the use of basic tools, improvising solutions in the field, and ensuring your vehicle remains operational even in the most challenging environments. Perfect for off-road adventurers, 4x4 owners, and those who want to be prepared for any mechanical situation while exploring remote areas.</p>
<div class="blog-sidebar tour-sidebar"> <hr class="mt-40">
<div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="blog-sidebar tour-sidebar">
<form action="process_course_booking.php" method="POST"> <div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul class="tickets clearfix"> <form action="process_course_booking" method="POST">
<li> <ul class="tickets clearfix">
Select Date <li>
<select name="course_id" id="course_id" required> Select Date
<?php <select name="course_id" id="course_id" required>
if ($result->num_rows > 0) { <?php
// Output each course as an option if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { // Output each course as an option
$course_id = htmlspecialchars($row['course_id']); // Escape output for security while ($row = $result->fetch_assoc()) {
$date = htmlspecialchars($row['date']); // Escape output for security $course_id = htmlspecialchars($row['course_id']); // Escape output for security
echo "<option value='$course_id'>$date</option>"; $date = htmlspecialchars($row['date']); // Escape output for security
} echo "<option value='$course_id'>$date</option>";
} else { }
echo "<option value='' disabled>No dates available</option>"; } else {
} echo "<option value='' disabled>No dates available</option>";
?> }
</select> ?>
</li> </select>
<?php </li>
if ($is_member || $pending_member) { <?php
echo ' if ($is_member || $pending_member) {
<li> echo '
Additional Members <span class="price"></span> <li>
<select name="members" id="members"> Additional Members <span class="price"></span>
<option value="0" selected>00</option> <select name="members" id="members">
<option value="1">01</option> <option value="0" selected>00</option>
<option value="2">02</option> <option value="1">01</option>
<option value="3">03</option> <option value="2">02</option>
</select> <option value="3">03</option>
</li> </select>
'; </li>
} ?> ';
} ?>
<li>
Additional Non-Members <span class="price"></span> <li>
<select name="non-members" id="non-members"> Additional Non-Members <span class="price"></span>
<option value="0" selected>00</option> <select name="non-members" id="non-members">
<option value="1">01</option> <option value="0" selected>00</option>
<option value="2">02</option> <option value="1">01</option>
<option value="3">03</option> <option value="2">02</option>
</select> <option value="3">03</option>
</li> </select>
</ul> </li>
<hr class="mb-25"> </ul>
<hr class="mb-25">
<h6>Total: <span id="booking_total" class="price">-</span></h6>
<div style="margin: 20px 0;"> <h6>Total: <span id="booking_total" class="price">-</span></h6>
<div id="indemnityBox" style="border: 1px solid #ccc; padding: 10px; height: 150px; overflow-y: scroll; background: #f9f9f9; font-size: 12px;"> <div style="margin: 20px 0;">
<p><strong>INDEMNITY AND WAIVER</strong></p> <div id="indemnityBox" style="border: 1px solid #ccc; padding: 10px; height: 150px; overflow-y: scroll; background: #f9f9f9; font-size: 12px;">
<p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p> <p><strong>INDEMNITY AND WAIVER</strong></p>
<p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p> <p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p>
<p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p> <p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p>
<p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p> <p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p>
<p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p> <p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p>
<p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p> <p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p>
<p><strong>BASE 4 CODE OF CONDUCT</strong></p> <p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p>
<p>1. No motorbikes or quadbikes.</p> <p><strong>BASE 4 CODE OF CONDUCT</strong></p>
<p>2. No loud music (unless authorised by the Committee or its representatives).</p> <p>1. No motorbikes or quadbikes.</p>
<p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p> <p>2. No loud music (unless authorised by the Committee or its representatives).</p>
<p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p> <p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p>
<p>5. No person in the rear of open vehicles when driving on obstacles.</p> <p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p>
<p>6. When driving the obstacles stay on the tracks.</p> <p>5. No person in the rear of open vehicles when driving on obstacles.</p>
<p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p> <p>6. When driving the obstacles stay on the tracks.</p>
<p>8. No alcohol to be consumed while driving the track.</p> <p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p>
<p>9. No littering (please pick up cigarette butts etc.)</p> <p>8. No alcohol to be consumed while driving the track.</p>
<p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p> <p>9. No littering (please pick up cigarette butts etc.)</p>
<p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p> <p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p>
<p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p> <p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p>
</div> <p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p>
<div style="margin-top: 10px;"> </div>
<input type="checkbox" id="agreeCheckbox" name="agree" disabled required> <div style="margin-top: 10px;">
<label for="agreeCheckbox" id="agreeLabel" style="color: #888;">I have read and agree to the indemnity terms</label> <input type="checkbox" id="agreeCheckbox" name="agree" disabled required>
</div> <label for="agreeCheckbox" id="agreeLabel" style="color: #888;">I have read and agree to the indemnity terms</label>
</div> </div>
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> </div>
<?php <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
$button_text = "Book Now"; <?php
$button_disabled = ""; $button_text = "Book Now";
if (!$result || $result->num_rows == 0) { $button_disabled = "";
$button_text = "No booking dates available"; if (!$result || $result->num_rows == 0) {
$button_disabled = "disabled"; $button_text = "No booking dates available";
} $button_disabled = "disabled";
?> }
<button type="submit" class="theme-btn style-two w-100 mt-15 mb-5" <?php echo $button_disabled; ?>> ?>
<span data-hover="<?php echo $button_text; ?>"><?php echo $button_text; ?></span> <button type="submit" class="theme-btn style-two w-100 mt-15 mb-5" <?php echo $button_disabled; ?>>
<i class="fal fa-arrow-right"></i> <span data-hover="<?php echo $button_text; ?>"><?php echo $button_text; ?></span>
</button> <i class="fal fa-arrow-right"></i>
<div class="text-center"> </button>
<a href="contact.php">Need some help?</a> <div class="text-center">
</div> <a href="contact">Need some help?</a>
</form> </div>
</div> </form>
</div>
</div>
<!-- <hr class="mb-45"> --> </div>
<!-- <a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a> --> <!-- <hr class="mb-45"> -->
</div> <!-- <a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a> -->
</div> </div>
</div> </div>
<ul class="nav nav product-tab mt-70 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div>
<li><a href="#details" data-bs-toggle="tab" class="active show">Course Overview<i class="far fa-arrow-right"></i></a></li> <ul class="nav nav product-tab mt-70 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<li><a href="#information" data-bs-toggle="tab">What to Expect<i class="far fa-arrow-right"></i></a></li> <li><a href="#details" data-bs-toggle="tab" class="active show">Course Overview<i class="far fa-arrow-right"></i></a></li>
<li><a href="#reviews" data-bs-toggle="tab"> Reviews <i class="far fa-arrow-right"></i></a></li> <li><a href="#information" data-bs-toggle="tab">What to Expect<i class="far fa-arrow-right"></i></a></li>
</ul> <li><a href="#reviews" data-bs-toggle="tab"> Reviews <i class="far fa-arrow-right"></i></a></li>
<div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50"> </ul>
<div class="tab-pane fade active show" id="details"> <div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
<p>This Bush Mechanics Course is designed to provide participants with practical, hands-on skills and knowledge for conducting essential repairs and maintenance in remote and off-road environments. Participants will learn how to assess mechanical issues and apply bush-friendly repair techniques, ensuring they can keep their 4x4 running smoothly in the field. The course covers a wide range of topics, from tire repairs and fixing fuel systems to electrical troubleshooting and engine repairs, all using minimal tools and available resources.</p> <div class="tab-pane fade active show" id="details">
<p>Emphasis is placed on the use of basic tools, improvising with available materials, and maintaining the vehicles functionality in harsh conditions. The course also prioritizes safety, teaching participants how to perform repairs while minimizing risk and ensuring they can safely handle mechanical breakdowns during off-road adventures. With a focus on resourcefulness and problem-solving, this course equips off-road enthusiasts and 4x4 owners with the confidence to tackle mechanical challenges and keep their vehicles in top shape while exploring remote locations.</p> <p>This Bush Mechanics Course is designed to provide participants with practical, hands-on skills and knowledge for conducting essential repairs and maintenance in remote and off-road environments. Participants will learn how to assess mechanical issues and apply bush-friendly repair techniques, ensuring they can keep their 4x4 running smoothly in the field. The course covers a wide range of topics, from tire repairs and fixing fuel systems to electrical troubleshooting and engine repairs, all using minimal tools and available resources.</p>
<div class="row gap-50 pt-25 pb-20 align-items-center"> <p>Emphasis is placed on the use of basic tools, improvising with available materials, and maintaining the vehicles functionality in harsh conditions. The course also prioritizes safety, teaching participants how to perform repairs while minimizing risk and ensuring they can safely handle mechanical breakdowns during off-road adventures. With a focus on resourcefulness and problem-solving, this course equips off-road enthusiasts and 4x4 owners with the confidence to tackle mechanical challenges and keep their vehicles in top shape while exploring remote locations.</p>
<div class="col-lg-7 pt-15"> <div class="row gap-50 pt-25 pb-20 align-items-center">
<h5>What this course includes</h5> <div class="col-lg-7 pt-15">
<ul class="list-style-two mt-25"> <h5>What this course includes</h5>
<li>Bush Mechanics Manual.</li> <ul class="list-style-two mt-25">
<li>Theory session and discussion.</li> <li>Bush Mechanics Manual.</li>
<li>Spend the afternoon practicing common bush mechanics techniques.</li> <li>Theory session and discussion.</li>
</ul> <li>Spend the afternoon practicing common bush mechanics techniques.</li>
</div> </ul>
<div class="col-lg-5"> </div>
<div class="image rmt-45"> <div class="col-lg-5">
<img src="assets/images/drivertraining/bm04.jpg" alt="Product Details"> <div class="image rmt-45">
</div> <img src="assets/images/drivertraining/bm04.jpg" alt="Product Details">
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="information"> </div>
<!-- <p>Circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses</p> --> <div class="tab-pane fade" id="information">
<ul class="list-style-two my-35"> <!-- <p>Circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses</p> -->
<li>Coffee and Welcome: Kick off the day with a warm coffee, meet your instructors, and receive an overview of the course schedule</li> <ul class="list-style-two my-35">
<li>Theory Session: Dive into the key principles of off-road driving, including vehicle mechanics, terrain navigation, recovery methods, and safety protocols.</li> <li>Coffee and Welcome: Kick off the day with a warm coffee, meet your instructors, and receive an overview of the course schedule</li>
<li>Practical Demonstrations: Watch live demonstrations covering vital techniques like gear selection, adjusting tire pressure, and setting up recovery equipment.</li> <li>Theory Session: Dive into the key principles of off-road driving, including vehicle mechanics, terrain navigation, recovery methods, and safety protocols.</li>
<li>Lunch Break: Enjoy a packed lunch or bring something to braai. Fires will be provided for an authentic outdoor experience.</li> <li>Practical Demonstrations: Watch live demonstrations covering vital techniques like gear selection, adjusting tire pressure, and setting up recovery equipment.</li>
<li>Practical Bush Mechanics Techniques: Learn hands-on techniques like rebeading a tire, fixing punctures, and performing basic vehicle repairs in the field.</li> <li>Lunch Break: Enjoy a packed lunch or bring something to braai. Fires will be provided for an authentic outdoor experience.</li>
<li>Debrief and Certificates: Conclude the day with a review of your progress, feedback from the instructors, and certificates of completion for your off-road training.</li> <li>Practical Bush Mechanics Techniques: Learn hands-on techniques like rebeading a tire, fixing punctures, and performing basic vehicle repairs in the field.</li>
<li>Debrief and Certificates: Conclude the day with a review of your progress, feedback from the instructors, and certificates of completion for your off-road training.</li>
</ul>
</div> </ul>
<div class="tab-pane fade mb-20" id="reviews"> </div>
<?php include_once('review_box.php'); ?> <div class="tab-pane fade mb-20" id="reviews">
</div> <?php include_once('review_box.php'); ?>
</div> </div>
</div> </div>
</section> </div>
<!-- Product Details End --> </section>
<!-- Product Details End -->
<!-- Shop Details Area start -->
<!-- <section class="shop-details-page pt-80 pb-100 rel z-1"> <!-- Shop Details Area start -->
<div class="container"> <!-- <section class="shop-details-page pt-80 pb-100 rel z-1">
<div class="section-title text-center mb-40"> <div class="container">
<h2>Other Courses</h2> <div class="section-title text-center mb-40">
</div> <h2>Other Courses</h2>
<div class="product-slider"> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50"> <div class="product-slider">
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/shop/product1.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product1.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Airport Travel Suitcases</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Airport Travel Suitcases</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50">
<img src="assets/images/shop/product2.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product2.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Travel Great blue hat</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Travel Great blue hat</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100">
<img src="assets/images/shop/product3.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product3.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Waistband and Mesh Fashion</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Waistband and Mesh Fashion</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="150"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="150">
<img src="assets/images/shop/product4.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product4.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Sandals for Casual Techies</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Sandals for Casual Techies</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
<div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50"> </div>
<div class="image"> <div class="product-item" data-aos="flip-left" data-aos-duration="1500" data-aos-offset="50">
<img src="assets/images/shop/product5.png" alt="Product"> <div class="image">
</div> <img src="assets/images/shop/product5.png" alt="Product">
<div class="content"> </div>
<div class="ratting"> <div class="content">
<i class="fas fa-star"></i> <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
</div> <i class="fas fa-star-half-alt"></i>
<h6><a href="product-details.html">Children With Jute Soles</a></h6> </div>
<span class="price">$188.00</span> <h6><a href="product-details.html">Children With Jute Soles</a></h6>
</div> <span class="price">$188.00</span>
</div> </div>
</div> </div>
</div> </div>
</section> --> </div>
<!-- Shop Details Area end --> </section> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <!-- Shop Details Area end -->
<script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
const indemnityBox = document.getElementById('indemnityBox'); <script>
const agreeCheckbox = document.getElementById('agreeCheckbox'); const indemnityBox = document.getElementById('indemnityBox');
const bookingForm = document.querySelector('form'); const agreeCheckbox = document.getElementById('agreeCheckbox');
const bookingForm = document.querySelector('form');
indemnityBox.addEventListener('scroll', function () {
const scrollTop = indemnityBox.scrollTop; indemnityBox.addEventListener('scroll', function () {
const scrollHeight = indemnityBox.scrollHeight; const scrollTop = indemnityBox.scrollTop;
const offsetHeight = indemnityBox.offsetHeight; const scrollHeight = indemnityBox.scrollHeight;
const offsetHeight = indemnityBox.offsetHeight;
// Enable checkbox when scrolled to bottom
if (scrollTop + offsetHeight >= scrollHeight - 1) { // Enable checkbox when scrolled to bottom
agreeCheckbox.disabled = false; if (scrollTop + offsetHeight >= scrollHeight - 1) {
document.getElementById('agreeLabel').style.color = "#000"; // optional: make label active agreeCheckbox.disabled = false;
} document.getElementById('agreeLabel').style.color = "#000"; // optional: make label active
}); }
});
bookingForm.addEventListener('submit', function (e) {
if (agreeCheckbox.disabled || !agreeCheckbox.checked) { bookingForm.addEventListener('submit', function (e) {
alert('Please read and agree to the indemnity terms before booking.'); if (agreeCheckbox.disabled || !agreeCheckbox.checked) {
e.preventDefault(); // stop form submission alert('Please read and agree to the indemnity terms before booking.');
} e.preventDefault(); // stop form submission
}); }
</script> });
<script> </script>
$(document).ready(function() { <script>
// Function to calculate booking total $(document).ready(function() {
function calculateTotal() { // Function to calculate booking total
// Get selected values from the form function calculateTotal() {
var members = parseInt($('#members').val()) || 0; // Default to 1 vehicle if not selected // Get selected values from the form
var nonmembers = parseInt($('#non-members').val()) || 0; // Default to 1 adult if not selected var members = parseInt($('#members').val()) || 0; // Default to 1 vehicle if not selected
var nonmembers = parseInt($('#non-members').val()) || 0; // Default to 1 adult if not selected
// Fetch PHP variables
var isMember = <?php echo $is_member ? 'true' : 'false'; ?>; // Fetch PHP variables
var pendingMember = <?php echo $pending_member ? 'true' : 'false'; ?>; var isMember = <?php echo $is_member ? 'true' : 'false'; ?>;
var cost_members = <?= getPrice('bush_mechanics', 'member');?>; var pendingMember = <?php echo $pending_member ? 'true' : 'false'; ?>;
var cost_nonmembers = <?= getPrice('bush_mechanics', 'nonmember');?>; var cost_members = <?= getPrice('bush_mechanics', 'member');?>;
var cost_nonmembers = <?= getPrice('bush_mechanics', 'nonmember');?>;
// Calculate the total cost based on membership
var total = 0; // Calculate the total cost based on membership
var total = 0;
// Calculate cost for members
if (isMember || pendingMember) { // Calculate cost for members
total = (cost_members) + (members * cost_members) + (nonmembers * cost_nonmembers); if (isMember || pendingMember) {
} else { total = (cost_members) + (members * cost_members) + (nonmembers * cost_nonmembers);
// Calculate cost for non-members } else {
total = (cost_nonmembers) + (members * cost_members) + (nonmembers * cost_nonmembers); // Calculate cost for non-members
} total = (cost_nonmembers) + (members * cost_members) + (nonmembers * cost_nonmembers);
}
// Update total price in the DOM
$('#booking_total').text('R ' + total.toFixed(2)); // Update total price in the DOM
$('#booking_total').text('R ' + total.toFixed(2));
}
}
// Event listeners to trigger recalculation when any form field changes
$('#members, #non-members').on('change', function() { // Event listeners to trigger recalculation when any form field changes
calculateTotal(); $('#members, #non-members').on('change', function() {
}); calculateTotal();
});
// Initial calculation on page load
calculateTotal(); // Initial calculation on page load
}); calculateTotal();
</script> });
</script>
<?php include_once('insta_footer.php') ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php') ?>

View File

@@ -1,159 +1,159 @@
<?php <?php
if (!isset($page_id)) { if (!isset($page_id)) {
die("Page ID not set for comment system."); die("Page ID not set for comment system.");
} }
$conn = openDatabaseConnection(); $conn = openDatabaseConnection();
// Handle comment post // Handle comment post
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_comment'])) { if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_comment'])) {
// Validate CSRF token // Validate CSRF token
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) { if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
http_response_code(403); http_response_code(403);
die('Security token validation failed.'); die('Security token validation failed.');
} }
$comment = trim($_POST['comment'] ?? ''); $comment = trim($_POST['comment'] ?? '');
if (!empty($comment)) { if (!empty($comment)) {
$stmt = $conn->prepare("INSERT INTO comments (page_id, user_id, comment) VALUES (?, ?, ?)"); $stmt = $conn->prepare("INSERT INTO comments (page_id, user_id, comment) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $page_id, $user_id, $comment); $stmt->bind_param("sss", $page_id, $user_id, $comment);
if ($stmt->execute()) { if ($stmt->execute()) {
header("Location: " . $_SERVER['REQUEST_URI']); header("Location: " . $_SERVER['REQUEST_URI']);
exit; exit;
} }
} }
} }
// Fetch comments // Fetch comments
$stmt = $conn->prepare("SELECT user_id, comment, created_at FROM comments WHERE page_id = ? ORDER BY created_at DESC"); $stmt = $conn->prepare("SELECT user_id, comment, created_at FROM comments WHERE page_id = ? ORDER BY created_at DESC");
$stmt->bind_param("s", $page_id); $stmt->bind_param("s", $page_id);
$stmt->execute(); $stmt->execute();
$result = $stmt->get_result(); $result = $stmt->get_result();
?> ?>
<div> <div>
<h5>Comments</h5> <h5>Comments</h5>
<div class="comments"> <div class="comments">
<?php while ($row = $result->fetch_assoc()): ?> <?php while ($row = $result->fetch_assoc()): ?>
<div class="comment-body" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="comment-body" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div> <div>
<img class="profile-pic" src="<?= getProfilePic($user_id); ?>" alt="Author"> <img class="profile-pic" src="<?= getProfilePic($user_id); ?>" alt="Author">
</div> </div>
<div class=""> <div class="">
<h6><?= getFullName($row['user_id']); ?></h6> <h6><?= getFullName($row['user_id']); ?></h6>
<?php <?php
if (getUserMemberStatus($row['user_id'])){ if (getUserMemberStatus($row['user_id'])){
echo '<div class="badge badge-primary badge-pill">MEMBER</div>'; echo '<div class="badge badge-primary badge-pill">MEMBER</div>';
} }
?> ?>
<em><?= $row['created_at'] ?></em> <em><?= $row['created_at'] ?></em>
<!-- <div class="ratting"> <!-- <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star-half-alt"></i>
</div> --> </div> -->
<p><?= nl2br(htmlspecialchars($row['comment'])) ?></p> <p><?= nl2br(htmlspecialchars($row['comment'])) ?></p>
<!-- <a class="read-more" href="#">Reply <i class="far fa-angle-right"></i></a> --> <!-- <a class="read-more" href="#">Reply <i class="far fa-angle-right"></i></a> -->
</div> </div>
</div> </div>
<?php endwhile; ?> <?php endwhile; ?>
</form> </form>
<!-- <h5>Add A Comment</h5> --> <!-- <h5>Add A Comment</h5> -->
<form method="POST" id="comment-form" class="comment-form bgc-lighter z-1 rel mt-30" name="review-form" action="" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <form method="POST" id="comment-form" class="comment-form bgc-lighter z-1 rel mt-30" name="review-form" action="" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<div class="row gap-20"> <div class="row gap-20">
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<textarea name="comment" id="comment" class="form-control" rows="5" placeholder="Add comment..." required></textarea> <textarea name="comment" id="comment" class="form-control" rows="5" placeholder="Add comment..." required></textarea>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
<button type="submit" name="submit_comment" class="theme-btn bgc-secondary style-two"> <button type="submit" name="submit_comment" class="theme-btn bgc-secondary style-two">
<span data-hover="Submit reviews">Add comment</span> <span data-hover="Submit reviews">Add comment</span>
<i class="fal fa-arrow-right"></i> <i class="fal fa-arrow-right"></i>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<style> <style>
.comment-box { .comment-box {
border: 1px solid #ccc; border: 1px solid #ccc;
padding: 10px; padding: 10px;
max-width: 600px; max-width: 600px;
} }
.comment-box form input, .comment-box form input,
.comment-box form textarea { .comment-box form textarea {
width: 100%; width: 100%;
margin-bottom: 8px; margin-bottom: 8px;
} }
.comments-list { .comments-list {
margin-top: 20px; margin-top: 20px;
} }
.comment { .comment {
border-top: 1px solid #eee; border-top: 1px solid #eee;
padding-top: 10px; padding-top: 10px;
margin-top: 10px; margin-top: 10px;
} }
.profile-pic { .profile-pic {
width: 50px; width: 50px;
height: 50px; height: 50px;
border-radius: 50%; border-radius: 50%;
margin-right: 10px; margin-right: 10px;
object-fit: cover; object-fit: cover;
/* Ensures the image fits without distortion */ /* Ensures the image fits without distortion */
} }
.badge { .badge {
display: inline-block; display: inline-block;
padding: 0.4em 0.8em; padding: 0.4em 0.8em;
font-size: 0.875rem; font-size: 0.875rem;
font-weight: 600; font-weight: 600;
color: white; color: white;
border-radius: 0.375em; border-radius: 0.375em;
margin-right: 0.5em; margin-right: 0.5em;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.5px; letter-spacing: 0.5px;
} }
.badge-primary { .badge-primary {
background-color: #e90000; background-color: #e90000;
} }
.badge-success { .badge-success {
background-color: #28a745; background-color: #28a745;
} }
.badge-warning { .badge-warning {
background-color: #ffc107; background-color: #ffc107;
color: #212529; color: #212529;
} }
.badge-danger { .badge-danger {
background-color: #dc3545; background-color: #dc3545;
} }
.badge-info { .badge-info {
background-color: #17a2b8; background-color: #17a2b8;
} }
.badge-pill { .badge-pill {
border-radius: 999px; border-radius: 999px;
} }
</style> </style>

View File

@@ -1,111 +1,113 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php') ?> $rootPath = dirname(dirname(dirname(__DIR__)));
include_once($rootPath . '/header.php');
<style> ?>
.image {
width: 400px; <style>
/* Set your desired width */ .image {
height: 320px; width: 400px;
/* Set your desired height */ /* Set your desired width */
overflow: hidden; height: 320px;
/* Hide any overflow */ /* Set your desired height */
display: block; overflow: hidden;
/* Ensure proper block behavior */ /* Hide any overflow */
} display: block;
/* Ensure proper block behavior */
.image img { }
width: 100%;
/* Image scales to fill the container */ .image img {
height: 100%; width: 100%;
/* Image scales to fill the container */ /* Image scales to fill the container */
object-fit: cover; height: 100%;
/* Fills the container while maintaining aspect ratio */ /* Image scales to fill the container */
object-position: top; object-fit: cover;
/* Aligns the top of the image with the top of the container */ /* Fills the container while maintaining aspect ratio */
display: block; object-position: top;
/* Prevents inline whitespace issues */ /* Aligns the top of the image with the top of the container */
} display: block;
/* Prevents inline whitespace issues */
}
</style><?php </style><?php
$pageTitle = 'Contact Us'; $pageTitle = 'Contact Us';
$breadcrumbs = [['Home' => 'index.php']]; $breadcrumbs = [['Home' => 'index.php']];
require_once('components/banner.php'); require_once($rootPath . '/components/banner.php');
?> ?>
<!-- Contact Info Area start --> <!-- Contact Info Area start -->
<section class="contact-info-area pt-100 rel z-1"> <section class="contact-info-area pt-100 rel z-1">
<div class="container"> <div class="container">
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col-lg-4"> <div class="col-lg-4">
<div class="contact-info-content mb-30 rmb-55" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="contact-info-content mb-30 rmb-55" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="section-title mb-30"> <div class="section-title mb-30">
<h2>For any queries, please don't hesitate to contact us:</h2> <h2>For any queries, please don't hesitate to contact us:</h2>
</div> </div>
<!-- <p>Our dedicated support team is always ready to assist you with any questions or issues, offering prompt and personalized solutions to meet your needs.</p> --> <!-- <p>Our dedicated support team is always ready to assist you with any questions or issues, offering prompt and personalized solutions to meet your needs.</p> -->
<!-- <div class="features-team-box mt-40"> <!-- <div class="features-team-box mt-40">
<h6>85+ Expert Team member</h6> <h6>85+ Expert Team member</h6>
<div class="feature-authors"> <div class="feature-authors">
<img src="assets/images/features/feature-author1.jpg" alt="Author"> <img src="assets/images/features/feature-author1.jpg" alt="Author">
<img src="assets/images/features/feature-author2.jpg" alt="Author"> <img src="assets/images/features/feature-author2.jpg" alt="Author">
<img src="assets/images/features/feature-author3.jpg" alt="Author"> <img src="assets/images/features/feature-author3.jpg" alt="Author">
<img src="assets/images/features/feature-author4.jpg" alt="Author"> <img src="assets/images/features/feature-author4.jpg" alt="Author">
<img src="assets/images/features/feature-author5.jpg" alt="Author"> <img src="assets/images/features/feature-author5.jpg" alt="Author">
<img src="assets/images/features/feature-author6.jpg" alt="Author"> <img src="assets/images/features/feature-author6.jpg" alt="Author">
<img src="assets/images/features/feature-author7.jpg" alt="Author"> <img src="assets/images/features/feature-author7.jpg" alt="Author">
<span>+</span> <span>+</span>
</div> </div>
</div> --> </div> -->
</div> </div>
</div> </div>
<div class="col-lg-8"> <div class="col-lg-8">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="contact-info-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50"> <div class="contact-info-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50">
<div class="icon"><i class="fas fa-envelope"></i></div> <div class="icon"><i class="fas fa-envelope"></i></div>
<div class="content"> <div class="content">
<h5>Need Help & Support</h5> <h5>Need Help & Support</h5>
<div class="text"><i class="far fa-envelope"></i> <a href="mailto:info@4wdcsa.co.za">info@4wdcsa.co.za</a></div> <div class="text"><i class="far fa-envelope"></i> <a href="mailto:info@4wdcsa.co.za">info@4wdcsa.co.za</a></div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="contact-info-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100"> <div class="contact-info-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="100">
<div class="icon"><i class="fas fa-phone"></i></div> <div class="icon"><i class="fas fa-phone"></i></div>
<div class="content"> <div class="content">
<h5>Need Anything Urgent</h5> <h5>Need Anything Urgent</h5>
<div class="text"><i class="far fa-phone"></i> <a href="callto:+27 079 065 2795">+2779 065 2795</a></div> <div class="text"><i class="far fa-phone"></i> <a href="callto:+27 079 065 2795">+2779 065 2795</a></div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="contact-info-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50"> <div class="contact-info-item" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50" data-aos-delay="50">
<div class="icon"><i class="fas fa-map-marker-alt"></i></div> <div class="icon"><i class="fas fa-map-marker-alt"></i></div>
<div class="content"> <div class="content">
<h5>BASE 4</h5> <h5>BASE 4</h5>
<div class="text"><i class="fal fa-map-marker-alt"></i> Plot 50, Gemstone Rd, Doornrandje, Centurion, 0157</div> <div class="text"><i class="fal fa-map-marker-alt"></i> Plot 50, Gemstone Rd, Doornrandje, Centurion, 0157</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Contact Info Area end --> <!-- Contact Info Area end -->
<!-- Contact Form Area start --> <!-- Contact Form Area start -->
<!-- --> <!-- -->
<!-- Contact Form Area end --> <!-- Contact Form Area end -->
<!-- Contact Map Start --> <!-- Contact Map Start -->
<div class="contact-map"> <div class="contact-map">
<iframe src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d818.9371187805272!2d28.000391592597513!3d-25.864399472588936!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e1!3m2!1sen!2sza!4v1744639736430!5m2!1sen!2sza" style="border:0; width: 100%;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe> <iframe src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d818.9371187805272!2d28.000391592597513!3d-25.864399472588936!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e1!3m2!1sen!2sza!4v1744639736430!5m2!1sen!2sza" style="border:0; width: 100%;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
</div> </div>
<!-- Contact Map End --> <!-- Contact Map End -->
<?php include_once("insta_footer.php"); ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php'); ?>

View File

@@ -1,132 +1,133 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
// Assuming you have the user ID stored in the session include_once($rootPath . '/header.php');
if (isset($_SESSION['user_id'])) { // Assuming you have the user ID stored in the session
$user_id = $_SESSION['user_id']; if (isset($_SESSION['user_id'])) {
} else { $user_id = $_SESSION['user_id'];
header('Location: login.php'); } else {
exit(); // Stop further script execution header('Location: login.php');
} exit(); // Stop further script execution
?> }
?>
<style>
h2 { <style>
text-align: center; h2 {
margin-bottom: 20px; text-align: center;
} margin-bottom: 20px;
}
.indemnitycontainer {
max-width: 800px; .indemnitycontainer {
margin: 0 auto; max-width: 800px;
} margin: 0 auto;
}
.indemnity-text {
text-align: justify; .indemnity-text {
margin-bottom: 20px; text-align: justify;
} margin-bottom: 20px;
}
.signature-container {
margin-top: 30px; .signature-container {
margin-bottom: 100px; margin-top: 30px;
text-align: center; margin-bottom: 100px;
} text-align: center;
}
#signature-pad {
border: 1px solid black; #signature-pad {
border: 1px solid black;
}
</style> }
</style>
<?php <?php
$pageTitle = 'Indemnity'; $pageTitle = 'Indemnity';
$breadcrumbs = [['Home' => 'index.php']]; $breadcrumbs = [['Home' => 'index.php']];
require_once('components/banner.php'); require_once($rootPath . '/components/banner.php');
?> ?>
<!-- Page Banner End --> <!-- Page Banner End -->
<div class="indemnitycontainer pt-20"> <div class="indemnitycontainer pt-20">
<!-- <h2>Indemnity and Waiver</h2> --> <!-- <h2>Indemnity and Waiver</h2> -->
<div class="indemnity-text"> <div class="indemnity-text">
<p><strong>INDEMNITY AND WAIVER</strong></p> <p><strong>INDEMNITY AND WAIVER</strong></p>
<p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p> <p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p>
<p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p> <p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p>
<p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p> <p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p>
<p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p> <p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p>
<p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p> <p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p>
<p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p> <p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p>
<p><strong>BASE 4 CODE OF CONDUCT</strong></p> <p><strong>BASE 4 CODE OF CONDUCT</strong></p>
<p>1. No motorbikes or quadbikes.</p> <p>1. No motorbikes or quadbikes.</p>
<p>2. No loud music (unless authorised by the Committee or its representatives).</p> <p>2. No loud music (unless authorised by the Committee or its representatives).</p>
<p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p> <p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p>
<p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p> <p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p>
<p>5. No person in the rear of open vehicles when driving on obstacles.</p> <p>5. No person in the rear of open vehicles when driving on obstacles.</p>
<p>6. When driving the obstacles stay on the tracks.</p> <p>6. When driving the obstacles stay on the tracks.</p>
<p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p> <p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p>
<p>8. No alcohol to be consumed while driving the track.</p> <p>8. No alcohol to be consumed while driving the track.</p>
<p>9. No littering (please pick up cigarette butts etc.)</p> <p>9. No littering (please pick up cigarette butts etc.)</p>
<p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p> <p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p>
<p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p> <p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p>
<p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p> <p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p>
</div> </div>
<div class="signature-container"> <div class="signature-container">
<div style="text-align: center;" id="responseMessage"></div> <!-- Message display area --> <div style="text-align: center;" id="responseMessage"></div> <!-- Message display area -->
<p><strong>Signature</strong></p> <p><strong>Signature</strong></p>
<canvas id="signature-pad" width=400 height=200></canvas><br> <canvas id="signature-pad" width=400 height=200></canvas><br>
<button type="button" class="theme-btn style-two" id="save">ACCEPT INDEMNITY</button> <button type="button" class="theme-btn style-two" id="save">ACCEPT INDEMNITY</button>
<!-- <div class="pt-20" style="text-align: center;">You will be redirected to Payfast for payment.</div> --> <!-- <div class="pt-20" style="text-align: center;">You will be redirected to Payfast for payment.</div> -->
</div> </div>
</div> </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js"></script>
<script> <script>
var canvas = document.getElementById('signature-pad'); var canvas = document.getElementById('signature-pad');
var signaturePad = new SignaturePad(canvas); var signaturePad = new SignaturePad(canvas);
document.getElementById('save').addEventListener('click', function() { document.getElementById('save').addEventListener('click', function() {
if (signaturePad.isEmpty()) { if (signaturePad.isEmpty()) {
alert("Please provide a signature."); alert("Please provide a signature.");
} else { } else {
var dataUrl = signaturePad.toDataURL(); // Get signature as base64 image var dataUrl = signaturePad.toDataURL(); // Get signature as base64 image
$.ajax({ $.ajax({
url: 'process_signature.php', url: 'process_signature',
type: 'POST', type: 'POST',
data: { data: {
signature: dataUrl // Send the base64 signature image signature: dataUrl // Send the base64 signature image
}, },
success: function(response) { success: function(response) {
// Parse response if needed // Parse response if needed
if (typeof response === "string") { if (typeof response === "string") {
response = JSON.parse(response); response = JSON.parse(response);
} }
if (response.status === 'success') { if (response.status === 'success') {
// Check if the user has paid // Check if the user has paid
if (response.paymentStatus === 'PAID') { if (response.paymentStatus === 'PAID') {
// Redirect to membership_details.php if paid // Redirect to membership_details.php if paid
setTimeout(function() { setTimeout(function() {
window.location.href = 'membership_details.php'; window.location.href = 'membership_details.php';
}, 2000); // 2-second delay before redirecting }, 2000); // 2-second delay before redirecting
} else { } else {
// Redirect to membership_payment.php if not paid // Redirect to membership_payment.php if not paid
setTimeout(function() { setTimeout(function() {
window.location.href = 'membership_payment.php'; window.location.href = 'membership_payment.php';
}, 2000); // 2-second delay before redirecting }, 2000); // 2-second delay before redirecting
} }
} else { } else {
$('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>'); $('#responseMessage').html('<div class="alert alert-danger">' + response.message + '</div>');
} }
}, },
error: function() { error: function() {
$('#responseMessage').html('<div class="alert alert-danger">Error uploading signature.</div>'); $('#responseMessage').html('<div class="alert alert-danger">Error uploading signature.</div>');
} }
}); });
} }
}); });
</script> </script>
<?php include_once('insta_footer.php') ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php') ?>

View File

@@ -1,20 +1,20 @@
<p><strong>INDEMNITY AND WAIVER</strong></p> <p><strong>INDEMNITY AND WAIVER</strong></p>
<p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p> <p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p>
<p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p> <p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p>
<p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p> <p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p>
<p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p> <p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p>
<p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p> <p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p>
<p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p> <p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p>
<p><strong>BASE 4 CODE OF CONDUCT</strong></p> <p><strong>BASE 4 CODE OF CONDUCT</strong></p>
<p>1. No motorbikes or quadbikes.</p> <p>1. No motorbikes or quadbikes.</p>
<p>2. No loud music (unless authorised by the Committee or its representatives).</p> <p>2. No loud music (unless authorised by the Committee or its representatives).</p>
<p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p> <p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p>
<p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p> <p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p>
<p>5. No person in the rear of open vehicles when driving on obstacles.</p> <p>5. No person in the rear of open vehicles when driving on obstacles.</p>
<p>6. When driving the obstacles stay on the tracks.</p> <p>6. When driving the obstacles stay on the tracks.</p>
<p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p> <p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p>
<p>8. No alcohol to be consumed while driving the track.</p> <p>8. No alcohol to be consumed while driving the track.</p>
<p>9. No littering (please pick up cigarette butts etc.)</p> <p>9. No littering (please pick up cigarette butts etc.)</p>
<p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p> <p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p>
<p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p> <p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p>
<p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p> <p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p>

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,14 @@
<div class="container my-4"> <div class="container my-4">
<div class="row justify-content-center align-items-center g-3"> <div class="row justify-content-center align-items-center g-3">
<?php <?php
$sponsorDir = 'assets/images/sponsors/'; $sponsorDir = 'assets/images/sponsors/';
$sponsorImages = glob($sponsorDir . '*.{jpg,jpeg,png,gif,svg,webp}', GLOB_BRACE); $sponsorImages = glob($sponsorDir . '*.{jpg,jpeg,png,gif,svg,webp}', GLOB_BRACE);
foreach ($sponsorImages as $img) { foreach ($sponsorImages as $img) {
echo " echo "
<div class='col-auto'> <div class='col-auto'>
<img src='$img' alt='Sponsor logo' style='max-height:120px; max-width:240px; object-fit:contain;'> <img src='$img' alt='Sponsor logo' style='max-height:120px; max-width:240px; object-fit:contain;'>
</div>"; </div>";
} }
?> ?>
</div> </div>
</div> </div>

View File

@@ -1,91 +1,91 @@
<?php <?php
require_once("env.php"); require_once("env.php");
require_once("session.php"); require_once("session.php");
require_once("connection.php"); require_once("connection.php");
require_once("functions.php");?> require_once("functions.php");?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modal with AJAX Dropdown</title> <title>Modal with AJAX Dropdown</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head> </head>
<body> <body>
<div class="container mt-5"> <div class="container mt-5">
<!-- Button to trigger modal --> <!-- Button to trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#userModal"> <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#userModal">
Open Modal Open Modal
</button> </button>
</div> </div>
<!-- Modal --> <!-- Modal -->
<div class="modal fade" id="userModal" tabindex="-1" aria-labelledby="userModalLabel" aria-hidden="true"> <div class="modal fade" id="userModal" tabindex="-1" aria-labelledby="userModalLabel" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="userModalLabel">Select a User</h5> <h5 class="modal-title" id="userModalLabel">Select a User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form id="barTabForm"> <form id="barTabForm">
<div class="mb-3"> <div class="mb-3">
<label for="userSelect" class="form-label">Choose a User</label> <label for="userSelect" class="form-label">Choose a User</label>
<select class="form-select" id="userSelect" name="user_id" required> <select class="form-select" id="userSelect" name="user_id" required>
<option value="">Loading...</option> <option value="">Loading...</option>
</select> </select>
</div> </div>
<button type="submit" class="btn btn-success">Create Bar Tab</button> <button type="submit" class="btn btn-success">Create Bar Tab</button>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
// Load users into dropdown when modal opens // Load users into dropdown when modal opens
$('#userModal').on('shown.bs.modal', function () { $('#userModal').on('shown.bs.modal', function () {
$.ajax({ $.ajax({
url: 'fetch_users.php', url: 'fetch_users',
method: 'GET', method: 'GET',
dataType: 'json', dataType: 'json',
success: function (data) { success: function (data) {
let dropdown = $('#userSelect'); let dropdown = $('#userSelect');
dropdown.empty(); dropdown.empty();
dropdown.append('<option value="">Select a user</option>'); dropdown.append('<option value="">Select a user</option>');
data.forEach(user => { data.forEach(user => {
dropdown.append(`<option value="${user.id}">${user.first_name} ${user.last_name}</option>`); dropdown.append(`<option value="${user.id}">${user.first_name} ${user.last_name}</option>`);
}); });
}, },
error: function () { error: function () {
alert('Error fetching users.'); alert('Error fetching users.');
} }
}); });
}); });
// Handle form submission // Handle form submission
$('#barTabForm').submit(function (e) { $('#barTabForm').submit(function (e) {
e.preventDefault(); // Prevent default form submission e.preventDefault(); // Prevent default form submission
$.ajax({ $.ajax({
url: 'create_bar_tab.php', url: 'create_bar_tab',
method: 'POST', method: 'POST',
data: $(this).serialize(), data: $(this).serialize(),
success: function (response) { success: function (response) {
alert('Bar tab created successfully!'); alert('Bar tab created successfully!');
$('#userModal').modal('hide'); // Close modal $('#userModal').modal('hide'); // Close modal
}, },
error: function () { error: function () {
alert('Error creating bar tab.'); alert('Error creating bar tab.');
} }
}); });
}); });
}); });
</script> </script>
</body> </body>
</html> </html>

File diff suppressed because one or more lines are too long

View File

@@ -1,316 +1,317 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); $rootPath = dirname(dirname(dirname(__DIR__)));
checkUserSession(); include_once($rootPath . '/header.php');
checkUserSession();
// SQL query to fetch dates for rescue & recovery
$stmt = $conn->prepare("SELECT course_id, date FROM courses WHERE course_type = ? AND date >= CURDATE()"); // SQL query to fetch dates for rescue & recovery
$course_type = 'rescue_recovery'; $stmt = $conn->prepare("SELECT course_id, date FROM courses WHERE course_type = ? AND date >= CURDATE()");
$stmt->bind_param("s", $course_type); $course_type = 'rescue_recovery';
$stmt->execute(); $stmt->bind_param("s", $course_type);
$result = $stmt->get_result(); $stmt->execute();
$page_id = 'rescue_recovery'; $result = $stmt->get_result();
?> $page_id = 'rescue_recovery';
?>
<style>
.form-group { <style>
margin-bottom: 15px; .form-group {
} margin-bottom: 15px;
}
select {
width: 100%; select {
padding: 8px; width: 100%;
font-size: 16px; padding: 8px;
} font-size: 16px;
</style><?php }
$pageTitle = 'Rescue & Recovery'; </style><?php
$breadcrumbs = [['Home' => 'index.php']]; $pageTitle = 'Rescue & Recovery';
require_once('components/banner.php'); $breadcrumbs = [['Home' => 'index.php']];
?> require_once($rootPath . '/components/banner.php');
?>
<!-- Product Details Start -->
<section class="product-details pt-100"> <!-- Product Details Start -->
<div class="container"> <section class="product-details pt-100">
<div class="row"> <div class="container">
<div class="col-lg-6"> <div class="row">
<div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6">
<div class="tab-content preview-images"> <div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="tab-pane fade preview-item active show" id="preview1"> <div class="tab-content preview-images">
<img src="assets/images/drivertraining/01.jpg" alt="Perview"> <div class="tab-pane fade preview-item active show" id="preview1">
</div> <img src="assets/images/drivertraining/01.jpg" alt="Perview">
<div class="tab-pane fade preview-item" id="preview2"> </div>
<img src="assets/images/drivertraining/02.jpg" alt="Perview"> <div class="tab-pane fade preview-item" id="preview2">
</div> <img src="assets/images/drivertraining/02.jpg" alt="Perview">
<div class="tab-pane fade preview-item" id="preview3"> </div>
<img src="assets/images/drivertraining/03.jpg" alt="Perview"> <div class="tab-pane fade preview-item" id="preview3">
</div> <img src="assets/images/drivertraining/03.jpg" alt="Perview">
</div> </div>
<div class="nav thumb-images rmb-20"> </div>
<a href="#preview1" data-bs-toggle="tab" class="thumb-item active show"> <div class="nav thumb-images rmb-20">
<img src="assets/images/drivertraining/01.jpg" alt="Thumb"> <a href="#preview1" data-bs-toggle="tab" class="thumb-item active show">
</a> <img src="assets/images/drivertraining/01.jpg" alt="Thumb">
<a href="#preview2" data-bs-toggle="tab" class="thumb-item"> </a>
<img src="assets/images/drivertraining/02.jpg" alt="Thumb"> <a href="#preview2" data-bs-toggle="tab" class="thumb-item">
</a> <img src="assets/images/drivertraining/02.jpg" alt="Thumb">
<a href="#preview3" data-bs-toggle="tab" class="thumb-item"> </a>
<img src="assets/images/drivertraining/03.jpg" alt="Thumb"> <a href="#preview3" data-bs-toggle="tab" class="thumb-item">
</a> <img src="assets/images/drivertraining/03.jpg" alt="Thumb">
</div> </a>
</div> </div>
</div> </div>
<div class="col-lg-6"> </div>
<div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6">
<div class="section-title"> <div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<h2>Rescue & Recovery</h2> <div class="section-title">
</div> <h2>Rescue & Recovery</h2>
<!-- <div class="ratting mb-15"> </div>
<i class="fas fa-star"></i> <!-- <div class="ratting mb-15">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star"></i>
<span>(5.8k+ reviews)</span> <i class="fas fa-star-half-alt"></i>
</div> --> <span>(5.8k+ reviews)</span>
<span class="price mb-5">R <?= getPrice('rescue_recovery', 'member'); ?>/member</span> </div> -->
<span class="price mb-25">R <?= getPrice('rescue_recovery', 'nonmember'); ?>/non-members</span> <span class="price mb-5">R <?= getPrice('rescue_recovery', 'member'); ?>/member</span>
<p> This is an enjoyable, educational, and informative day. This one-day course is a natural follow-on from our 4x4 driving course and introduces drivers to safe off-road recovery procedures, equipment and also their responsibilities in regards to caring for the environment.</p> <span class="price mb-25">R <?= getPrice('rescue_recovery', 'nonmember'); ?>/non-members</span>
<hr class="mt-40"> <p> This is an enjoyable, educational, and informative day. This one-day course is a natural follow-on from our 4x4 driving course and introduces drivers to safe off-road recovery procedures, equipment and also their responsibilities in regards to caring for the environment.</p>
<div class="blog-sidebar tour-sidebar"> <hr class="mt-40">
<div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="blog-sidebar tour-sidebar">
<form action="process_course_booking.php" method="POST"> <div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<ul class="tickets clearfix"> <form action="process_course_booking" method="POST">
<li> <ul class="tickets clearfix">
Select Date <li>
<select name="course_id" id="course_id" required> Select Date
<?php <select name="course_id" id="course_id" required>
if ($result->num_rows > 0) { <?php
// Output each course as an option if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { // Output each course as an option
$course_id = htmlspecialchars($row['course_id']); // Escape output for security while ($row = $result->fetch_assoc()) {
$date = htmlspecialchars($row['date']); // Escape output for security $course_id = htmlspecialchars($row['course_id']); // Escape output for security
echo "<option value='$course_id'>$date</option>"; $date = htmlspecialchars($row['date']); // Escape output for security
} echo "<option value='$course_id'>$date</option>";
} else { }
echo "<option value='' disabled>No dates available</option>"; } else {
} echo "<option value='' disabled>No dates available</option>";
?> }
</select> ?>
</li> </select>
<?php </li>
if ($is_member || $pending_member) { <?php
echo ' if ($is_member || $pending_member) {
<li> echo '
Additional Members <span class="price"></span> <li>
<select name="members" id="members"> Additional Members <span class="price"></span>
<option value="0" selected>00</option> <select name="members" id="members">
<option value="1">01</option> <option value="0" selected>00</option>
<option value="2">02</option> <option value="1">01</option>
<option value="3">03</option> <option value="2">02</option>
</select> <option value="3">03</option>
</li> </select>
'; </li>
} ?> ';
} ?>
<li>
Additional Non-Members <span class="price"></span> <li>
<select name="non-members" id="non-members"> Additional Non-Members <span class="price"></span>
<option value="0" selected>00</option> <select name="non-members" id="non-members">
<option value="1">01</option> <option value="0" selected>00</option>
<option value="2">02</option> <option value="1">01</option>
<option value="3">03</option> <option value="2">02</option>
</select> <option value="3">03</option>
</li> </select>
</ul> </li>
<hr class="mb-25"> </ul>
<hr class="mb-25">
<h6>Total: <span id="booking_total" class="price">-</span></h6>
<div style="margin: 20px 0;"> <h6>Total: <span id="booking_total" class="price">-</span></h6>
<div id="indemnityBox" style="border: 1px solid #ccc; padding: 10px; height: 150px; overflow-y: scroll; background: #f9f9f9; font-size: 12px;"> <div style="margin: 20px 0;">
<p><strong>INDEMNITY AND WAIVER</strong></p> <div id="indemnityBox" style="border: 1px solid #ccc; padding: 10px; height: 150px; overflow-y: scroll; background: #f9f9f9; font-size: 12px;">
<p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p> <p><strong>INDEMNITY AND WAIVER</strong></p>
<p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p> <p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p>
<p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p> <p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p>
<p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p> <p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p>
<p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p> <p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p>
<p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p> <p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p>
<p><strong>BASE 4 CODE OF CONDUCT</strong></p> <p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p>
<p>1. No motorbikes or quadbikes.</p> <p><strong>BASE 4 CODE OF CONDUCT</strong></p>
<p>2. No loud music (unless authorised by the Committee or its representatives).</p> <p>1. No motorbikes or quadbikes.</p>
<p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p> <p>2. No loud music (unless authorised by the Committee or its representatives).</p>
<p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p> <p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p>
<p>5. No person in the rear of open vehicles when driving on obstacles.</p> <p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p>
<p>6. When driving the obstacles stay on the tracks.</p> <p>5. No person in the rear of open vehicles when driving on obstacles.</p>
<p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p> <p>6. When driving the obstacles stay on the tracks.</p>
<p>8. No alcohol to be consumed while driving the track.</p> <p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p>
<p>9. No littering (please pick up cigarette butts etc.)</p> <p>8. No alcohol to be consumed while driving the track.</p>
<p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p> <p>9. No littering (please pick up cigarette butts etc.)</p>
<p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p> <p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p>
<p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p> <p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p>
</div> <p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p>
<div style="margin-top: 10px;"> </div>
<input type="checkbox" id="agreeCheckbox" name="agree" disabled required> <div style="margin-top: 10px;">
<label for="agreeCheckbox" id="agreeLabel" style="color: #888;">I have read and agree to the indemnity terms</label> <input type="checkbox" id="agreeCheckbox" name="agree" disabled required>
</div> <label for="agreeCheckbox" id="agreeLabel" style="color: #888;">I have read and agree to the indemnity terms</label>
</div> </div>
<?php </div>
$button_text = "Book Now"; <?php
$button_disabled = ""; $button_text = "Book Now";
if (!$result || $result->num_rows == 0) { $button_disabled = "";
$button_text = "No booking dates available"; if (!$result || $result->num_rows == 0) {
$button_disabled = "disabled"; $button_text = "No booking dates available";
} $button_disabled = "disabled";
?> }
<button type="submit" class="theme-btn style-two w-100 mt-15 mb-5" <?php echo $button_disabled; ?>> ?>
<span data-hover="<?php echo $button_text; ?>"><?php echo $button_text; ?></span> <button type="submit" class="theme-btn style-two w-100 mt-15 mb-5" <?php echo $button_disabled; ?>>
<i class="fal fa-arrow-right"></i> <span data-hover="<?php echo $button_text; ?>"><?php echo $button_text; ?></span>
</button> <i class="fal fa-arrow-right"></i>
<div class="text-center"> </button>
<a href="mailto:info@4wdcsa.co.za">Need some help?</a> <div class="text-center">
</div> <a href="mailto:info@4wdcsa.co.za">Need some help?</a>
</form> </div>
</div> </form>
</div>
</div>
<!-- <hr class="mb-45"> --> </div>
<!-- <a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a> --> <!-- <hr class="mb-45"> -->
</div> <!-- <a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a> -->
</div> </div>
</div> </div>
<ul class="nav nav product-tab mt-70 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> </div>
<li><a href="#details" data-bs-toggle="tab" class="active show">Course Overview<i class="far fa-arrow-right"></i></a></li> <ul class="nav nav product-tab mt-70 mb-30" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<li><a href="#information" data-bs-toggle="tab">What to Expect<i class="far fa-arrow-right"></i></a></li> <li><a href="#details" data-bs-toggle="tab" class="active show">Course Overview<i class="far fa-arrow-right"></i></a></li>
<li><a href="#reviews" data-bs-toggle="tab"> Reviews <i class="far fa-arrow-right"></i></a></li> <li><a href="#information" data-bs-toggle="tab">What to Expect<i class="far fa-arrow-right"></i></a></li>
</ul> <li><a href="#reviews" data-bs-toggle="tab"> Reviews <i class="far fa-arrow-right"></i></a></li>
<div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50"> </ul>
<div class="tab-pane fade active show" id="details"> <div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
<div class="container my-5"> <div class="tab-pane fade active show" id="details">
<h5>The course introduces and guides participants in the following:</h5> <div class="container my-5">
<ul > <h5>The course introduces and guides participants in the following:</h5>
<li>Correct selection, size and purchase of equipment such as Shackles, Slings, Chains and Snatch Blocks.</li> <ul >
<li>Correct selection of Pull Straps and Kinetic Straps.</li> <li>Correct selection, size and purchase of equipment such as Shackles, Slings, Chains and Snatch Blocks.</li>
<li>Importance of Safety Slings, Safety Blankets and the correct use of Bridles.</li> <li>Correct selection of Pull Straps and Kinetic Straps.</li>
<li> <li>Importance of Safety Slings, Safety Blankets and the correct use of Bridles.</li>
Importance of secondary equipment such as:</li> <li>
<ul> Importance of secondary equipment such as:</li>
<li>Puncture Repair Kits</li> <ul>
<li>Tyre Pressure Gauges</li> <li>Puncture Repair Kits</li>
<li>Compressors</li> <li>Tyre Pressure Gauges</li>
<li>Fire Extinguishers</li> <li>Compressors</li>
</ul> <li>Fire Extinguishers</li>
</ul>
</ul>
</ul>
<h5>The day also covers the practical instruction in the following:</h5>
<ul class="list-unstyled ms-4" style="list-style-type: disc;"> <h5>The day also covers the practical instruction in the following:</h5>
<li>Use of Pull straps and Kinetic Straps</li> <ul class="list-unstyled ms-4" style="list-style-type: disc;">
<li>Recovery Points and their importance.</li> <li>Use of Pull straps and Kinetic Straps</li>
<li>Jacking of vehicles OEM, High Lift, Bottle Jacks and Scissor Jacks.</li> <li>Recovery Points and their importance.</li>
<li>Correct use of Winches including the accessories.</li> <li>Jacking of vehicles OEM, High Lift, Bottle Jacks and Scissor Jacks.</li>
</ul> <li>Correct use of Winches including the accessories.</li>
<h5>The day culminates with an impressive demonstration of a kinetic strap failure and the repercussion.</h5> </ul>
<p><strong>PLEASE NOTE </strong>- <i>Recovery equipment is provided for use by participants during the course. If you already have your own equipment, you are welcome to make use of it during training.</i></p> <h5>The day culminates with an impressive demonstration of a kinetic strap failure and the repercussion.</h5>
<p>Please bring your own lunch and refreshments, sun hats and sunblock.</p> <p><strong>PLEASE NOTE </strong>- <i>Recovery equipment is provided for use by participants during the course. If you already have your own equipment, you are welcome to make use of it during training.</i></p>
</div> <p>Please bring your own lunch and refreshments, sun hats and sunblock.</p>
</div>
<div class="row gap-50 pt-25 pb-20 align-items-center">
<div class="col-lg-7 pt-15"> <div class="row gap-50 pt-25 pb-20 align-items-center">
<h5>What this course includes</h5> <div class="col-lg-7 pt-15">
<ul class="list-style-two mt-25"> <h5>What this course includes</h5>
<li>Rescue & Recovery Manual.</li> <ul class="list-style-two mt-25">
<li>Theory session and discussion.</li> <li>Rescue & Recovery Manual.</li>
<li>Spend the afternoon practicing common techniques of advanced rescue and recovery.</li> <li>Theory session and discussion.</li>
</ul> <li>Spend the afternoon practicing common techniques of advanced rescue and recovery.</li>
</div> </ul>
<div class="col-lg-5"> </div>
<div class="image rmt-45"> <div class="col-lg-5">
<img src="assets/images/drivertraining/04.jpg" alt="Product Details"> <div class="image rmt-45">
</div> <img src="assets/images/drivertraining/04.jpg" alt="Product Details">
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="information"> </div>
<!-- <p>Circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses</p> --> <div class="tab-pane fade" id="information">
<ul class="list-style-two my-35"> <!-- <p>Circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses</p> -->
<li>Coffee and Welcome: Kick off the day with a warm coffee, meet your instructors, and receive an overview of the course schedule</li> <ul class="list-style-two my-35">
<li>Theory Session: Dive into the key principles of off-road driving, including vehicle mechanics, terrain navigation, recovery methods, and safety protocols.</li> <li>Coffee and Welcome: Kick off the day with a warm coffee, meet your instructors, and receive an overview of the course schedule</li>
<li>Practical Demonstrations: Watch live demonstrations covering vital techniques like gear selection, adjusting tire pressure, and setting up recovery equipment.</li> <li>Theory Session: Dive into the key principles of off-road driving, including vehicle mechanics, terrain navigation, recovery methods, and safety protocols.</li>
<li>Lunch Break: Enjoy a packed lunch or bring something to braai. Fires will be provided for an authentic outdoor experience.</li> <li>Practical Demonstrations: Watch live demonstrations covering vital techniques like gear selection, adjusting tire pressure, and setting up recovery equipment.</li>
<li>Track Driving and Practical Training: Test your skills with hands-on driving exercises on a custom-built off-road track, learning how to tackle different obstacles and terrain challenges.</li> <li>Lunch Break: Enjoy a packed lunch or bring something to braai. Fires will be provided for an authentic outdoor experience.</li>
<li>Debrief and Certificates: Conclude the day with a review of your progress, feedback from the instructors, and certificates of completion for your off-road training.</li> <li>Track Driving and Practical Training: Test your skills with hands-on driving exercises on a custom-built off-road track, learning how to tackle different obstacles and terrain challenges.</li>
</ul> <li>Debrief and Certificates: Conclude the day with a review of your progress, feedback from the instructors, and certificates of completion for your off-road training.</li>
</div> </ul>
<div class="tab-pane fade mb-20" id="reviews"> </div>
<?php include_once('review_box.php'); ?> <div class="tab-pane fade mb-20" id="reviews">
</div> <?php include_once('review_box.php'); ?>
</div> </div>
</div> </div>
</section> </div>
</section>
<!-- Shop Details Area end -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <!-- Shop Details Area end -->
<script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
const indemnityBox = document.getElementById('indemnityBox'); <script>
const agreeCheckbox = document.getElementById('agreeCheckbox'); const indemnityBox = document.getElementById('indemnityBox');
const bookingForm = document.querySelector('form'); const agreeCheckbox = document.getElementById('agreeCheckbox');
const bookingForm = document.querySelector('form');
indemnityBox.addEventListener('scroll', function() {
const scrollTop = indemnityBox.scrollTop; indemnityBox.addEventListener('scroll', function() {
const scrollHeight = indemnityBox.scrollHeight; const scrollTop = indemnityBox.scrollTop;
const offsetHeight = indemnityBox.offsetHeight; const scrollHeight = indemnityBox.scrollHeight;
const offsetHeight = indemnityBox.offsetHeight;
// Enable checkbox when scrolled to bottom
if (scrollTop + offsetHeight >= scrollHeight - 1) { // Enable checkbox when scrolled to bottom
agreeCheckbox.disabled = false; if (scrollTop + offsetHeight >= scrollHeight - 1) {
document.getElementById('agreeLabel').style.color = "#000"; // optional: make label active agreeCheckbox.disabled = false;
} document.getElementById('agreeLabel').style.color = "#000"; // optional: make label active
}); }
});
bookingForm.addEventListener('submit', function(e) {
if (agreeCheckbox.disabled || !agreeCheckbox.checked) { bookingForm.addEventListener('submit', function(e) {
alert('Please read and agree to the indemnity terms before booking.'); if (agreeCheckbox.disabled || !agreeCheckbox.checked) {
e.preventDefault(); // stop form submission alert('Please read and agree to the indemnity terms before booking.');
} e.preventDefault(); // stop form submission
}); }
</script> });
<script> </script>
$(document).ready(function() { <script>
// Function to calculate booking total $(document).ready(function() {
function calculateTotal() { // Function to calculate booking total
// Get selected values from the form function calculateTotal() {
var members = parseInt($('#members').val()) || 0; // Default to 1 vehicle if not selected // Get selected values from the form
var nonmembers = parseInt($('#non-members').val()) || 0; // Default to 1 adult if not selected var members = parseInt($('#members').val()) || 0; // Default to 1 vehicle if not selected
var nonmembers = parseInt($('#non-members').val()) || 0; // Default to 1 adult if not selected
// Fetch PHP variables
var isMember = <?php echo $is_member ? 'true' : 'false'; ?>; // Fetch PHP variables
var pendingMember = <?php echo $pending_member ? 'true' : 'false'; ?>; var isMember = <?php echo $is_member ? 'true' : 'false'; ?>;
var cost_members = <?= getPrice('rescue_recovery', 'member'); ?>; var pendingMember = <?php echo $pending_member ? 'true' : 'false'; ?>;
var cost_nonmembers = <?= getPrice('rescue_recovery', 'nonmember'); ?>; var cost_members = <?= getPrice('rescue_recovery', 'member'); ?>;
var cost_nonmembers = <?= getPrice('rescue_recovery', 'nonmember'); ?>;
// Calculate the total cost based on membership
var total = 0; // Calculate the total cost based on membership
var total = 0;
// Calculate cost for members
if (isMember || pendingMember) { // Calculate cost for members
total = (cost_members) + (members * cost_members) + (nonmembers * cost_nonmembers); if (isMember || pendingMember) {
} else { total = (cost_members) + (members * cost_members) + (nonmembers * cost_nonmembers);
// Calculate cost for non-members } else {
total = (cost_nonmembers) + (members * cost_members) + (nonmembers * cost_nonmembers); // Calculate cost for non-members
} total = (cost_nonmembers) + (members * cost_members) + (nonmembers * cost_nonmembers);
}
// Update total price in the DOM
$('#booking_total').text('R ' + total.toFixed(2)); // Update total price in the DOM
$('#booking_total').text('R ' + total.toFixed(2));
}
}
// Event listeners to trigger recalculation when any form field changes
$('#members, #non-members').on('change', function() { // Event listeners to trigger recalculation when any form field changes
calculateTotal(); $('#members, #non-members').on('change', function() {
}); calculateTotal();
});
// Initial calculation on page load
calculateTotal(); // Initial calculation on page load
}); calculateTotal();
</script> });
</script>
<?php include_once('insta_footer.php') ?>
<?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php') ?>

View File

@@ -1,152 +1,152 @@
<?php <?php
if (!isset($page_id)) { if (!isset($page_id)) {
die("Page ID not set for comment system."); die("Page ID not set for comment system.");
} }
$conn = openDatabaseConnection(); $conn = openDatabaseConnection();
// Handle comment post // Handle comment post
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_comment'])) { if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_comment'])) {
$comment = $conn->real_escape_string(trim($_POST['comment'])); $comment = $conn->real_escape_string(trim($_POST['comment']));
if (!empty($comment)) { if (!empty($comment)) {
$stmt = $conn->prepare("INSERT INTO comments (page_id, user_id, comment) VALUES (?, ?, ?)"); $stmt = $conn->prepare("INSERT INTO comments (page_id, user_id, comment) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $page_id, $user_id, $comment); $stmt->bind_param("sss", $page_id, $user_id, $comment);
if ($stmt->execute()) { if ($stmt->execute()) {
header("Location: " . $_SERVER['REQUEST_URI']); header("Location: " . $_SERVER['REQUEST_URI']);
exit; exit;
} }
} }
} }
// Fetch comments // Fetch comments
$stmt = $conn->prepare("SELECT user_id, comment, created_at FROM comments WHERE page_id = ? ORDER BY created_at DESC"); $stmt = $conn->prepare("SELECT user_id, comment, created_at FROM comments WHERE page_id = ? ORDER BY created_at DESC");
$stmt->bind_param("s", $page_id); $stmt->bind_param("s", $page_id);
$stmt->execute(); $stmt->execute();
$result = $stmt->get_result(); $result = $stmt->get_result();
?> ?>
<div> <div>
<h5>Reviews</h5> <h5>Reviews</h5>
<div class="comments my-30"> <div class="comments my-30">
<?php while ($row = $result->fetch_assoc()): ?> <?php while ($row = $result->fetch_assoc()): ?>
<div class="comment-body" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <div class="comment-body" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div> <div>
<img class="profile-pic" src="<?= getProfilePic($user_id); ?>" alt="Author"> <img class="profile-pic" src="<?= getProfilePic($user_id); ?>" alt="Author">
</div> </div>
<div class="content"> <div class="content">
<h6><?= getFullName($row['user_id']); ?></h6> <h6><?= getFullName($row['user_id']); ?></h6>
<?php <?php
if (getUserMemberStatus($row['user_id'])){ if (getUserMemberStatus($row['user_id'])){
echo '<div class="badge badge-primary badge-pill">MEMBER</div>'; echo '<div class="badge badge-primary badge-pill">MEMBER</div>';
} }
?> ?>
<em><?= $row['created_at'] ?></em> <em><?= $row['created_at'] ?></em>
<!-- <div class="ratting"> <!-- <div class="ratting">
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star"></i> <i class="fas fa-star"></i>
<i class="fas fa-star-half-alt"></i> <i class="fas fa-star-half-alt"></i>
</div> --> </div> -->
<p><?= nl2br(htmlspecialchars($row['comment'])) ?></p> <p><?= nl2br(htmlspecialchars($row['comment'])) ?></p>
<!-- <a class="read-more" href="#">Reply <i class="far fa-angle-right"></i></a> --> <!-- <a class="read-more" href="#">Reply <i class="far fa-angle-right"></i></a> -->
</div> </div>
</div> </div>
<?php endwhile; ?> <?php endwhile; ?>
</div> </div>
<h5>Add A Review</h5> <h5>Add A Review</h5>
<form method="POST" id="comment-form" class="comment-form bgc-lighter z-1 rel mt-30" name="review-form" action="" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50"> <form method="POST" id="comment-form" class="comment-form bgc-lighter z-1 rel mt-30" name="review-form" action="" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="row gap-20"> <div class="row gap-20">
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<textarea name="comment" id="comment" class="form-control" rows="5" placeholder="Add review..." required></textarea> <textarea name="comment" id="comment" class="form-control" rows="5" placeholder="Add review..." required></textarea>
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
<button type="submit" name="submit_comment" class="theme-btn bgc-secondary style-two"> <button type="submit" name="submit_comment" class="theme-btn bgc-secondary style-two">
<span data-hover="Submit reviews">Submit review</span> <span data-hover="Submit reviews">Submit review</span>
<i class="fal fa-arrow-right"></i> <i class="fal fa-arrow-right"></i>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<style> <style>
.comment-box { .comment-box {
border: 1px solid #ccc; border: 1px solid #ccc;
padding: 10px; padding: 10px;
max-width: 600px; max-width: 600px;
} }
.comment-box form input, .comment-box form input,
.comment-box form textarea { .comment-box form textarea {
width: 100%; width: 100%;
margin-bottom: 8px; margin-bottom: 8px;
} }
.comments-list { .comments-list {
margin-top: 20px; margin-top: 20px;
} }
.comment { .comment {
border-top: 1px solid #eee; border-top: 1px solid #eee;
padding-top: 10px; padding-top: 10px;
margin-top: 10px; margin-top: 10px;
} }
.profile-pic { .profile-pic {
width: 50px; width: 50px;
height: 50px; height: 50px;
border-radius: 50%; border-radius: 50%;
margin-right: 10px; margin-right: 10px;
object-fit: cover; object-fit: cover;
/* Ensures the image fits without distortion */ /* Ensures the image fits without distortion */
} }
.badge { .badge {
display: inline-block; display: inline-block;
padding: 0.4em 0.8em; padding: 0.4em 0.8em;
font-size: 0.875rem; font-size: 0.875rem;
font-weight: 600; font-weight: 600;
color: white; color: white;
border-radius: 0.375em; border-radius: 0.375em;
margin-right: 0.5em; margin-right: 0.5em;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.5px; letter-spacing: 0.5px;
} }
.badge-primary { .badge-primary {
background-color: #e90000; background-color: #e90000;
} }
.badge-success { .badge-success {
background-color: #28a745; background-color: #28a745;
} }
.badge-warning { .badge-warning {
background-color: #ffc107; background-color: #ffc107;
color: #212529; color: #212529;
} }
.badge-danger { .badge-danger {
background-color: #dc3545; background-color: #dc3545;
} }
.badge-info { .badge-info {
background-color: #17a2b8; background-color: #17a2b8;
} }
.badge-pill { .badge-pill {
border-radius: 999px; border-radius: 999px;
} }
</style> </style>

View File

@@ -1,104 +1,104 @@
<?php <?php
$headerStyle = 'light'; $headerStyle = 'light';
include_once('header.php'); include_once(dirname(dirname(dirname(__DIR__))) . '/header.php');
// Assuming you have the user ID stored in the session // Assuming you have the user ID stored in the session
if (isset($_SESSION['user_id'])) { if (isset($_SESSION['user_id'])) {
$user_id = $_SESSION['user_id']; $user_id = $_SESSION['user_id'];
} else { } else {
header('Location: login.php'); header('Location: login.php');
exit(); // Stop further script execution exit(); // Stop further script execution
} }
?> ?>
<style> <style>
h2 { h2 {
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: 20px;
} }
.indemnitycontainer { .indemnitycontainer {
max-width: 800px; max-width: 800px;
margin: 0 auto; margin: 0 auto;
} }
.indemnity-text { .indemnity-text {
text-align: justify; text-align: justify;
margin-bottom: 20px; margin-bottom: 20px;
} }
.signature-container { .signature-container {
margin-top: 30px; margin-top: 30px;
margin-bottom: 100px; margin-bottom: 100px;
text-align: center; text-align: center;
} }
#signature-pad { #signature-pad {
border: 1px solid black; border: 1px solid black;
} }
</style> </style>
<!-- Page Banner Start --> <!-- Page Banner Start -->
<?php <?php
$bannerFolder = 'assets/images/banners/'; $bannerFolder = 'assets/images/banners/';
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE); $bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
$randomBanner = 'assets/images/base4/camping.jpg'; // default fallback $randomBanner = 'assets/images/base4/camping.jpg'; // default fallback
if (!empty($bannerImages)) { if (!empty($bannerImages)) {
$randomBanner = $bannerImages[array_rand($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; ?>');"> <section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="container"> <div class="container">
<div class="banner-inner text-white"> <div class="banner-inner text-white">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">Indemnity</h2> <h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">Indemnity</h2>
<nav aria-label="breadcrumb"> <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"> <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"><a href="index">Home</a></li>
<li class="breadcrumb-item ">Membership</li> <li class="breadcrumb-item ">Membership</li>
<li class="breadcrumb-item active">Indemnity</li> <li class="breadcrumb-item active">Indemnity</li>
</ol> </ol>
</nav> </nav>
</div> </div>
</div> </div>
</section> </section>
<!-- Page Banner End --> <!-- Page Banner End -->
<div class="indemnitycontainer pt-20"> <div class="indemnitycontainer pt-20">
<!-- <h2>Indemnity and Waiver</h2> --> <!-- <h2>Indemnity and Waiver</h2> -->
<div class="indemnity-text"> <div class="indemnity-text">
<p><strong>INDEMNITY AND WAIVER</strong></p> <p><strong>INDEMNITY AND WAIVER</strong></p>
<p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p> <p>1. I agree to abide by the Code of Conduct as listed below, as well as any reasonable instructions given by any Member of the Committee of the Club, or any person appointed by the Club to organise or control any event (Club Officer).</p>
<p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p> <p>2. I acknowledge that driving the off-road track is inherently dangerous, and that I am fully aware of the dangers thereof. I warrant that I will make all members of my party aware of such dangers prior to driving the track.</p>
<p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p> <p>3. While I, or any member of my party, enjoy the facilities at Base 4 including overnight camping, picnicking, driving the track, using the swimming pool facility or activity or any other activity while at Base 4, I agree that under no circumstances shall the Club be liable for any loss or damage of any kind whatsoever (including consequential loss) which I or any of my party may suffer, regardless of how such loss or damage may have been caused or sustained, and whether or not as a result of the negligence or breach of contract (whether fundamental or otherwise) or other wrongful act of the Club, or any Club Officer, or any of the Clubs agents or contractors, and I hereby indemnify and hold harmless the Club and any Club Officer against all such loss or damage.</p>
<p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p> <p>4. The expression, member of my party, means all persons who accompany me or attending any event at my specific invitation, request or suggestion, and includes without limitation, members of family, guests and invitees.</p>
<p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p> <p>5. I understand that I am responsible for ensuring my vehicle and equipment and that all members of my party have adequate health and medical insurance to cover any and all likely occurrences.</p>
<p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p> <p>6. This indemnity is irrevocable and shall apply to me and the members of my party for any Club events in which I may participate or attend.</p>
<p><strong>BASE 4 CODE OF CONDUCT</strong></p> <p><strong>BASE 4 CODE OF CONDUCT</strong></p>
<p>1. No motorbikes or quadbikes.</p> <p>1. No motorbikes or quadbikes.</p>
<p>2. No loud music (unless authorised by the Committee or its representatives).</p> <p>2. No loud music (unless authorised by the Committee or its representatives).</p>
<p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p> <p>3. Dogs to be controlled by their owners who take full responsibility for the animals behaviour.</p>
<p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p> <p>4. No dogs belonging to non-members are allowed at Base 4 unless with the express permission of the Committee.</p>
<p>5. No person in the rear of open vehicles when driving on obstacles.</p> <p>5. No person in the rear of open vehicles when driving on obstacles.</p>
<p>6. When driving the obstacles stay on the tracks.</p> <p>6. When driving the obstacles stay on the tracks.</p>
<p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p> <p>7. Engage 4WD when driving the obstacles to minimise wear and damage to the track.</p>
<p>8. No alcohol to be consumed while driving the track.</p> <p>8. No alcohol to be consumed while driving the track.</p>
<p>9. No littering (please pick up cigarette butts etc.)</p> <p>9. No littering (please pick up cigarette butts etc.)</p>
<p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p> <p>10. All rubbish is to be taken away with you when leaving. Dustbins and refuse collection is not provided.</p>
<p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p> <p>11. Use water sparingly. Please bring your own water and a little extra for the Club.</p>
<p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p> <p>I am a member of the Four Wheel Drive Club of Southern Africa and I will strive to uphold these Codes.</p>
</div> </div>
<div class="signature-container"> <div class="signature-container">
<div style="text-align: center;" id="responseMessage"></div> <!-- Message display area --> <div style="text-align: center;" id="responseMessage"></div> <!-- Message display area -->
<p><strong>Signature</strong></p> <p><strong>Signature</strong></p>
<img src="uploads/signatures/signature_<?php echo $user_id;?>.png" alt="Signature" width="200"> <img src="uploads/signatures/signature_<?php echo $user_id;?>.png" alt="Signature" width="200">
</div> </div>
</div> </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js"></script>
<?php include_once('insta_footer.php') ?> <?php include_once(dirname(dirname(dirname(__DIR__))) . '/components/insta_footer.php') ?>

Some files were not shown because too many files have changed in this diff Show More