Files
4WDCSA.co.za/rescue_recovery.php
twotalesanimation 4c839d02c0 Standardize: Convert final 4 queries to prepared statements - ALL COMPLETE
Converted final queries in:
- bush_mechanics.php - Course query
- rescue_recovery.php - Course query
- admin_members.php - Membership applications query

COMPLETION STATUS:  All 21 instances of $conn->query() converted to prepared statements

Files updated: 14
  Functions.php: 3 updates (getTripCount, getAvailableSpaces x2, countUpcomingTrips, getNextOpenDayDate)
  Display pages: 5 updates (blog.php, course_details.php, driver_training.php, events.php, index.php)
  Data pages: 2 updates (campsites.php, admin_members.php)
  AJAX handlers: 2 updates (fetch_users.php, get_campsites.php)
  Course pages: 3 updates (bush_mechanics.php, rescue_recovery.php)

Benefits:
 Consistent prepared statement usage across codebase
 Better protection against SQL injection (even hardcoded queries benefit from parameter binding)
 Cleaner, more maintainable code
 Foundation set for Phase 2 standardization
2025-12-03 19:41:34 +02:00

316 lines
20 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
$headerStyle = 'light';
include_once('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()");
$course_type = 'rescue_recovery';
$stmt->bind_param("s", $course_type);
$stmt->execute();
$result = $stmt->get_result();
$page_id = 'rescue_recovery';
?>
<style>
.form-group {
margin-bottom: 15px;
}
select {
width: 100%;
padding: 8px;
font-size: 16px;
}
</style><?php
$pageTitle = 'Rescue & Recovery';
$breadcrumbs = [['Home' => 'index.php']];
require_once('components/banner.php');
?>
<!-- Product Details Start -->
<section class="product-details pt-100">
<div class="container">
<div class="row">
<div class="col-lg-6">
<div class="product-details-images rmb-55" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
<div class="tab-content preview-images">
<div class="tab-pane fade preview-item active show" id="preview1">
<img src="assets/images/drivertraining/01.jpg" alt="Perview">
</div>
<div class="tab-pane fade preview-item" id="preview2">
<img src="assets/images/drivertraining/02.jpg" alt="Perview">
</div>
<div class="tab-pane fade preview-item" id="preview3">
<img src="assets/images/drivertraining/03.jpg" alt="Perview">
</div>
</div>
<div class="nav thumb-images rmb-20">
<a href="#preview1" data-bs-toggle="tab" class="thumb-item active show">
<img src="assets/images/drivertraining/01.jpg" alt="Thumb">
</a>
<a href="#preview2" data-bs-toggle="tab" class="thumb-item">
<img src="assets/images/drivertraining/02.jpg" alt="Thumb">
</a>
<a href="#preview3" data-bs-toggle="tab" class="thumb-item">
<img src="assets/images/drivertraining/03.jpg" alt="Thumb">
</a>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="product-details-content" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">
<div class="section-title">
<h2>Rescue & Recovery</h2>
</div>
<!-- <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-half-alt"></i>
<span>(5.8k+ reviews)</span>
</div> -->
<span class="price mb-5">R <?= getPrice('rescue_recovery', 'member'); ?>/member</span>
<span class="price mb-25">R <?= getPrice('rescue_recovery', 'nonmember'); ?>/non-members</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>
<hr class="mt-40">
<div class="blog-sidebar tour-sidebar">
<div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<form action="process_course_booking.php" method="POST">
<ul class="tickets clearfix">
<li>
Select Date
<select name="course_id" id="course_id" required>
<?php
if ($result->num_rows > 0) {
// Output each course as an option
while ($row = $result->fetch_assoc()) {
$course_id = htmlspecialchars($row['course_id']); // Escape output for security
$date = htmlspecialchars($row['date']); // Escape output for security
echo "<option value='$course_id'>$date</option>";
}
} else {
echo "<option value='' disabled>No dates available</option>";
}
?>
</select>
</li>
<?php
if ($is_member || $pending_member) {
echo '
<li>
Additional Members <span class="price"></span>
<select name="members" id="members">
<option value="0" selected>00</option>
<option value="1">01</option>
<option value="2">02</option>
<option value="3">03</option>
</select>
</li>
';
} ?>
<li>
Additional Non-Members <span class="price"></span>
<select name="non-members" id="non-members">
<option value="0" selected>00</option>
<option value="1">01</option>
<option value="2">02</option>
<option value="3">03</option>
</select>
</li>
</ul>
<hr class="mb-25">
<h6>Total: <span id="booking_total" class="price">-</span></h6>
<div style="margin: 20px 0;">
<div id="indemnityBox" style="border: 1px solid #ccc; padding: 10px; height: 150px; overflow-y: scroll; background: #f9f9f9; font-size: 12px;">
<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>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>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>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>1. No motorbikes or quadbikes.</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>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>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>8. No alcohol to be consumed while driving the track.</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>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>
</div>
<div style="margin-top: 10px;">
<input type="checkbox" id="agreeCheckbox" name="agree" disabled required>
<label for="agreeCheckbox" id="agreeLabel" style="color: #888;">I have read and agree to the indemnity terms</label>
</div>
</div>
<?php
$button_text = "Book Now";
$button_disabled = "";
if (!$result || $result->num_rows == 0) {
$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>
<i class="fal fa-arrow-right"></i>
</button>
<div class="text-center">
<a href="mailto:info@4wdcsa.co.za">Need some help?</a>
</div>
</form>
</div>
</div>
<!-- <hr class="mb-45"> -->
<!-- <a href="#" class="wishlist"><i class="far fa-heart"></i> Add to Wishlist</a> -->
</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">
<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="#information" data-bs-toggle="tab">What to Expect<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>
</ul>
<div class="tab-content" data-aos="fade-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
<div class="tab-pane fade active show" id="details">
<div class="container my-5">
<h5>The course introduces and guides participants in the following:</h5>
<ul >
<li>Correct selection, size and purchase of equipment such as Shackles, Slings, Chains and Snatch Blocks.</li>
<li>Correct selection of Pull Straps and Kinetic Straps.</li>
<li>Importance of Safety Slings, Safety Blankets and the correct use of Bridles.</li>
<li>
Importance of secondary equipment such as:</li>
<ul>
<li>Puncture Repair Kits</li>
<li>Tyre Pressure Gauges</li>
<li>Compressors</li>
<li>Fire Extinguishers</li>
</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;">
<li>Use of Pull straps and Kinetic Straps</li>
<li>Recovery Points and their importance.</li>
<li>Jacking of vehicles OEM, High Lift, Bottle Jacks and Scissor Jacks.</li>
<li>Correct use of Winches including the accessories.</li>
</ul>
<h5>The day culminates with an impressive demonstration of a kinetic strap failure and the repercussion.</h5>
<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>
<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">
<h5>What this course includes</h5>
<ul class="list-style-two mt-25">
<li>Rescue & Recovery Manual.</li>
<li>Theory session and discussion.</li>
<li>Spend the afternoon practicing common techniques of advanced rescue and recovery.</li>
</ul>
</div>
<div class="col-lg-5">
<div class="image rmt-45">
<img src="assets/images/drivertraining/04.jpg" alt="Product Details">
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="information">
<!-- <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> -->
<ul class="list-style-two my-35">
<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>Theory Session: Dive into the key principles of off-road driving, including vehicle mechanics, terrain navigation, recovery methods, and safety protocols.</li>
<li>Practical Demonstrations: Watch live demonstrations covering vital techniques like gear selection, adjusting tire pressure, and setting up recovery equipment.</li>
<li>Lunch Break: Enjoy a packed lunch or bring something to braai. Fires will be provided for an authentic outdoor experience.</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>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>
<div class="tab-pane fade mb-20" id="reviews">
<?php include_once('review_box.php'); ?>
</div>
</div>
</div>
</section>
<!-- Shop Details Area end -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
const indemnityBox = document.getElementById('indemnityBox');
const agreeCheckbox = document.getElementById('agreeCheckbox');
const bookingForm = document.querySelector('form');
indemnityBox.addEventListener('scroll', function() {
const scrollTop = indemnityBox.scrollTop;
const scrollHeight = indemnityBox.scrollHeight;
const offsetHeight = indemnityBox.offsetHeight;
// Enable checkbox when scrolled to bottom
if (scrollTop + offsetHeight >= scrollHeight - 1) {
agreeCheckbox.disabled = false;
document.getElementById('agreeLabel').style.color = "#000"; // optional: make label active
}
});
bookingForm.addEventListener('submit', function(e) {
if (agreeCheckbox.disabled || !agreeCheckbox.checked) {
alert('Please read and agree to the indemnity terms before booking.');
e.preventDefault(); // stop form submission
}
});
</script>
<script>
$(document).ready(function() {
// Function to calculate booking total
function calculateTotal() {
// Get selected values from the form
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'; ?>;
var pendingMember = <?php echo $pending_member ? 'true' : 'false'; ?>;
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 cost for members
if (isMember || pendingMember) {
total = (cost_members) + (members * cost_members) + (nonmembers * cost_nonmembers);
} else {
// 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));
}
// Event listeners to trigger recalculation when any form field changes
$('#members, #non-members').on('change', function() {
calculateTotal();
});
// Initial calculation on page load
calculateTotal();
});
</script>
<?php include_once('insta_footer.php') ?>