import React, { useState, useEffect, useRef } from 'react';
import { Play, Pause, SkipForward, SkipBack, Volume2, Calendar, Music, Mail, Instagram, Twitter, ExternalLink, Disc, CheckCircle, Headphones, Mic2, AlertCircle } from 'lucide-react';
/* CONFIGURATION DES MIXES
Pour Hostinger :
1. Crée un dossier "mixes" dans ton dossier "public".
2. Mets tes fichiers mp3 dedans.
3. Mets à jour les "audioSrc" ci-dessous avec les noms exacts de tes fichiers (ex: "/mixes/mon-mix.mp3").
*/
const MOCK_MIXES = [
{
id: 1,
title: "Midnight Dreams Vol. 1",
genre: "Deep House / Melodic",
duration: "58:30",
date: "12 Jan 2026",
color: "from-purple-600 to-blue-600",
description: "Un voyage sonore pour les nuits sans fin. Mélodies hypnotiques et basses profondes.",
bpm: 122,
audioSrc: "/mixes/midnight_dreams_vol1.mp3" // Change ceci avec ton vrai fichier
},
{
id: 2,
title: "Techno Bunker Session",
genre: "Peak Time Techno",
duration: "1:05:12",
date: "28 Dec 2025",
color: "from-red-600 to-orange-600",
description: "Énergie pure pour le dancefloor. Attention, haute intensité.",
bpm: 135,
audioSrc: "/mixes/techno_bunker.mp3"
},
{
id: 3,
title: "Sunset Rooftop Live",
genre: "Organic House",
duration: "45:20",
date: "10 Nov 2025",
color: "from-pink-500 to-rose-400",
description: "Vibes solaires enregistrées en live à Nice. Parfait pour l'apéro.",
bpm: 118,
audioSrc: "/mixes/sunset_live.mp3"
},
{
id: 4,
title: "Lucid State of Mind",
genre: "Progressive Trance",
duration: "1:12:00",
date: "15 Oct 2025",
color: "from-cyan-500 to-blue-500",
description: "L'essence même du projet 2Lucid. Un mix qui vous emmène ailleurs.",
bpm: 128,
audioSrc: "/mixes/lucid_state.mp3"
}
];
export default function App() {
const [currentTrack, setCurrentTrack] = useState(null);
const [isPlaying, setIsPlaying] = useState(false);
const [progress, setProgress] = useState(0);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [activeSection, setActiveSection] = useState('home');
const [showNotification, setShowNotification] = useState(false);
const [volume, setVolume] = useState(0.7);
const [loadError, setLoadError] = useState(false);
// Référence vers l'élément audio HTML réel
const audioRef = useRef(null);
// Gestion de la lecture/pause quand l'état change
useEffect(() => {
if (audioRef.current) {
if (isPlaying) {
const playPromise = audioRef.current.play();
if (playPromise !== undefined) {
playPromise.catch((error) => {
console.log("Lecture empêchée ou fichier manquant:", error);
setIsPlaying(false);
});
}
} else {
audioRef.current.pause();
}
}
}, [isPlaying, currentTrack]);
// Gestion du volume
useEffect(() => {
if (audioRef.current) {
audioRef.current.volume = volume;
}
}, [volume]);
const handlePlay = (mix) => {
setLoadError(false);
if (currentTrack?.id === mix.id) {
setIsPlaying(!isPlaying);
} else {
setCurrentTrack(mix);
setIsPlaying(true);
// Le changement de source est géré par la prop 'src' de l'élément audio
}
};
const handleTimeUpdate = () => {
const current = audioRef.current.currentTime;
const total = audioRef.current.duration;
setCurrentTime(current);
setDuration(total);
setProgress((current / total) * 100);
};
const handleAudioEnded = () => {
setIsPlaying(false);
setProgress(0);
};
const handleAudioError = () => {
if (currentTrack) {
console.error("Erreur de chargement du fichier audio:", currentTrack.audioSrc);
setLoadError(true);
setIsPlaying(false);
}
};
const handleSeek = (e) => {
if (!audioRef.current) return;
const clickPosition = (e.nativeEvent.offsetX / e.currentTarget.offsetWidth);
const newTime = clickPosition * audioRef.current.duration;
audioRef.current.currentTime = newTime;
setProgress(clickPosition * 100);
};
// Formatage du temps (secondes -> mm:ss)
const formatTime = (time) => {
if (isNaN(time)) return "00:00";
const minutes = Math.floor(time / 60);
const seconds = Math.floor(time % 60);
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
};
const handleNavClick = (sectionId) => {
setActiveSection(sectionId);
setIsMenuOpen(false);
const element = document.getElementById(sectionId);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
};
const handleContactSubmit = (e) => {
e.preventDefault();
setShowNotification(true);
setTimeout(() => setShowNotification(false), 3000);
};
return (
{/* Lecteur Audio Caché (Le vrai moteur) */}
{/* Background Ambience & Video */}
{/* VIDÉO D'ARRIÈRE-PLAN
Utilisation d'un lien CDN Pixabay plus fiable.
poster: Image affichée pendant le chargement de la vidéo.
*/}
{/* Nouveau lien vidéo Crowd/Lights */}
{/* Fallback si la vidéo ne charge pas */}
{/* Gradient Overlay pour lisibilité */}
{/* Animated Blobs (conservés pour la couleur) */}
{/* Grid Pattern Overlay */}
{/* Navigation */}
handleNavClick('home')}>
2LUCID
{/* Desktop Menu */}
{['Home', 'Mixes', 'Bio', 'Contact'].map((item) => (
handleNavClick(item.toLowerCase())}
className={`px-3 py-2 rounded-md text-sm font-medium transition-all duration-300 ${
activeSection === item.toLowerCase()
? 'text-cyan-400 scale-105'
: 'text-gray-300 hover:text-white hover:bg-white/5'
}`}
>
{item}
))}
{/* Mobile menu button */}
setIsMenuOpen(!isMenuOpen)}
className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none"
>
{/* Mobile Menu Panel */}
{isMenuOpen && (
{['Home', 'Mixes', 'Bio', 'Contact'].map((item) => (
handleNavClick(item.toLowerCase())}
className="block w-full text-left px-3 py-4 rounded-md text-base font-medium text-gray-300 hover:text-white hover:bg-gray-700"
>
{item}
))}
)}
{/* Main Content */}
{/* Hero Section */}
{/* Decorative DJ Elements */}
2LUCID
{/* Text Glow Effect */}
2LUCID
DJ
|
PRODUCER
L'expérience sonore immersive.
House • Techno • Trance
handleNavClick('mixes')}
className="group px-8 py-4 bg-white text-black font-bold rounded-full hover:bg-cyan-400 transition-all duration-300 flex items-center justify-center gap-3 shadow-[0_0_20px_rgba(255,255,255,0.3)] hover:shadow-[0_0_30px_rgba(34,211,238,0.6)]"
>
Écouter les Mixes
handleNavClick('contact')}
className="px-8 py-4 border border-white/20 bg-black/30 backdrop-blur-sm text-white font-medium rounded-full hover:bg-white/10 hover:border-cyan-400/50 transition-all duration-300"
>
Booking & Contact
{/* Scroll indicator */}
{/* Mixes Section */}
Derniers Mixes
Sélectionnés pour vous
House
Techno
Trance
{MOCK_MIXES.map((mix) => (
{/* Cover Art Placeholder */}
{/* Overlay Play Button */}
handlePlay(mix)}
className="absolute inset-0 bg-black/30 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300"
>
{currentTrack?.id === mix.id && isPlaying ?
:
}
{/* Content */}
{mix.genre}
{mix.date}
{mix.title}
{mix.description}
{mix.bpm} BPM
{mix.duration}
handlePlay(mix)}
className={`text-sm font-medium hover:text-white transition-colors flex items-center gap-2 ${currentTrack?.id === mix.id ? 'text-cyan-400' : 'text-gray-400'}`}
>
{currentTrack?.id === mix.id && isPlaying ? 'En lecture...' : 'Écouter'}
))}
{/* Bio Section */}
{/* Placeholder for DJ Photo */}
L'Esprit 2Lucid
Basé en France, 2Lucid n'est pas seulement un alias, c'est une invitation à la conscience accrue sur le dancefloor. Passionné par la fusion entre l'analogique et le numérique, je crée des sets qui naviguent entre obscurité et lumière.
Mes influences vont de la Deep House berlinoise à la Progressive Trance mélodique. Chaque mix est conçu comme une histoire, avec un début, une montée en puissance et une résolution cathartique.
{/* Contact Section */}
{/* Footer */}
2LUCID
© 2026 Tous droits réservés.
{/* Sticky Player Bar */}
{/* Progress Bar (Visual & Interactive) */}
{/* Track Info */}
{currentTrack && (
<>
{currentTrack.title}
{currentTrack.genre}
{loadError &&
Fichier introuvable}
>
)}
{/* Controls */}
setIsPlaying(!isPlaying)}
className="w-10 h-10 rounded-full bg-white text-black flex items-center justify-center hover:scale-105 transition-transform"
>
{isPlaying ? : }
{/* Volume / Time */}
{/* Notification Toast */}
{showNotification && (
Message envoyé !
Je vous répondrai dès que possible.
)}
{/* CSS personnalisé pour animations spécifiques */}
);
}