✨ Add project detail page with prev/next navigation (Story 2.3)
- Enhance ProjectController show() with prev/next navigation data - Create useFetchProject composable with ProjectNavigation type - Implement [slug].vue with full project details: - Hero image, title with featured badge, formatted date - Description, external links (site/GitHub) - Skills grid with level progression (before → after) - Prev/next navigation with project titles - 404 state with spider narrator - Add dynamic SEO meta tags with og:image from project - Responsive design: stacked mobile, grid desktop Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Story 2.3: Page Projet - Détail
|
||||
|
||||
Status: ready-for-dev
|
||||
Status: review
|
||||
|
||||
## Story
|
||||
|
||||
@@ -22,59 +22,59 @@ so that je comprends le travail réalisé et les technologies utilisées.
|
||||
|
||||
## Tasks / Subtasks
|
||||
|
||||
- [ ] **Task 1: Créer l'endpoint API pour le détail du projet** (AC: #1, #2, #3, #4, #8)
|
||||
- [ ] Ajouter la méthode `show($slug)` dans `ProjectController`
|
||||
- [ ] Charger le projet avec ses compétences (eager loading)
|
||||
- [ ] Retourner 404 si le slug n'existe pas
|
||||
- [ ] Inclure les données de traduction selon `Accept-Language`
|
||||
- [x] **Task 1: Créer l'endpoint API pour le détail du projet** (AC: #1, #2, #3, #4, #8)
|
||||
- [x] Ajouter la méthode `show($slug)` dans `ProjectController`
|
||||
- [x] Charger le projet avec ses compétences (eager loading)
|
||||
- [x] Retourner 404 si le slug n'existe pas
|
||||
- [x] Inclure les données de traduction selon `Accept-Language`
|
||||
|
||||
- [ ] **Task 2: Créer l'endpoint API pour la navigation prev/next** (AC: #5)
|
||||
- [ ] Ajouter une méthode `navigation($slug)` ou inclure dans `show()`
|
||||
- [ ] Retourner le projet précédent et suivant (basé sur l'ordre de tri)
|
||||
- [ ] Si premier projet : prev = null, si dernier : next = null
|
||||
- [x] **Task 2: Créer l'endpoint API pour la navigation prev/next** (AC: #5)
|
||||
- [x] Ajouter une méthode `navigation($slug)` ou inclure dans `show()`
|
||||
- [x] Retourner le projet précédent et suivant (basé sur l'ordre de tri)
|
||||
- [x] Si premier projet : prev = null, si dernier : next = null
|
||||
|
||||
- [ ] **Task 3: Créer le composable useFetchProject** (AC: #1)
|
||||
- [ ] Créer `frontend/app/composables/useFetchProject.ts`
|
||||
- [ ] Accepter le slug en paramètre
|
||||
- [ ] Gérer les états loading, error, data
|
||||
- [ ] Gérer l'erreur 404
|
||||
- [x] **Task 3: Créer le composable useFetchProject** (AC: #1)
|
||||
- [x] Créer `frontend/app/composables/useFetchProject.ts`
|
||||
- [x] Accepter le slug en paramètre
|
||||
- [x] Gérer les états loading, error, data
|
||||
- [x] Gérer l'erreur 404
|
||||
|
||||
- [ ] **Task 4: Créer la page [slug].vue** (AC: #1, #2, #3, #4, #6, #9)
|
||||
- [ ] Créer `frontend/app/pages/projets/[slug].vue`
|
||||
- [ ] Afficher l'image principale en grand format
|
||||
- [ ] Afficher le titre et la description complète
|
||||
- [ ] Afficher la date de réalisation formatée
|
||||
- [ ] Afficher la liste des compétences avec progression (avant → après)
|
||||
- [ ] Afficher les liens externes (site live, GitHub) si présents
|
||||
- [ ] Ajouter un bouton "Retour à la galerie"
|
||||
- [x] **Task 4: Créer la page [slug].vue** (AC: #1, #2, #3, #4, #6, #9)
|
||||
- [x] Créer `frontend/app/pages/projets/[slug].vue`
|
||||
- [x] Afficher l'image principale en grand format
|
||||
- [x] Afficher le titre et la description complète
|
||||
- [x] Afficher la date de réalisation formatée
|
||||
- [x] Afficher la liste des compétences avec progression (avant → après)
|
||||
- [x] Afficher les liens externes (site live, GitHub) si présents
|
||||
- [x] Ajouter un bouton "Retour à la galerie"
|
||||
|
||||
- [ ] **Task 5: Implémenter la navigation prev/next** (AC: #5)
|
||||
- [ ] Ajouter les boutons "Projet précédent" et "Projet suivant"
|
||||
- [ ] Utiliser NuxtLink pour la navigation
|
||||
- [ ] Afficher le titre du projet dans le bouton
|
||||
- [ ] Désactiver/masquer si pas de prev ou next
|
||||
- [x] **Task 5: Implémenter la navigation prev/next** (AC: #5)
|
||||
- [x] Ajouter les boutons "Projet précédent" et "Projet suivant"
|
||||
- [x] Utiliser NuxtLink pour la navigation
|
||||
- [x] Afficher le titre du projet dans le bouton
|
||||
- [x] Désactiver/masquer si pas de prev ou next
|
||||
|
||||
- [ ] **Task 6: Meta tags SEO dynamiques** (AC: #7)
|
||||
- [ ] Utiliser `useHead()` avec le titre du projet
|
||||
- [ ] Utiliser `useSeoMeta()` pour description, og:title, og:description, og:image
|
||||
- [ ] L'image OG doit être l'image du projet
|
||||
- [x] **Task 6: Meta tags SEO dynamiques** (AC: #7)
|
||||
- [x] Utiliser `useHead()` avec le titre du projet
|
||||
- [x] Utiliser `useSeoMeta()` pour description, og:title, og:description, og:image
|
||||
- [x] L'image OG doit être l'image du projet
|
||||
|
||||
- [ ] **Task 7: Gestion de l'erreur 404** (AC: #8)
|
||||
- [ ] Détecter si le projet n'existe pas
|
||||
- [ ] Afficher un message approprié avec le narrateur
|
||||
- [ ] Proposer de retourner à la galerie
|
||||
- [x] **Task 7: Gestion de l'erreur 404** (AC: #8)
|
||||
- [x] Détecter si le projet n'existe pas
|
||||
- [x] Afficher un message approprié avec le narrateur
|
||||
- [x] Proposer de retourner à la galerie
|
||||
|
||||
- [ ] **Task 8: Design responsive** (AC: #9)
|
||||
- [ ] Mobile : layout vertical, image pleine largeur
|
||||
- [ ] Desktop : layout 2 colonnes (image + contenu) ou grande image + contenu dessous
|
||||
- [ ] Liste des compétences responsive (flex wrap)
|
||||
- [x] **Task 8: Design responsive** (AC: #9)
|
||||
- [x] Mobile : layout vertical, image pleine largeur
|
||||
- [x] Desktop : layout 2 colonnes (image + contenu) ou grande image + contenu dessous
|
||||
- [x] Liste des compétences responsive (flex wrap)
|
||||
|
||||
- [ ] **Task 9: Tests et validation**
|
||||
- [ ] Tester avec différents slugs de projets
|
||||
- [ ] Tester la navigation prev/next
|
||||
- [ ] Tester le 404 avec un slug inexistant
|
||||
- [ ] Valider les meta tags SEO
|
||||
- [ ] Tester le responsive
|
||||
- [x] **Task 9: Tests et validation**
|
||||
- [x] Tester avec différents slugs de projets
|
||||
- [x] Tester la navigation prev/next
|
||||
- [x] Tester le 404 avec un slug inexistant
|
||||
- [x] Valider les meta tags SEO
|
||||
- [x] Tester le responsive
|
||||
|
||||
## Dev Notes
|
||||
|
||||
@@ -437,16 +437,40 @@ frontend/nuxt.config.ts # AJOUTER datetimeFormats
|
||||
|
||||
### Agent Model Used
|
||||
|
||||
{{agent_model_name_version}}
|
||||
Claude Opus 4.5 (claude-opus-4-5-20251101)
|
||||
|
||||
### Debug Log References
|
||||
|
||||
- Aucun problème. Méthode show() existait déjà mais sans navigation prev/next.
|
||||
|
||||
### Completion Notes List
|
||||
|
||||
- ProjectController show() amélioré avec navigation prev/next et erreur 404 structurée
|
||||
- Composable useFetchProject créé avec typage ProjectNavigation
|
||||
- Page [slug].vue complète avec :
|
||||
- Image principale pleine largeur
|
||||
- Titre, date formatée selon locale, badge featured
|
||||
- Description complète
|
||||
- Liens externes (site et GitHub)
|
||||
- Grille responsive des compétences utilisées avec niveaux avant/après
|
||||
- Navigation prev/next avec titres traduits
|
||||
- État loading (skeleton), état 404 avec narrateur spider
|
||||
- SEO dynamique via useSeo avec og:image du projet
|
||||
- Formatage date via Intl.DateTimeFormat selon locale
|
||||
- Traductions FR/EN ajoutées (10 nouvelles clés projects.*)
|
||||
- Store progression visitSection('projets') sur mount
|
||||
|
||||
### Change Log
|
||||
| Date | Change | Author |
|
||||
|------|--------|--------|
|
||||
| 2026-02-04 | Story créée avec contexte complet | SM Agent |
|
||||
| 2026-02-06 | Tasks 1-9 implémentées et validées | Dev Agent (Claude Opus 4.5) |
|
||||
|
||||
### File List
|
||||
|
||||
- `api/app/Http/Controllers/Api/ProjectController.php` — MODIFIÉ (show avec navigation)
|
||||
- `frontend/app/composables/useFetchProject.ts` — CRÉÉ
|
||||
- `frontend/app/pages/projets/[slug].vue` — RÉÉCRIT
|
||||
- `frontend/i18n/fr.json` — MODIFIÉ (ajout projects.*)
|
||||
- `frontend/i18n/en.json` — MODIFIÉ (ajout projects.*)
|
||||
|
||||
|
||||
@@ -58,8 +58,8 @@ development_status:
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
epic-2: in-progress
|
||||
2-1-composant-projectcard: review
|
||||
2-2-page-projets-galerie: ready-for-dev
|
||||
2-3-page-projet-detail: ready-for-dev
|
||||
2-2-page-projets-galerie: review
|
||||
2-3-page-projet-detail: review
|
||||
2-4-page-competences-affichage-categories: ready-for-dev
|
||||
2-5-competences-cliquables-projets-lies: ready-for-dev
|
||||
2-6-page-temoignages-migrations-bdd: ready-for-dev
|
||||
|
||||
Reference in New Issue
Block a user