You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
7.5 KiB

// Smooth scroll for navigation links
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'
});
}
});
});
// Mobile menu
const mobileMenuBtn = document.querySelector('.mobile-menu-btn');
const navLinks = document.querySelector('.nav-links');
if (mobileMenuBtn && navLinks) {
mobileMenuBtn.addEventListener('click', () => {
mobileMenuBtn.classList.toggle('active');
navLinks.classList.toggle('active');
});
// Close menu when clicking on a link
navLinks.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
mobileMenuBtn.classList.remove('active');
navLinks.classList.remove('active');
});
});
}
// Experience card details toggle
document.querySelectorAll('.show-more').forEach(button => {
button.addEventListener('click', () => {
const card = button.closest('.experience-card');
const details = card.querySelector('.experience-details');
if (details) {
details.classList.toggle('show');
button.textContent = details.classList.contains('show') ? 'Voir moins' : 'Voir plus';
}
});
});
// Testimonials slider
const testimonialCards = document.querySelectorAll('.testimonial-card');
const dots = document.querySelectorAll('.dot');
const prevBtn = document.querySelector('.control-btn.prev');
const nextBtn = document.querySelector('.control-btn.next');
let currentTestimonial = 0;
let autoSlideInterval;
function showTestimonial(index) {
testimonialCards.forEach(card => card.classList.remove('active'));
dots.forEach(dot => dot.classList.remove('active'));
testimonialCards[index].classList.add('active');
dots[index].classList.add('active');
}
function nextTestimonial() {
currentTestimonial = (currentTestimonial + 1) % testimonialCards.length;
showTestimonial(currentTestimonial);
}
function prevTestimonial() {
currentTestimonial = (currentTestimonial - 1 + testimonialCards.length) % testimonialCards.length;
showTestimonial(currentTestimonial);
}
function startAutoSlide() {
autoSlideInterval = setInterval(nextTestimonial, 5000);
}
function stopAutoSlide() {
clearInterval(autoSlideInterval);
}
// Event listeners for testimonial controls
if (prevBtn && nextBtn) {
prevBtn.addEventListener('click', () => {
prevTestimonial();
stopAutoSlide();
startAutoSlide();
});
nextBtn.addEventListener('click', () => {
nextTestimonial();
stopAutoSlide();
startAutoSlide();
});
}
dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
currentTestimonial = index;
showTestimonial(currentTestimonial);
stopAutoSlide();
startAutoSlide();
});
});
// Start auto-sliding
startAutoSlide();
// Pause auto-slide when hovering over testimonials
const testimonialSlider = document.querySelector('.testimonials-slider');
if (testimonialSlider) {
testimonialSlider.addEventListener('mouseenter', stopAutoSlide);
testimonialSlider.addEventListener('mouseleave', startAutoSlide);
}
// Project modal
const projectData = {
1: {
title: "Application E-commerce",
description: `Une plateforme de commerce électronique complète offrant une expérience d'achat fluide et sécurisée. Caractéristiques principales :
• Système de panier d'achat dynamique
• Intégration de paiement sécurisé
• Gestion des stocks en temps réel
• Interface administrateur complète
• Système de notation et avis clients
• Optimisation SEO avancée`,
image: "https://via.placeholder.com/800x400",
tags: ["React", "Node.js", "MongoDB", "Stripe", "Redux", "AWS"],
link: "#"
},
2: {
title: "Dashboard Analytics",
description: `Interface d'administration sophistiquée permettant la visualisation et l'analyse de données en temps réel. Fonctionnalités :
• Graphiques interactifs personnalisables
• Tableaux de bord en temps réel
• Export de rapports automatisés
• Système d'alertes intelligent
• Analyse prédictive
• Interface responsive`,
image: "https://via.placeholder.com/800x400",
tags: ["Vue.js", "D3.js", "Firebase", "TypeScript", "TailwindCSS"],
link: "#"
},
3: {
title: "Application Mobile Fitness",
description: `Application mobile de suivi fitness complète avec synchronisation cloud et analyses détaillées. Caractéristiques :
• Suivi d'activités personnalisé
• Synchronisation multi-appareils
• Statistiques détaillées
• Plans d'entraînement adaptatifs
• Intégration avec appareils connectés
• Mode hors ligne`,
image: "https://via.placeholder.com/800x400",
tags: ["React Native", "Redux", "AWS", "Node.js", "MongoDB"],
link: "#"
}
};
const modal = document.getElementById('projectModal');
const modalImage = modal.querySelector('.modal-image');
const modalTitle = modal.querySelector('.modal-title');
const modalDescription = modal.querySelector('.modal-description');
const modalTags = modal.querySelector('.modal-tags');
const modalLink = modal.querySelector('.modal-link');
const modalClose = modal.querySelector('.modal-close');
// Open modal
document.querySelectorAll('.project-card').forEach(card => {
card.addEventListener('click', (e) => {
const projectId = card.dataset.project;
const project = projectData[projectId];
modalImage.src = project.image;
modalImage.alt = project.title;
modalTitle.textContent = project.title;
modalDescription.innerHTML = project.description;
modalTags.innerHTML = project.tags
.map(tag => `<span>${tag}</span>`)
.join('');
modalLink.href = project.link;
modal.style.display = 'block';
document.body.style.overflow = 'hidden';
});
});
// Close modal
modalClose.addEventListener('click', () => {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
});
window.addEventListener('click', (e) => {
if (e.target === modal) {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
// Intersection Observer for scroll animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-in');
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Observe all sections for animation
document.querySelectorAll('section').forEach(section => {
observer.observe(section);
});
// Header scroll behavior
let lastScroll = 0;
const header = document.querySelector('.header');
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > lastScroll && currentScroll > 80) {
header.style.transform = 'translateY(-100%)';
} else {
header.style.transform = 'translateY(0)';
}
lastScroll = currentScroll;
});