<?php
// Include database connection if not already included
if (!isset($conn)) {
require_once __DIR__ . "/../config/database.php";
}
// Define safe_query function if it doesn't exist
if (!function_exists('safe_query')) {
function safe_query($conn, $sql, $params = []) {
try {
if (empty($params)) {
return $conn->query($sql);
} else {
$stmt = $conn->prepare($sql);
if ($stmt === false) {
throw new Exception("Failed to prepare statement: " . $conn->error);
}
if (!empty($params)) {
$types = '';
foreach ($params as $param) {
if (is_int($param)) {
$types .= 'i';
} elseif (is_float($param)) {
$types .= 'd';
} elseif (is_string($param)) {
$types .= 's';
} else {
$types .= 'b';
}
}
$stmt->bind_param($types, ...$params);
}
$stmt->execute();
return $stmt->get_result();
}
} catch (Exception $e) {
error_log("Database query error: " . $e->getMessage());
return false;
}
}
}
// Fetch sliders from database
$sliders = [];
try {
// Check if the sliders table exists first
$table_check = "SHOW TABLES LIKE 'sliders'";
$table_exists = safe_query($conn, $table_check);
if ($table_exists && $table_exists->num_rows > 0) {
$sql = "SELECT * FROM sliders WHERE status = 'active' ORDER BY sort_order ASC";
$result = safe_query($conn, $sql);
if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$sliders[] = $row;
}
}
}
} catch (Exception $e) {
// Log the error but continue with default sliders
error_log("Hero slider database error: " . $e->getMessage());
// Empty the sliders array in case of error
$sliders = [];
}
// Use default sliders if none found in database or if table doesn't exist
if (empty($sliders)) {
// Check if default slider images exist
$default_images = [
'assets/img/slider/default-slide-1.jpg',
'assets/img/slider/default-slide-2.jpg',
'assets/img/slider/default-slide-3.jpg'
];
// Create the slider directory if it doesn't exist
$slider_dir = __DIR__ . '/../assets/img/slider';
if (!file_exists($slider_dir)) {
mkdir($slider_dir, 0755, true);
}
// Validate image paths and replace with placeholder if missing
foreach ($default_images as $index => $image) {
if (!file_exists(__DIR__ . '/../' . $image)) {
$default_images[$index] = 'https://via.placeholder.com/1920x1080/4e73df/ffffff?text=Slide+' . ($index + 1);
}
}
$sliders = [
[
'id' => 1,
'title' => 'Empowering Future Technology Leaders',
'subtitle' => 'Cutting-edge technology courses for modern careers',
'description' => 'Our courses are designed by industry experts to prepare you for the challenges of tomorrow\'s technology landscape.',
'content_type' => 'image',
'media_url' => $default_images[0],
'button_text' => 'Explore Courses',
'button_url' => 'courses.php',
'overlay_color' => 'rgba(0, 0, 0, 0.4)',
'text_color' => '#ffffff',
'animation' => 'zoom'
],
[
'id' => 2,
'title' => 'Learn From Industry Experts',
'subtitle' => 'Get certified with our professional courses',
'description' => 'Join our community of learners and gain practical skills taught by professionals with years of industry experience.',
'content_type' => 'image',
'media_url' => $default_images[1],
'button_text' => 'Join Now',
'button_url' => 'register.php',
'overlay_color' => 'rgba(0, 36, 125, 0.5)',
'text_color' => '#ffffff',
'animation' => 'fade'
],
[
'id' => 3,
'title' => 'Achieve Your Career Goals',
'subtitle' => 'Practical skills for real-world success',
'description' => 'Transform your career with our comprehensive curriculum focused on building job-ready skills for today\'s market.',
'content_type' => 'image',
'media_url' => $default_images[2],
'button_text' => 'Get Started',
'button_url' => 'courses.php',
'overlay_color' => 'rgba(28, 35, 49, 0.6)',
'text_color' => '#ffffff',
'animation' => 'slide'
]
];
}
?>
<!-- Check if Swiper JS is loaded, if not, load it -->
<script>
if (typeof Swiper === 'undefined') {
// If Swiper isn't loaded, add the required scripts and styles
document.write('<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.css">');
document.write('<script src="https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.js"><\/script>');
}
</script>
<style>
/* Hero Slider Styles */
.hero-slider-wrapper {
/* margin-bottom: 40px; */
}
.hero-slider-wrapper .hero-slider-container {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
box-shadow: 0 15px 50px rgba(0, 0, 0, 0.1);
/* border-radius: 0 0 20px 20px; */
}
.hero-slider-wrapper .hero-slider {
width: 100%;
height: 100%;
}
.hero-slider-wrapper .hero-slide {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.hero-slider-wrapper .slide-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
transition: transform 10s ease;
}
.hero-slider-wrapper .slide-video-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.hero-slider-wrapper .slide-video {
position: absolute;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
transform: translate(-50%, -50%);
object-fit: cover;
}
.hero-slider-wrapper .slide-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.2);
}
.hero-slider-wrapper .slide-content {
position: relative;
z-index: 10;
max-width: 1200px;
width: 100%;
padding: 0 30px;
text-align: center;
color: #fff;
}
.hero-slider-wrapper .slide-subtitle {
display: block;
font-size: 18px;
font-weight: 500;
margin-bottom: 15px;
opacity: 0;
transform: translateY(20px);
transition: opacity 0.5s ease, transform 0.5s ease;
}
.hero-slider-wrapper .slide-title {
font-size: 48px;
font-weight: 700;
margin-bottom: 20px;
opacity: 0;
transform: translateY(20px);
transition: opacity 0.5s ease, transform 0.5s ease;
line-height: 1.2;
}
.hero-slider-wrapper .slide-description {
font-size: 20px;
max-width: 800px;
margin: 0 auto 30px;
opacity: 0;
transform: translateY(20px);
transition: opacity 0.5s ease, transform 0.5s ease;
}
.swiper-pagination-bullets.swiper-pagination-horizontal{
bottom: 0;
top: 0;
left: 0;
width: auto;
}
.hero-slider-wrapper .slide-button {
display: inline-flex;
align-items: center;
padding: 12px 30px;
background-color: #3498db;
color: #fff;
text-decoration: none;
border-radius: 5px;
font-weight: 600;
transition: all 0.3s ease;
opacity: 0;
transform: translateY(20px);
}
.hero-slider-wrapper .slide-button span {
margin-right: 10px;
}
.hero-slider-wrapper .slide-button:hover {
background-color: #2980b9;
transform: translateY(-5px);
}
/* Navigation Styles */
.hero-slider-wrapper .slider-navigation {
position: absolute;
bottom: 30px;
left: 0;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
}
.hero-slider-wrapper .nav-button {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.3);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
cursor: pointer;
transition: all 0.3s ease;
margin: 0 15px;
}
.hero-slider-wrapper .nav-button:hover {
background-color: rgba(255, 255, 255, 0.5);
transform: scale(1.1);
}
.hero-slider-wrapper .custom-pagination {
/* display: flex; */
align-items: center;
}
.hero-slider-wrapper .pagination-item {
width: 30px;
height: 4px;
background-color: rgba(255, 255, 255, 0.3);
margin: 0 5px;
cursor: pointer;
position: relative;
overflow: hidden;
border-radius: 2px;
transition: all 0.3s ease;
}
.hero-slider-wrapper .pagination-item:hover {
background-color: rgba(255, 255, 255, 0.5);
}
.hero-slider-wrapper .pagination-item.active {
background-color: rgba(255, 255, 255, 0.7);
width: 40px;
}
.swiper-pagination {
position: relative;
}
.hero-slider-wrapper .pagination-progress {
position: relative;
top: 0;
left: 0;
height: 100%;
width: 0;
background-color: #fff;
transition: width 5s linear;
}
/* Animation Classes */
.hero-slider-wrapper .animate-fade .slide-image {
animation: fadeIn 1s forwards;
}
.hero-slider-wrapper .animate-zoom .slide-image {
animation: zoomIn 10s forwards;
}
.hero-slider-wrapper .animate-slide .slide-image {
animation: slideIn 1s forwards;
}
.hero-slider-wrapper .slide-content .animate-in {
opacity: 1;
transform: translateY(0);
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes zoomIn {
0% {
transform: scale(1);
}
100% {
transform: scale(1.1);
}
}
@keyframes slideIn {
0% {
transform: translateX(-5%);
}
100% {
transform: translateX(0);
}
}
/* Responsive Styles */
@media (max-width: 991px) {
.hero-slider-wrapper .hero-slider-container {
height: 500px;
}
.hero-slider-wrapper .slide-title {
font-size: 36px;
}
.hero-slider-wrapper .slide-description {
font-size: 18px;
}
}
@media (max-width: 767px) {
.hero-slider-wrapper .hero-slider-container {
height: 400px;
}
.hero-slider-wrapper .slide-title {
font-size: 28px;
}
.hero-slider-wrapper .slide-subtitle {
font-size: 16px;
}
.hero-slider-wrapper .slide-description {
font-size: 16px;
margin-bottom: 20px;
}
.hero-slider-wrapper .nav-button {
width: 40px;
height: 40px;
}
}
@media (max-width: 575px) {
.hero-slider-wrapper .hero-slider-container {
height: 350px;
}
.hero-slider-wrapper .slide-title {
font-size: 24px;
margin-bottom: 10px;
}
.hero-slider-wrapper .slide-subtitle {
font-size: 14px;
margin-bottom: 8px;
}
.hero-slider-wrapper .slide-description {
display: none;
}
.hero-slider-wrapper .slide-button {
padding: 10px 20px;
font-size: 14px;
}
}
/* Fix for slider display issues */
.hero-slider-wrapper .swiper-slide-active .slide-content * {
transition-delay: 0.5s;
}
.hero-slider-wrapper .swiper-slide-active .slide-subtitle {
transition-delay: 0.7s;
}
.hero-slider-wrapper .swiper-slide-active .slide-title {
transition-delay: 0.9s;
}
.hero-slider-wrapper .swiper-slide-active .slide-description {
transition-delay: 1.1s;
}
.hero-slider-wrapper .swiper-slide-active .slide-button {
transition-delay: 1.3s;
}
/* Fixed height for swiper container */
.hero-slider-wrapper .swiper,
.hero-slider-wrapper .swiper-wrapper,
.hero-slider-wrapper .swiper-slide {
height: 100%;
}
</style>
<!-- Hero Slider Section -->
<div class="hero-slider-wrapper">
<div class="hero-slider-container">
<div class="hero-slider swiper">
<div class="swiper-wrapper">
<?php foreach ($sliders as $slider): ?>
<div class="swiper-slide hero-slide"
data-animation="<?php echo htmlspecialchars($slider['animation'] ?? 'fade'); ?>">
<!-- Content: Image or Video -->
<?php if (($slider['content_type'] ?? 'image') == 'video'): ?>
<div class="slide-video-container">
<video class="slide-video" autoplay muted loop playsinline>
<source src="<?php echo htmlspecialchars($slider['media_url']); ?>" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
<?php else: ?>
<div class="slide-image" style="background-image: url('<?php echo htmlspecialchars($slider['media_url']); ?>')"></div>
<?php endif; ?>
<!-- Overlay -->
<div class="slide-overlay" style="background-color: <?php echo htmlspecialchars($slider['overlay_color'] ?? 'rgba(0, 0, 0, 0.4)'); ?>"></div>
<!-- Content -->
<div class="slide-content" style="color: <?php echo htmlspecialchars($slider['text_color'] ?? '#ffffff'); ?>">
<?php if (!empty($slider['subtitle'])): ?>
<span class="slide-subtitle"><?php echo htmlspecialchars($slider['subtitle']); ?></span>
<?php endif; ?>
<?php if (!empty($slider['title'])): ?>
<h2 class="slide-title"><?php echo htmlspecialchars($slider['title']); ?></h2>
<?php endif; ?>
<?php if (!empty($slider['description'])): ?>
<p class="slide-description"><?php echo htmlspecialchars($slider['description']); ?></p>
<?php endif; ?>
<?php if (!empty($slider['button_text'])): ?>
<a href="<?php echo htmlspecialchars($slider['button_url'] ?? '#'); ?>" class="slide-button">
<span><?php echo htmlspecialchars($slider['button_text']); ?></span>
<i class="fas fa-arrow-right"></i>
</a>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<!-- Custom Navigation -->
<div class="slider-navigation">
<div class="nav-button slider-prev">
<i class="fas fa-chevron-left"></i>
</div>
<!-- Custom Pagination -->
<div class="custom-pagination">
<?php foreach ($sliders as $index => $slider): ?>
<div class="pagination-item <?php echo $index === 0 ? 'active' : ''; ?>" data-index="<?php echo $index; ?>">
<span class="pagination-progress"></span>
</div>
<?php endforeach; ?>
</div>
<div class="nav-button slider-next">
<i class="fas fa-chevron-right"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Slider JS -->
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log('Hero slider initialization starting...');
// Make sure Swiper is loaded
if (typeof Swiper === 'undefined') {
console.error('Swiper library not loaded. The slider might not function properly.');
// Try to load Swiper dynamically as a fallback
const swiperCSS = document.createElement('link');
swiperCSS.rel = 'stylesheet';
swiperCSS.href = 'https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.css';
document.head.appendChild(swiperCSS);
const swiperScript = document.createElement('script');
swiperScript.src = 'https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.js';
swiperScript.onload = initSlider;
document.head.appendChild(swiperScript);
return;
}
initSlider();
function initSlider() {
console.log('Initializing hero slider with Swiper...');
// Find our specific slider
const sliderWrapper = document.querySelector('.hero-slider-wrapper');
if (!sliderWrapper) {
console.error('Hero slider wrapper not found');
return;
}
// Initialize Swiper with custom options
const heroSlider = new Swiper(sliderWrapper.querySelector('.hero-slider'), {
effect: 'fade', // Use fade effect for smooth transitions
speed: 1000,
loop: true,
grabCursor: true,
autoplay: {
delay: 5000,
disableOnInteraction: false,
},
navigation: {
nextEl: sliderWrapper.querySelector('.slider-next'),
prevEl: sliderWrapper.querySelector('.slider-prev'),
},
pagination: {
el: sliderWrapper.querySelector('.custom-pagination'),
clickable: true,
renderBullet: function(index, className) {
return '<div class="' + className + ' pagination-item" data-index="' + index + '"><span class="pagination-progress"></span></div>';
},
},
on: {
init: function() {
console.log('Swiper initialized successfully!');
updatePagination(this.realIndex);
animateSlide(this.slides[this.activeIndex]);
},
slideChangeTransitionStart: function() {
updatePagination(this.realIndex);
resetSlideAnimations();
},
slideChangeTransitionEnd: function() {
animateSlide(this.slides[this.activeIndex]);
}
}
});
// Custom pagination interaction
sliderWrapper.querySelectorAll('.pagination-item').forEach(function(bullet, index) {
bullet.addEventListener('click', function() {
heroSlider.slideTo(index);
});
});
// Function to update custom pagination
function updatePagination(activeIndex) {
sliderWrapper.querySelectorAll('.pagination-item').forEach(function(item, index) {
if (index === activeIndex) {
item.classList.add('active');
} else {
item.classList.remove('active');
}
});
}
// Function to animate the current slide
function animateSlide(slide) {
if (!slide) return;
const animation = slide.getAttribute('data-animation') || 'fade';
slide.classList.add('animate-' + animation);
// Animate content elements sequentially
const content = slide.querySelector('.slide-content');
if (content) {
content.querySelectorAll('.slide-subtitle, .slide-title, .slide-description, .slide-button').forEach((element, index) => {
setTimeout(() => {
element.classList.add('animate-in');
}, 200 * (index + 1));
});
}
}
// Function to reset animations
function resetSlideAnimations() {
sliderWrapper.querySelectorAll('.swiper-slide').forEach(slide => {
const animation = slide.getAttribute('data-animation') || 'fade';
slide.classList.remove('animate-' + animation);
slide.querySelectorAll('.slide-subtitle, .slide-title, .slide-description, .slide-button').forEach(element => {
element.classList.remove('animate-in');
});
});
}
// Progress indicators for autoplay
let autoplayDuration = 5000; // should match the delay setting in Swiper
function startProgressAnimation(index) {
const progressBar = sliderWrapper.querySelector(`.pagination-item[data-index="${index}"] .pagination-progress`);
if (!progressBar) return;
// Reset progress
progressBar.style.transition = 'none';
progressBar.style.width = '0%';
// Force reflow to make sure the reset takes effect before starting animation
progressBar.offsetHeight;
// Start animation
progressBar.style.transition = `width ${autoplayDuration}ms linear`;
progressBar.style.width = '100%';
}
// Start progress animation on init
startProgressAnimation(heroSlider.realIndex);
// Update progress animation on slide change
heroSlider.on('slideChange', function() {
startProgressAnimation(heroSlider.realIndex);
});
// Fix for swiper pagination
const customPagination = sliderWrapper.querySelector('.custom-pagination');
if (customPagination) {
customPagination.classList.add('swiper-pagination');
}
}
});
</script>