- Added photo gallery carousel view (gallery.php) with all member albums - Implemented album detail view with responsive photo grid and lightbox - Created album creation/editing form with drag-and-drop photo uploads - Added backend processors for album CRUD operations and photo management - Implemented API endpoints for fetching and deleting photos - Added database migration for photo_albums and photos tables - Included comprehensive feature documentation with testing checklist - Updated .htaccess with URL rewrite rules for gallery routes - Added Gallery link to Members Area menu in header - Created upload directory structure (/assets/uploads/gallery/) - Implemented security: CSRF tokens, ownership verification, file validation - Added transaction safety with rollback on errors and cleanup - Features: Lightbox with keyboard navigation, drag-and-drop uploads, responsive design
382 lines
16 KiB
PHP
382 lines
16 KiB
PHP
<?php
|
|
/**
|
|
* UNIFIED HEADER TEMPLATE
|
|
*
|
|
* Replaces header01.php and header02.php with a single configurable template.
|
|
*
|
|
* Usage:
|
|
* $headerStyle = 'dark'; // or 'light'
|
|
* require_once("header.php");
|
|
*
|
|
* Styles:
|
|
* 'dark' = White text on dark background (header01 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
|
|
$headerStyle = $headerStyle ?? 'light';
|
|
|
|
// Use absolute paths based on this file's location
|
|
$rootDir = dirname(__FILE__);
|
|
require_once($rootDir . "/src/config/env.php");
|
|
require_once($rootDir . "/src/config/session.php");
|
|
require_once($rootDir . "/src/config/connection.php");
|
|
require_once($rootDir . "/src/config/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();
|
|
|
|
// Determine styling based on headerStyle parameter
|
|
$headerClasses = 'main-header header-one';
|
|
$headerBgClass = '';
|
|
$logoImg = 'assets/images/logos/logo.png';
|
|
$mobileLogoImg = 'assets/images/logos/logo.png';
|
|
$textColor = '#fff'; // Default for dark style
|
|
$btnTextColor = '#fff';
|
|
|
|
if ($headerStyle === 'light') {
|
|
$headerBgClass = 'bg-white';
|
|
$logoImg = 'assets/images/logos/logo-two.png';
|
|
$mobileLogoImg = 'assets/images/logos/logo-two.png';
|
|
$textColor = '#111111';
|
|
$btnTextColor = '#111111';
|
|
} else {
|
|
// Dark style
|
|
$headerClasses .= ' white-menu menu-absolute';
|
|
$headerBgClass = '';
|
|
}
|
|
?>
|
|
|
|
<!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>
|
|
<?php if ($headerStyle === 'light'): ?>
|
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
<?php endif; ?>
|
|
<!-- 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">
|
|
<?php if ($headerStyle === 'light'): ?>
|
|
<!-- jQuery UI -->
|
|
<link rel="stylesheet" href="assets/css/jquery-ui.min.css">
|
|
<?php endif; ?>
|
|
<!-- Animate -->
|
|
<link rel="stylesheet" href="assets/css/aos.css">
|
|
<?php if ($headerStyle === 'light'): ?>
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.css" onload="AOS.init();">
|
|
<?php endif; ?>
|
|
<!-- Slick -->
|
|
<link rel="stylesheet" href="assets/css/slick.min.css">
|
|
<!-- Main Style -->
|
|
<link rel="stylesheet" href="assets/css/style_new.css<?php echo ($headerStyle === 'dark') ? '?v=1' : ''; ?>">
|
|
<?php if ($headerStyle === 'dark'): ?>
|
|
<link rel="stylesheet" href="header_css.css">
|
|
<?php endif; ?>
|
|
|
|
<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: <?php echo ($headerStyle === 'light') ? '2px 2px 5px 1px rgba(0, 0, 0, 0.1), -2px 0px 5px 1px rgba(0, 0, 0, 0.1)' : '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;
|
|
}
|
|
|
|
<?php if ($headerStyle === 'light'): ?>
|
|
.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;
|
|
}
|
|
<?php endif; ?>
|
|
</style>
|
|
|
|
<body>
|
|
<div class="page-wrapper">
|
|
|
|
<!-- Preloader -->
|
|
<div class="preloader">
|
|
<div class="custom-loader"></div>
|
|
</div>
|
|
|
|
<!-- main header -->
|
|
<header class="<?php echo $headerClasses; ?>">
|
|
<!--Header-Upper-->
|
|
<div class="header-upper <?php echo $headerBgClass; ?> 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" style="width:200px;"><a href="index"><img src="<?php echo $logoImg; ?>" 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">
|
|
<img src="<?php echo $mobileLogoImg; ?>" 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">Home</a></li>
|
|
<li><a href="about">About</a></li>
|
|
<li><a href="trips">Trips</a>
|
|
<?php if ($headerStyle === 'dark'): ?>
|
|
<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">Tour Details</a></li>
|
|
<li><a href="tour-guide.html">Tour Guide</a></li>
|
|
</ul>
|
|
<?php endif; ?>
|
|
</li>
|
|
<li class="dropdown"><a href="#">Training</a>
|
|
<ul>
|
|
<li><a href="driver_training">Basic 4X4 Driver Training</a></li>
|
|
<li><a href="bush_mechanics">Bush Mechanics</a></li>
|
|
<li><a href="rescue_recovery">Rescue & Recovery</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="events">Events</a></li>
|
|
<li><a href="blog">Blog</a></li>
|
|
<?php if ($role === 'admin' || $role === 'superadmin') { ?>
|
|
<li class="dropdown"><a href="#">admin</a>
|
|
<ul>
|
|
<li><a href="admin_web_users">Website Users</a></li>
|
|
<li><a href="admin_members">4WDCSA Members</a></li>
|
|
<li><a href="admin_events">Manage Events</a></li>
|
|
<li><a href="admin_trips">Manage Trips</a></li>
|
|
<li><a href="admin_trip_bookings">Trip Bookings</a></li>
|
|
<li><a href="admin_course_bookings">Course Bookings</a></li>
|
|
<li><a href="admin_efts">EFT Payments</a></li>
|
|
<li><a href="process_payments">Process Payments</a></li>
|
|
<?php if ($role === 'superadmin') { ?>
|
|
<li><a href="admin_visitors">Visitor Log</a></li>
|
|
<?php } ?>
|
|
</ul>
|
|
</li>
|
|
<?php } ?>
|
|
<li><a href="contact">Contact</a></li>
|
|
<?php if ($is_logged_in) : ?>
|
|
<li class="dropdown"><a href="#">Members Area</a>
|
|
<ul>
|
|
<?php
|
|
if (getUserMemberStatus($_SESSION['user_id'])) {
|
|
echo "<li><a href=\"campsites\">Campsites Directory</a></li>";
|
|
echo "<li><a href=\"gallery\">Photo Gallery</a></li>";
|
|
} else {
|
|
echo "<li><a href=\"membership\">Campsites Directory</a><i class='fal fa-lock'></i></li>";
|
|
echo "<li><a href=\"membership\">Photo Gallery</a><i class='fal fa-lock'></i></li>";
|
|
}
|
|
?>
|
|
</ul>
|
|
</li>
|
|
|
|
|
|
|
|
<li class="dropdown"><a href="#">My Account</a>
|
|
<ul>
|
|
<li><a href="account_settings">Account Settings</a></li>
|
|
<li><a href="membership_details">Membership</a></li>
|
|
<li><a href="bookings">My Bookings</a></li>
|
|
<li><a href="submit_pop">Submit P.O.P</a></li>
|
|
<li><a href="logout">Log Out</a></li>
|
|
</ul>
|
|
</li>
|
|
<?php else : ?>
|
|
<li class="nav-item d-xl-none"><a href="login">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: <?php echo $textColor; ?>;">Welcome, <?php echo $_SESSION['first_name']; ?></span>
|
|
<a href="account_settings">
|
|
<img src="<?php echo $_SESSION['profile_pic']; ?>?v=<?php echo time(); ?>" alt="Profile Picture" class="profile-pic">
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<?php else : ?>
|
|
<a href="login" 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; ?>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--End Header Upper-->
|
|
</header>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const profileInfo = document.querySelector('.profile-info');
|
|
if (profileInfo) {
|
|
profileInfo.addEventListener('click', function(event) {
|
|
const dropdownMenu = document.querySelector('.dropdown-menu2');
|
|
if (dropdownMenu) {
|
|
dropdownMenu.style.display = dropdownMenu.style.display === 'block' ? 'none' : 'block';
|
|
event.stopPropagation();
|
|
}
|
|
});
|
|
}
|
|
|
|
document.addEventListener('click', function(event) {
|
|
const dropdownMenu = document.querySelector('.dropdown-menu2');
|
|
const profileMenu = document.querySelector('.profile-menu');
|
|
if (profileMenu && dropdownMenu && !profileMenu.contains(event.target)) {
|
|
dropdownMenu.style.display = 'none';
|
|
}
|
|
});
|
|
});
|
|
</script>
|