// ProjectsExpedition — la « découverte des projets » de l'accueil. // Chaque projet est une « étape d'expédition » : vignette topo + fiche carnet, // en alternance gauche/droite, avec usage IA, cordée, durée et un CTA. // Règle du dénivelé : 100 M = 1 techno/outil appris sur le projet. // // Les données vivent dans projects-data.js (window.EXPEDITION). // L'accueil n'affiche que les projets « featured »; la page projets.html // affiche l'ensemble. Pour ajouter un projet : voir projects-data.js. // NB : ne jamais nommer cette constante « EXPEDITION ». Babel compile les // const de ce fichier en `var` au niveau global — `var EXPEDITION` écraserait // alors window.EXPEDITION avec la liste filtrée, et projets.html (chargé // après ce fichier) n'y verrait plus que les projets « featured ». const FEATURED_STEPS = (window.EXPEDITION || []).filter(p => p.featured); // little topo-rings vignette behind each photo function TopoRings({ seed }) { const rings = []; const n = 6; const cx = 50 + (seed % 3) * 6; const cy = 50 + (seed % 5) * 4; for (let i = 0; i < n; i++) { const r = 12 + i * 9; rings.push(); } return ( ); } function AiUsage({ level }) { return (
USAGE IA {[1,2,3,4,5].map(i => ( ))}
); } function ExpeditionCard({ e, i, onOpen }) { const side = i % 2 === 0 ? "left" : "right"; // Ouverture de la fiche — partagée entre la photo et le bouton "Explorer" const open = () => onOpen({ id: e.id, title: e.title, img: e.img, video: e.video, date: e.subtitle.split(' · ')[1] || '', stamp: e.n, role: e.subtitle, desc: e.desc, tags: e.tags, url: e.url || '#', }); return (
{/* Connector dot anchored to the central trail */}
{ if (ev.key === "Enter" || ev.key === " ") { ev.preventDefault(); open(); } }} > {e.video ?
{e.n} {e.subtitle}

{e.title}

CORDÉE
{e.cordée}
DURÉE
{e.durée}
DÉNIVELÉ
{e.alt}

{e.desc}

    {e.tags.map(t =>
  • {t}
  • )}
); } function ProjectsExpedition({ onOpen }) { const count = FEATURED_STEPS.length; return (
03KM 03 · SÉLECTION
EXPÉDITION 2024 — 2026 {count} ÉTAPES EN VEDETTE BOUCLE COMPLÈTE

Decouvre mes aventures.

Trois ans de projets menés en entreprise, en cours et en autonomie.

Chaque fiche présente le projet, la technique et le contexte.

Ouvrez une étape pour découvrir le projet en détail.

DÉPART
ÉTAPE
SOMMET
{/* central dashed trail spine */} {FEATURED_STEPS.map((e, i) => ( ))} {/* Le badge "sommet" devient un bouton vers la page de tous les projets */} ON N'EST PAS ENCORE AU SOMMET ! Voir tous les projets
); } function ProjectModal({ project, onClose }) { React.useEffect(() => { const onKey = (e) => e.key === "Escape" && onClose(); window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [onClose]); // Pas d'animation JS sur le contenu : la carte a déjà son entrée en CSS // (vm-pop). Un gsap.from + autoAlpha laissait le dernier élément — le // bouton "VOIR LE PROJET" — bloqué à visibility:hidden si le tween ne // se terminait pas. On garantit ici que tout le contenu reste visible. return (
e.stopPropagation()}>
{project.video ?

{project.title}

{project.role}

{project.desc}

{project.tags.map(t => {t})}
VOIR LE PROJET
); } window.ProjectsExpedition = ProjectsExpedition; window.ProjectModal = ProjectModal; window.ExpeditionCard = ExpeditionCard;