Commit 56d72d1d by PLN (Algolia)

wip

parent 133e522c
...@@ -25,22 +25,24 @@ export default function ParVaguesFooter() { ...@@ -25,22 +25,24 @@ export default function ParVaguesFooter() {
{/* About Column */} {/* About Column */}
<div> <div>
<p className="text-gray-400 text-sm mb-4"> <p className="text-gray-400 text-sm mb-4">
Livecoding de musique open-source avec TidalCycles et contrôleur MIDI.<br /> Livecoding de musique libre<br />
Performances algorithmiques et création sonore en direct. Performances algorithmiques en direct.
</p> </p>
</div> </div>
{/* Social Column */} {/* Social Column */}
<div className="flex flex-col items-center md:items-end"> <div className="flex flex-col items-center md:items-end">
<div className="flex justify-center mb-4 md:mb-0 md:absolute md:left-1/2 md:transform md:-translate-x-1/2"> <div className="flex justify-center w-full">
<Image <div className="relative">
src="/images/parvagues/logo_text.png" <Image
alt="ParVagues Logo" src="/images/parvagues/logo.png"
width={96} alt="ParVagues Logo"
height={96} width={240}
className="md:mt-16" height={240}
/> className="mx-auto mb-4"
</div> />
</div>
</div>
<div className="flex flex-wrap gap-4 justify-center md:justify-end"> <div className="flex flex-wrap gap-4 justify-center md:justify-end">
{socialLinks.map((link, index) => ( {socialLinks.map((link, index) => (
...@@ -60,30 +62,26 @@ export default function ParVaguesFooter() { ...@@ -60,30 +62,26 @@ export default function ParVaguesFooter() {
</div> </div>
{/* Navigation Links - more compact */} {/* Navigation Links - more compact */}
<div className="w-full bg-black py-4 my-4"> <div className="w-full bg-black py-4">
<div className="flex justify-center items-center space-x-4 text-xs tracking-widest uppercase flex-wrap"> <div className="flex justify-center items-center space-x-8 text-xs tracking-widest uppercase flex-wrap">
<Link href="/parvagues#music" className="text-gray-300 hover:text-[#ff3d7b] transition-colors"> <Link href="/parvagues#music" className="text-gray-300 hover:text-[#ff3d7b] transition-colors tracking-wider px-3">
MUSIQUE MUSIQUE
</Link> </Link>
<Link href="/parvagues#performances" className="text-gray-300 hover:text-[#ff3d7b] transition-colors"> <Link href="/parvagues#performances" className="text-gray-300 hover:text-[#ff3d7b] transition-colors tracking-wider px-3">
PERFORMANCES PERFORMANCES
</Link> </Link>
<Link href="/parvagues#about" className="text-gray-300 hover:text-[#ff3d7b] transition-colors"> <Link href="/parvagues#about" className="text-gray-300 hover:text-[#ff3d7b] transition-colors tracking-wider px-3">
À PROPOS À PROPOS
</Link> </Link>
<a <a
href="mailto:parvagues@nech.pl?subject=Booking Request" href="mailto:parvagues@nech.pl?subject=Booking Request"
className="text-gray-300 hover:text-[#ff3d7b] transition-colors" className="text-gray-300 hover:text-[#ff3d7b] transition-colors tracking-wider px-3"
> >
RÉSERVER RÉSERVER
</a> </a>
</div> </div>
</div> </div>
{/* Bottom Bar */}
<div className="border-t border-gray-800 mt-4 pt-4 text-center text-gray-500 text-xs">
<p>© {year} ParVagues. All code is open-source.</p>
</div>
</div> </div>
</footer> </footer>
); );
......
...@@ -31,28 +31,30 @@ export default function ParVaguesHeader({ eventName = null, title = null }) { ...@@ -31,28 +31,30 @@ export default function ParVaguesHeader({ eventName = null, title = null }) {
const headerTitle = title || eventName || 'ParVagues'; const headerTitle = title || eventName || 'ParVagues';
return ( return (
<header <header className="sticky top-0 left-0 w-full z-50 bg-black/80 backdrop-blur-md border-b border-[#d900ff]/20">
className="sticky top-0 left-0 w-full z-50 bg-black/80 backdrop-blur-md border-b border-[#d900ff]/20 shadow-lg transition-all duration-300" <div className={`${styles.neonGradient} opacity-5`}></div>
> <div className="max-w-6xl mx-auto px-4 py-3 flex justify-between items-center relative">
<div className="max-w-6xl mx-auto px-4 py-3 flex justify-between items-center"> <div className="flex items-center">
<div className="flex items-center gap-2"> <Link href="/parvagues" className="flex items-center group">
<Link href="/parvagues" className="flex items-center">
<div className="h-10 w-auto relative"> <div className="h-10 w-auto relative">
<Image <Image
src="/images/parvagues/logo_transparent.png" src="/images/parvagues/logo_transparent.png"
alt="ParVagues Logo" alt="ParVagues Logo"
width={40} width={200}
height={40} height={200}
className="object-contain" className="object-contain transition-all duration-300 group-hover:filter group-hover:drop-shadow-[0_0_8px_rgba(217,0,255,0.7)]"
/> />
</div> </div>
{/* Title animation based on scroll */}
<div className="overflow-hidden ml-2"> <div className="overflow-hidden ml-2">
<span <span
className={`text-[#d900ff] text-xl font-bold transform transition-all duration-500 ${ className={`text-white font-bold transition-all duration-500 ${
showInHeader ? 'opacity-100 translate-y-0' : 'opacity-0 -translate-y-8' showInHeader ? 'opacity-100 translate-y-0' : 'opacity-0 -translate-y-8'
}`} }`}
style={{
textShadow: '0 0 5px rgba(217, 0, 255, 0.7), 0 0 10px rgba(217, 0, 255, 0.5)',
color: 'var(--neon-high)'
}}
> >
{headerTitle} {headerTitle}
</span> </span>
...@@ -61,27 +63,27 @@ export default function ParVaguesHeader({ eventName = null, title = null }) { ...@@ -61,27 +63,27 @@ export default function ParVaguesHeader({ eventName = null, title = null }) {
</div> </div>
{/* Navigation Links */} {/* Navigation Links */}
<div className="hidden md:flex items-center space-x-6 text-sm"> <nav className="hidden md:flex items-center space-x-6 text-sm tracking-wider">
<Link href="/parvagues#music" className="text-white hover:text-[#ff3d7b] transition-colors"> <Link href="/parvagues#music" className="text-gray-300 hover:text-[#ff3d7b] transition-colors">
Music Music
</Link> </Link>
<Link href="/parvagues#performances" className="text-white hover:text-[#ff3d7b] transition-colors"> <Link href="/parvagues#performances" className="text-gray-300 hover:text-[#ff3d7b] transition-colors">
Performances Performances
</Link> </Link>
<Link href="/parvagues#about" className="text-white hover:text-[#ff3d7b] transition-colors"> <Link href="/parvagues#about" className="text-gray-300 hover:text-[#ff3d7b] transition-colors">
About About
</Link> </Link>
</div> </nav>
{/* CTA button */} {/* CTA button */}
<a <a
href="mailto:parvagues@nech.pl?subject=Booking Request&body=Bonjour,%0D%0A%0D%0AJe souhaiterais discuter d'une possibilité de performance live coding." href="/book"
className={`${styles.ctaButton} ${showInHeader ? 'scale-90' : 'scale-100'} transition-transform duration-300`} className={`${styles.outlineButton} py-2 px-4 text-sm`}
> >
<FaEnvelope className="inline mr-2" /> <FaEnvelope className="inline mr-2" />
{showInHeader ? 'Invoquer' : 'Invoquer un live'} Book
</a> </a>
</div> </div>
</header> </header>
); );
} }
\ No newline at end of file \ No newline at end of file
...@@ -75,16 +75,28 @@ export default function ParVagues({ lives }) { ...@@ -75,16 +75,28 @@ export default function ParVagues({ lives }) {
// Define section content // Define section content
const sections = { const sections = {
potentiel: { potentiel: {
type: 'image', type: 'carousel',
image: '/images/parvagues/samples.png' images: [
'/images/parvagues/samples.png',
'/images/parvagues/code.png',
'/images/parvagues/code2.png',
'/images/parvagues/code_dense.png'
]
}, },
composition: { composition: {
type: 'image', type: 'carousel',
image: '/images/parvagues/gear1.jpg' images: [
'/images/parvagues/gear1.jpg',
'/images/parvagues/gear2.jpg',
'/images/parvagues/studio1.jpg'
]
}, },
performance: { performance: {
type: 'image', type: 'carousel',
image: '/images/parvagues/live.jpg' images: [
'/images/parvagues/live.jpg',
'/images/parvagues/code_overlay.jpg'
]
} }
}; };
...@@ -112,53 +124,27 @@ d4 $ note ("<e3 fs3 <gs3 d4> <a3 df4>>" - 12) ...@@ -112,53 +124,27 @@ d4 $ note ("<e3 fs3 <gs3 d4> <a3 df4>>" - 12)
} }
}, [selectedSection]); }, [selectedSection]);
// Carousel effect for section images // Auto-advance carousel for section images
// next/pages/parvagues.js (snippet from useEffect for backgroundRef)
useEffect(() => { useEffect(() => {
if (!backgroundRef.current) return; if (sections[selectedSection]?.images?.length > 1) {
const images = backgroundRef.current.children;
if (images.length === 0) return; // Guard against no images
let index = 0;
// Initial setup for the very first image
for (let i = 0; i < images.length; i++) {
images[i].style.opacity = '0'; // Ensure all are initially transparent
}
if (images[index]) {
images[index].style.opacity = '0.7'; // Make the first one visible
}
const cycle = () => {
// Current image fades out
if (images[index]) {
images[index].style.opacity = '0';
}
index = (index + 1) % images.length;
// Next image fades in
if (images[index]) {
images[index].style.opacity = '0.7';
}
};
// Call cycle once to set the initial state correctly after a brief moment
// setTimeout(cycle, 100); // Or let the interval handle the first full cycle
const interval = setInterval(cycle, 3000); // Start cycling after 3s
return () => clearInterval(interval);
}, []); // Removed sectionImages.length from dependencies as it's not used here
useEffect(() => {
if (sectionImages.length > 1) {
const interval = setInterval(() => { const interval = setInterval(() => {
setCurrentImageIndex(prev => (prev + 1) % sectionImages.length); setCurrentImageIndex(prev => (prev + 1) % sections[selectedSection].images.length);
}, 4000); }, 2500);
return () => clearInterval(interval); return () => clearInterval(interval);
} }
}, [sectionImages.length]); }, [selectedSection, sections]);
// Carousel navigation functions
const nextSectionImage = () => {
const imagesArray = sections[selectedSection].images;
setCurrentImageIndex(prev => (prev + 1) % imagesArray.length);
};
const prevSectionImage = () => {
const imagesArray = sections[selectedSection].images;
setCurrentImageIndex(prev => (prev === 0 ? imagesArray.length - 1 : prev - 1));
};
// Carousel effect for albums // Carousel effect for albums
useEffect(() => { useEffect(() => {
...@@ -226,16 +212,47 @@ d4 $ note ("<e3 fs3 <gs3 d4> <a3 df4>>" - 12) ...@@ -226,16 +212,47 @@ d4 $ note ("<e3 fs3 <gs3 d4> <a3 df4>>" - 12)
const sectionContent = sections[selectedSection]; const sectionContent = sections[selectedSection];
if (!sectionContent) return null; if (!sectionContent) return null;
// For any section type, display the image
return ( return (
<div className="relative w-full aspect-video rounded-lg overflow-hidden shadow-xl"> <div className="w-full rounded-lg overflow-hidden shadow-xl">
<Image <div className="relative w-full bg-black flex items-center justify-center">
src={sectionContent.image} <div className="w-[30vw] h-[30vw] max-w-[30vw] max-h-[30vw] flex items-center justify-center p-4">
alt={selectedSection} <div className="relative w-full h-full flex items-center justify-center">
fill <Image
className="object-cover" src={sectionContent.images[currentImageIndex]}
priority={true} alt={selectedSection}
/> width={1280}
height={1280}
className="w-full h-full object-contain"
priority={true}
/>
</div>
</div>
{sectionContent.images.length > 1 && (
<>
{/* Left arrow */}
<button
onClick={prevSectionImage}
className="absolute left-2 top-1/2 -translate-y-1/2 bg-black/30 hover:bg-black/50 p-2 rounded-full transition-colors"
aria-label="Image précédente"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
{/* Right arrow */}
<button
onClick={nextSectionImage}
className="absolute right-2 top-1/2 -translate-y-1/2 bg-black/30 hover:bg-black/50 p-2 rounded-full transition-colors"
aria-label="Image suivante"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</>
)}
</div>
</div> </div>
); );
}; };
...@@ -250,7 +267,6 @@ d4 $ note ("<e3 fs3 <gs3 d4> <a3 df4>>" - 12) ...@@ -250,7 +267,6 @@ d4 $ note ("<e3 fs3 <gs3 d4> <a3 df4>>" - 12)
</Head> </Head>
<div className="flex flex-col min-h-screen bg-black text-white"> <div className="flex flex-col min-h-screen bg-black text-white">
{/* Apply proper sticky header */}
<ParVaguesHeader /> <ParVaguesHeader />
{/* Main content flex-auto to push footer to bottom */} {/* Main content flex-auto to push footer to bottom */}
...@@ -340,26 +356,35 @@ d4 $ note ("<e3 fs3 <gs3 d4> <a3 df4>>" - 12) ...@@ -340,26 +356,35 @@ d4 $ note ("<e3 fs3 <gs3 d4> <a3 df4>>" - 12)
<div className={styles.splitSection}> <div className={styles.splitSection}>
<div> <div>
<div <div
className={`${styles.bulletPoint} cursor-pointer ${selectedSection === 'potentiel' ? 'text-purple-400 border-l-2 border-purple-400 pl-4' : ''}`} className={`${styles.bulletPoint} cursor-pointer transition-all duration-300 hover:bg-purple-500/10 rounded-lg ${selectedSection === 'potentiel' ? 'text-purple-400 border-l-2 border-purple-400 pl-4' : ''}`}
onClick={() => setSelectedSection('potentiel')} onClick={() => setSelectedSection('potentiel')}
> >
<h3 className="text-xl font-semibold text-purple-400 mb-2">Potentiel</h3> <h3 className="text-xl font-semibold text-purple-400 mb-2 group relative inline-block">
Potentiel
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-gradient-to-r from-purple-400 to-pink-500 group-hover:w-full transition-all duration-300"></span>
</h3>
<p className="text-gray-300">Samples glanés et synthés SuperCollider</p> <p className="text-gray-300">Samples glanés et synthés SuperCollider</p>
</div> </div>
<div <div
className={`${styles.bulletPoint} cursor-pointer ${selectedSection === 'composition' ? 'text-purple-400 border-l-2 border-purple-400 pl-4' : ''}`} className={`${styles.bulletPoint} cursor-pointer transition-all duration-300 hover:bg-purple-500/10 rounded-lg ${selectedSection === 'composition' ? 'text-purple-400 border-l-2 border-purple-400 pl-4' : ''}`}
onClick={() => setSelectedSection('composition')} onClick={() => setSelectedSection('composition')}
> >
<h3 className="text-xl font-semibold text-purple-400 mb-2">Composition</h3> <h3 className="text-xl font-semibold text-purple-400 mb-2 group relative inline-block">
Composition
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-gradient-to-r from-purple-400 to-pink-500 group-hover:w-full transition-all duration-300"></span>
</h3>
<p className="text-gray-300">Code Haskell TidalCycles + input MIDI</p> <p className="text-gray-300">Code Haskell TidalCycles + input MIDI</p>
</div> </div>
<div <div
className={`${styles.bulletPoint} cursor-pointer ${selectedSection === 'performance' ? 'text-purple-400 border-l-2 border-purple-400 pl-4' : ''}`} className={`${styles.bulletPoint} cursor-pointer transition-all duration-300 hover:bg-purple-500/10 rounded-lg ${selectedSection === 'performance' ? 'text-purple-400 border-l-2 border-purple-400 pl-4' : ''}`}
onClick={() => setSelectedSection('performance')} onClick={() => setSelectedSection('performance')}
> >
<h3 className="text-xl font-semibold text-purple-400 mb-2">Performance</h3> <h3 className="text-xl font-semibold text-purple-400 mb-2 group relative inline-block">
Performance
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-gradient-to-r from-purple-400 to-pink-500 group-hover:w-full transition-all duration-300"></span>
</h3>
<p className="text-gray-300">Performance live avec improvisation au contrôleur MIDI</p> <p className="text-gray-300">Performance live avec improvisation au contrôleur MIDI</p>
</div> </div>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment