// Fichier app.js - scripts côté client pour ATLANTIS // Ce fichier contient maintenant les vraies images locales // Initialize Swiper et chargement des images document.addEventListener('DOMContentLoaded', function() { let swiper = null; // Fonction pour initialiser Swiper function initSwiper() { if (swiper) { swiper.destroy(true, true); } swiper = new Swiper('.realisationsSwiper', { spaceBetween: 30, slidesPerView: 1, breakpoints: { 640: { slidesPerView: 2, }, 768: { slidesPerView: 3, }, 1024: { slidesPerView: 4, }, }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, pagination: { el: '.swiper-pagination', clickable: true, }, autoplay: { delay: 4000, disableOnInteraction: false, }, }); } // Variables globales pour les images let images = []; // Charger les images dynamiquement depuis l'API async function loadImages() { try { const response = await fetch('/api/images'); const data = await response.json(); // Prendre toutes les images disponibles (jusqu'à 50) // Le système détectera automatiquement celles qui existent sur GitHub images = data.images; console.log(`📸 ${images.length} images détectées pour le carousel ATLANTIS`); // Initialiser le carousel après avoir chargé les images initializeCarousel(); } catch (error) { console.error('Erreur lors du chargement des images:', error); // Fallback vers une liste de base images = []; for (let i = 1; i <= 20; i++) { images.push({ src: '/images/realisation_' + i.toString().padStart(2, '0') + '.jpg', title: 'Réalisation ATLANTIS ' + i, description: 'Projet de tuyauterie industrielle réalisé par l\'équipe ATLANTIS' }); } initializeCarousel(); } } // Fonction pour initialiser le carousel function initializeCarousel() { // Populate Swiper slides avec les images chargées const swiperContainer = document.querySelector('#swiper-container'); const swiperWrapper = document.querySelector('.realisationsSwiper'); if (swiperContainer && images.length > 0) { // Filtrer les images qui existent réellement (celles qui ne provoquent pas d'erreur) const validImages = []; let loadedCount = 0; // Utiliser toutes les images pour l'instant (on laisse le navigateur gérer les erreurs) // En production Cloudflare Pages, les images GitHub seront automatiquement servies console.log(`🔍 Test de ${images.length} images potentielles...`); images.forEach((image, index) => { const testImg = new Image(); testImg.onload = function() { validImages.push({ ...image, originalIndex: index }); loadedCount++; console.log(`✅ Image ${index + 1} chargée: ${image.title}`); // Une fois toutes les images testées, créer le carousel if (loadedCount === images.length) { createCarouselSlides(validImages.length > 0 ? validImages : images.slice(0, 15)); } }; testImg.onerror = function() { console.log(`❌ Image ${index + 1} non trouvée: ${image.src}`); loadedCount++; if (loadedCount === images.length) { // Si aucune image locale, utiliser les 15 premières avec fallback URLs createCarouselSlides(validImages.length > 0 ? validImages : images.slice(0, 15)); } }; testImg.src = image.src; }); } } // Créer les slides du carousel avec les images valides function createCarouselSlides(validImages) { const swiperContainer = document.querySelector('#swiper-container'); const swiperWrapper = document.querySelector('.realisationsSwiper'); if (validImages.length > 0) { // Mettre à jour les images globales avec seulement celles qui sont valides images = validImages; swiperContainer.innerHTML = images.map((image, index) => `
${image.title}
`).join(''); // Ajouter le compteur au wrapper Swiper if (swiperWrapper) { swiperWrapper.setAttribute('data-count', images.length); } console.log(`✅ Carousel initialisé avec ${images.length} photos ATLANTIS`); // Initialiser Swiper après avoir ajouté les slides setTimeout(() => { initSwiper(); }, 200); } else { console.warn('❌ Aucune image valide trouvée pour le carousel'); } } // Initialiser notre carousel personnalisé si disponible if (document.getElementById('carouselTrack')) { // Images ATLANTIS réelles const atlantisImages = [ 'https://page.gensparksite.com/v1/base64_upload/f2b3e3709825ea2e94cc8554ed49bfae', 'https://page.gensparksite.com/v1/base64_upload/50911dc38c48281e88dee000df0f5354', 'https://page.gensparksite.com/v1/base64_upload/e8f18c8e4995cb45e8fe4b07c4c15a60', 'https://page.gensparksite.com/v1/base64_upload/53b3daa80b1d3d17a9ecdcc1ffc18056', 'https://page.gensparksite.com/v1/base64_upload/396a6009777367687c1f268999887d6f', 'https://page.gensparksite.com/v1/base64_upload/bee75ae503c7275e97efd8ad3e94faa8', 'https://page.gensparksite.com/v1/base64_upload/af1d914e6f1469fc2df0cf948ae13ad6', 'https://page.gensparksite.com/v1/base64_upload/8beaa61997cc8afeea728a466f7c3559' ]; initAtlantisCarousel(atlantisImages); } else { // Charger les images pour l'ancien système Swiper loadImages(); } // Fonction pour initialiser notre carousel ATLANTIS function initAtlantisCarousel(imageUrls) { const track = document.getElementById('carouselTrack'); if (!track) return; // Créer les éléments du carousel track.innerHTML = imageUrls.map((url, index) => ` `).join(''); let currentIndex = 0; // Navigation const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); function updateCarousel() { const itemWidth = 100 / 4; // 4 images par vue sur desktop const translateX = -(currentIndex * itemWidth); track.style.transform = `translateX(${translateX}%)`; } if (prevBtn) { prevBtn.onclick = () => { currentIndex = Math.max(0, currentIndex - 1); updateCarousel(); }; } if (nextBtn) { nextBtn.onclick = () => { const maxIndex = Math.max(0, imageUrls.length - 4); currentIndex = Math.min(maxIndex, currentIndex + 1); updateCarousel(); }; } // Auto-play setInterval(() => { const maxIndex = Math.max(0, imageUrls.length - 4); currentIndex = currentIndex >= maxIndex ? 0 : currentIndex + 1; updateCarousel(); }, 3000); console.log('✅ Carousel ATLANTIS initialisé avec ' + imageUrls.length + ' images'); } // Lightbox simple pour notre carousel window.openAtlantisLightbox = function(index, src, title) { let lightbox = document.getElementById('atlantis-lightbox'); if (!lightbox) { lightbox = document.createElement('div'); lightbox.id = 'atlantis-lightbox'; lightbox.innerHTML = `
`; document.body.appendChild(lightbox); } const img = lightbox.querySelector('#atlantis-lightbox-img'); img.src = src; lightbox.style.display = 'block'; document.body.style.overflow = 'hidden'; }; let currentImageIndex = 0; // Lightbox functions avec support des descriptions et indicateur de position window.openLightbox = function(index) { currentImageIndex = index; const lightbox = document.getElementById('lightbox'); const lightboxImg = document.getElementById('lightbox-img'); const lightboxTitle = document.getElementById('lightbox-title'); const lightboxDesc = document.getElementById('lightbox-desc'); // Afficher la lightbox lightbox.style.display = 'block'; lightboxImg.src = images[index].src; // Mettre à jour l'indicateur de position lightbox.setAttribute('data-position', `${index + 1} / ${images.length}`); // Mettre à jour les descriptions if (lightboxTitle) { lightboxTitle.textContent = images[index].title; } if (lightboxDesc) { lightboxDesc.textContent = images[index].description; } // Bloquer le scroll de la page document.body.style.overflow = 'hidden'; console.log(`📸 Lightbox ouverte - Image ${index + 1}/${images.length}: ${images[index].title}`); } window.closeLightbox = function() { document.getElementById('lightbox').style.display = 'none'; document.body.style.overflow = 'auto'; } window.nextImage = function() { currentImageIndex = (currentImageIndex + 1) % images.length; updateLightboxContent(); } window.prevImage = function() { currentImageIndex = (currentImageIndex - 1 + images.length) % images.length; updateLightboxContent(); } // Fonction pour mettre à jour le contenu de la lightbox function updateLightboxContent() { const lightbox = document.getElementById('lightbox'); const lightboxImg = document.getElementById('lightbox-img'); const lightboxTitle = document.getElementById('lightbox-title'); const lightboxDesc = document.getElementById('lightbox-desc'); // Mettre à jour l'image lightboxImg.src = images[currentImageIndex].src; // Mettre à jour l'indicateur de position lightbox.setAttribute('data-position', `${currentImageIndex + 1} / ${images.length}`); // Mettre à jour les descriptions if (lightboxTitle) { lightboxTitle.textContent = images[currentImageIndex].title; } if (lightboxDesc) { lightboxDesc.textContent = images[currentImageIndex].description; } } // Close lightbox when clicking outside the image document.getElementById('lightbox').addEventListener('click', function(e) { if (e.target === this) { closeLightbox(); } }); // Keyboard navigation document.addEventListener('keydown', function(e) { if (document.getElementById('lightbox').style.display === 'block') { if (e.key === 'Escape') { closeLightbox(); } else if (e.key === 'ArrowRight') { nextImage(); } else if (e.key === 'ArrowLeft') { prevImage(); } } }); // Cette section est maintenant gérée par initializeCarousel() // Gestion des erreurs d'images document.querySelectorAll('img').forEach(img => { img.onerror = function() { console.log('Erreur de chargement pour:', this.src); }; }); // FAQ Interactive (accordéon) const faqItems = document.querySelectorAll('.faq-item'); faqItems.forEach(item => { const question = item.querySelector('.faq-question'); const answer = item.querySelector('.faq-answer'); const icon = item.querySelector('.faq-icon'); if (question && answer && icon) { question.addEventListener('click', () => { answer.classList.toggle('active'); icon.classList.toggle('active'); }); } }); // Smooth scroll pour les liens de navigation document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // Formulaire de contact const contactForm = document.getElementById('contact-form'); if (contactForm) { contactForm.addEventListener('submit', function(e) { e.preventDefault(); const submitBtn = contactForm.querySelector('button[type="submit"]'); const originalText = submitBtn.innerHTML; // Animation de chargement submitBtn.innerHTML = '
Envoi en cours...'; submitBtn.disabled = true; // Récupérer les données du formulaire const formData = new FormData(contactForm); const data = {}; formData.forEach((value, key) => { data[key] = value; }); // Simuler l'envoi (en attendant une vraie API) setTimeout(() => { // Afficher un message de succès const successMessage = document.createElement('div'); successMessage.className = 'bg-green-500 text-white p-4 rounded-lg mt-4'; successMessage.innerHTML = 'Message envoyé avec succès ! Nous vous recontacterons rapidement.'; contactForm.appendChild(successMessage); // Réinitialiser le formulaire contactForm.reset(); // Restaurer le bouton setTimeout(() => { submitBtn.innerHTML = originalText; submitBtn.disabled = false; successMessage.remove(); }, 3000); }, 2000); }); } // Animation des stats au scroll (si présentes) const observerOptions = { threshold: 0.5, rootMargin: '0px 0px -100px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-in'); } }); }, observerOptions); // Observer les éléments à animer document.querySelectorAll('.card-hover, .sector-item, .prestation-card').forEach(el => { observer.observe(el); }); });