# Story 1.5: Landing page et choix du héros Status: review ## Story As a visiteur, I want choisir entre l'aventure et le mode express, puis sélectionner mon héros, so that mon expérience est adaptée à mon profil et mon temps disponible. ## Acceptance Criteria 1. **Given** le visiteur arrive sur la landing page (`/`) **When** la page se charge **Then** deux CTA distincts sont visibles : "Partir à l'aventure" et "Mode express" 2. **And** un texte d'accroche intrigant bilingue est affiché 3. **And** une animation d'entrée subtile est présente (respectant `prefers-reduced-motion`) 4. **And** le design est responsive (mobile + desktop) 5. **And** au clic sur "Partir à l'aventure", le composant `HeroSelector` s'affiche avec 3 cards illustrées (Recruteur, Client, Développeur) avec nom et description courte 6. **And** le héros sélectionné est stocké dans le store Pinia `useProgressionStore` (champ `hero`) 7. **And** au clic sur "Mode express", le visiteur est redirigé vers la page résumé 8. **And** le `HeroSelector` est accessible au clavier (`role="radiogroup"`, flèches pour naviguer, Enter pour sélectionner) ## Tasks / Subtasks - [x] **Task 1: Structure de la landing page** (AC: #1, #2, #4) - [x] Implémenter `frontend/app/pages/index.vue` - [x] Section hero avec texte d'accroche bilingue (`$t('landing.title')`, `$t('landing.subtitle')`) - [x] Deux boutons CTA côte à côte (desktop) ou empilés (mobile) - [x] Utiliser les couleurs du design system (sky-accent pour CTA principal) - [x] Layout responsive : centré verticalement, max-width pour le contenu - [x] **Task 2: Animations d'entrée** (AC: #3) - [x] Animation fade-in + slide-up pour le texte d'accroche - [x] Animation staggered pour les CTA (apparition décalée) - [x] Utiliser CSS animations ou GSAP (lazy-loaded) - [x] Media query `prefers-reduced-motion` : animations désactivées - [x] Durée totale : ~1s max - [x] **Task 3: Composant HeroSelector** (AC: #5, #8) - [x] Créer `frontend/app/components/feature/HeroSelector.vue` - [x] Props : `modelValue` (héros sélectionné), emit `update:modelValue` - [x] Afficher 3 cards : Recruteur, Client, Développeur - [x] Chaque card : illustration/icône, nom traduit, description courte traduite - [x] État visuel : card sélectionnée avec bordure accent - [x] Accessibilité : `role="radiogroup"`, `role="radio"` sur chaque card - [x] Navigation clavier : flèches gauche/droite, Enter pour confirmer - [x] Focus visible sur la card active - [x] **Task 4: Données des héros** (AC: #5) - [x] Définir les 3 héros dans un fichier de config ou composable - [x] Structure : `{ id: 'recruteur' | 'client' | 'dev', nameKey, descriptionKey, icon }` - [x] Traductions dans `i18n/fr.json` et `i18n/en.json` : - `hero.recruteur.name`: "Recruteur" - `hero.recruteur.description`: "Je cherche un talent pour mon équipe" - `hero.client.name`: "Client" - `hero.client.description`: "J'ai un projet à réaliser" - `hero.dev.name`: "Développeur" - `hero.dev.description`: "Je suis curieux de voir ton travail" - [x] **Task 5: Intégration avec le store Pinia** (AC: #6) - [x] Importer `useProgressionStore` (créé en Story 1.6, mais interface définie ici) - [x] Au choix du héros : `store.setHero(heroId)` - [x] Après sélection : naviguer vers la première zone ou afficher l'intro narrative - [x] Si store non disponible (Story 1.6 pas encore faite) : utiliser un state local temporaire - [x] **Task 6: Flow de sélection** (AC: #5, #6) - [x] État initial : CTA visibles, HeroSelector masqué - [x] Clic "Partir à l'aventure" : transition vers HeroSelector (fade/slide) - [x] Clic sur un héros : sélection visuelle - [x] Bouton "Confirmer" ou double-clic : valider et naviguer - [x] Bouton "Retour" pour revenir aux CTA - [x] Animation de transition fluide entre les états - [x] **Task 7: Redirection Mode Express** (AC: #7) - [x] Clic "Mode express" : `navigateTo(localePath('/resume'))` - [x] Pas de sélection de héros requise pour le mode express - [x] Le store peut rester sans héros défini (mode anonyme) - [x] **Task 8: SEO et meta tags** (AC: #1) - [x] Utiliser `useSeo()` pour définir les meta tags de la landing - [x] Title : "Skycel - Portfolio interactif de Célian" - [x] Description : "Découvrez mon portfolio gamifié..." - [x] Open Graph image : image de preview attractive - [x] **Task 9: Validation finale** (AC: tous) - [x] Page accessible en FR (`/`) et EN (`/en`) - [x] Textes traduits correctement - [x] CTA fonctionnels - [x] HeroSelector s'affiche et fonctionne - [x] Navigation clavier complète - [x] Animations fluides (et désactivées si reduced-motion) - [x] Responsive : mobile et desktop - [x] Redirection vers `/resume` fonctionne ## Dev Notes ### Structure de la landing page ``` ┌─────────────────────────────────────────────────────────────────┐ │ LANDING PAGE │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ [Logo ou titre animé] │ │ │ │ "Bienvenue dans mon univers" │ │ Développeur Full-Stack │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Partir à │ │ Mode express │ │ │ │ l'aventure │ │ (30 secondes) │ │ │ └─────────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ↓ Clic "Aventure" ┌─────────────────────────────────────────────────────────────────┐ │ HERO SELECTOR │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ "Qui êtes-vous, voyageur ?" │ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 👔 │ │ 💼 │ │ 💻 │ │ │ │Recruteur│ │ Client │ │ Dev │ │ │ │ "Je..." │ │ "J'ai..." │ │"Je suis.."│ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ [Retour] [Confirmer] │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ### Composant HeroSelector ```vue ``` ### Traductions à ajouter ```json // frontend/i18n/fr.json { "landing": { "title": "Bienvenue dans mon univers", "subtitle": "Développeur Full-Stack passionné", "cta_adventure": "Partir à l'aventure", "cta_express": "Mode express (30s)" }, "hero": { "question": "Qui êtes-vous, voyageur ?", "select_label": "Sélectionnez votre profil", "recruteur": { "name": "Recruteur", "description": "Je cherche un talent pour rejoindre mon équipe" }, "client": { "name": "Client", "description": "J'ai un projet à réaliser et je cherche le bon développeur" }, "dev": { "name": "Développeur", "description": "Je suis curieux de découvrir ton travail et tes compétences" } } } ``` ### Animations CSS ```css /* Animations d'entrée pour la landing */ @keyframes fadeSlideUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .animate-fade-slide-up { animation: fadeSlideUp 0.6s ease-out forwards; } .animate-delay-100 { animation-delay: 0.1s; } .animate-delay-200 { animation-delay: 0.2s; } .animate-delay-300 { animation-delay: 0.3s; } /* Respect prefers-reduced-motion */ @media (prefers-reduced-motion: reduce) { .animate-fade-slide-up { animation: none; opacity: 1; transform: none; } } ``` ### Dépendances **Cette story DÉPEND de :** - Story 1.3 : Système i18n pour les traductions - Story 1.4 : Layout default, transitions de page, useSeo() **Cette story PRÉPARE pour :** - Story 1.6 : Le store Pinia stockera le héros sélectionné - Story 4.2 : L'intro narrative suivra la sélection du héros **Note :** Si Story 1.6 n'est pas encore implémentée, utiliser un state local (`ref`) comme placeholder. ### References - [Source: docs/planning-artifacts/epics.md#Story-1.5] - [Source: docs/planning-artifacts/ux-design-specification.md#Hero-System] - [Source: docs/planning-artifacts/architecture.md#Store-Pinia] - [Source: docs/prd-gamification.md#FR1] ### Technical Requirements | Requirement | Value | Source | |-------------|-------|--------| | Héros disponibles | Recruteur, Client, Dev | UX Design | | Accessibilité | WCAG AA, keyboard nav | NFR6 | | Animations | Respecter reduced-motion | NFR6 | | Responsive | Mobile + Desktop | NFR3 | ## Dev Agent Record ### Agent Model Used Claude Opus 4.5 (claude-opus-4-5-20251101) ### Debug Log References - Aucun problème majeur rencontré. Le HeroSelector est rendu côté client (interactif), pas dans le HTML SSR initial. ### Completion Notes List - Landing page avec accroche bilingue, animations fade-slide-up staggered, responsive - HeroSelector accessible (role="radiogroup", navigation clavier flèches+Enter, focus management) - 3 héros : Recruteur, Client, Développeur avec icônes emoji et traductions FR/EN - Flow : CTA → Transition hero → Sélection → Confirm → Navigation vers /projets - Mode express : NuxtLink vers /resume (pas de sélection de héros) - Intégration store Pinia préparée (commentaire placeholder pour Story 1.6) - prefers-reduced-motion respecté pour toutes les animations - SEO meta tags sur la landing via useSeo() ### Change Log | Date | Change | Author | |------|--------|--------| | 2026-02-03 | Story créée avec contexte complet | SM Agent | | 2026-02-05 | Tasks 1-9 implémentées et validées | Dev Agent (Claude Opus 4.5) | ### File List - `frontend/app/pages/index.vue` — MODIFIÉ (landing complète avec flow HeroSelector) - `frontend/app/components/feature/HeroSelector.vue` — CRÉÉ - `frontend/app/assets/css/transitions.css` — MODIFIÉ (animations landing + hero transition) - `frontend/i18n/fr.json` — MODIFIÉ (ajout hero.*, landing.subtitle/cta_express) - `frontend/i18n/en.json` — MODIFIÉ (ajout hero.*, landing.subtitle/cta_express)