- Dockerfile multi-étapes (node:22-alpine, pnpm, output standalone), .dockerignore - docker-compose : service web (hôte 4000) + mysql + mongo avec volumes nommés - Env de connexion selon DB_IMPL (MYSQL_*, MONGODB_URI) ; mongo ?authSource=admin - Seed MySQL via 02-seed.sh (--default-character-set=utf8mb4) pour un UTF-8 propre - fix(api): parseTags gère les colonnes JSON déjà parsées par mysql2 - TODO : phase 5 et DoD cochées
210 lines
12 KiB
Markdown
210 lines
12 KiB
Markdown
# TODO — Application web Flashcards (développement assisté par IA)
|
|
|
|
Document de spécifications et checklist destiné à guider un agent IA dans le développement complet de l'application. Il complète le GOAL.md en le rendant actionnable.
|
|
|
|
---
|
|
|
|
## 1. Contexte produit
|
|
|
|
Application web **SPA + PWA** : Flashcards affiche des cartes (questions/réponses) sur des sujets de code, de développement ou de culture tech.
|
|
|
|
### Principe du jeu
|
|
|
|
- Affichage d'une **carte au hasard** : une question ou un terme apparaît, la réponse est cachée.
|
|
- L'utilisateur peut **révéler la réponse** à la demande.
|
|
- Possibilité de tirer une carte au hasard sur un **thème précis** (code, langage, etc.).
|
|
|
|
### Gestion des cartes
|
|
|
|
- L'utilisateur peut **créer, modifier ou supprimer** une carte (CRUD complet).
|
|
- L'utilisateur peut **afficher la liste** des cartes ou **consulter une carte spécifique**.
|
|
|
|
---
|
|
|
|
## 2. Exigences fonctionnelles
|
|
|
|
> Chaque exigence doit être satisfaite avant de considérer la feature terminée.
|
|
|
|
| Ref | Exigence | Critère d'acceptation |
|
|
| ---- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
| F-01 | Afficher une carte au hasard | Un clic sur « Jouer » affiche UNE carte tirée aléatoirement de l'ensemble des cartes |
|
|
| F-02 | Dans un tirage aléatoire, la question est visible et la réponse cachée | Le terme/question s'affiche ; la réponse ne s'affiche pas |
|
|
| F-03 | Révéler la réponse | Un clic (ou action) déroule/affiche la réponse cachée ; un second clic la masque |
|
|
| F-04 | Tirer une carte au hasard **par thème** | L'utilisateur choisit un thème ; le tirage se fait uniquement parmi les cartes de ce thème |
|
|
| F-05 | Créer une carte | Formulaire de création avec question, réponse et thème ; la carte est persistée |
|
|
| F-06 | Modifier une carte | Formulaire pré-rempli ; la modification est persistée |
|
|
| F-07 | Supprimer une carte | Confirmation avant suppression ; la carte disparaît de la liste |
|
|
| F-08 | Lister les cartes | La liste complète des cartes s'affiche (avec au minimum question + thème) |
|
|
| F-09 | Consulter une carte spécifique | L'accès direct à une carte (via sa route/id) affiche son détail complet |
|
|
| F-10 | Thèmes | L'utilisateur peut choisir un thème reflétant les cartes existantes |
|
|
|
|
---
|
|
|
|
## 3. Modélisation de données (proposition à valider)
|
|
|
|
### Entité `Card`
|
|
|
|
| Champ | Type | Contrainte | Description |
|
|
| ----------- | ---------- | ----------- | ---------------------------------------------- |
|
|
| `id` | string/INT | unique (PK) | Identifiant stable de la carte |
|
|
| `question` | string | requis | Terme ou question affiché |
|
|
| `response` | string | requis | Réponse cachée puis révélée |
|
|
| `theme` | string | requis | Thème/catégorie (ex. « code », « javascript ») |
|
|
| `tags` | string[] | optionnel | Mots-clés additionnels |
|
|
| `createdAt` | datetime | auto | Date de création |
|
|
| `updatedAt` | datetime | auto | Date de dernière modification |
|
|
|
|
> La liste des thèmes peut être dérivée dynamiquement des valeurs `theme` distinctes présentes en base (simplicité) ou gérée en entité `Theme` dédiée (robustesse). Choix à figer en phase de conception.
|
|
|
|
### Représentation duale SGBD
|
|
|
|
- **MySQL** : table `cards`
|
|
- **MongoDB** : collection `cards`
|
|
|
|
Le même `id` doit permettre de retrouver une carte dans les deux SGBD (l'id métier n'est pas nécessairement l'id technique Mongo).
|
|
|
|
---
|
|
|
|
## 4. Exigences techniques et architecture
|
|
|
|
### Stack
|
|
|
|
- Framework : **Next.js**
|
|
- Langage : **TypeScript** (strict)
|
|
- Styles : **Tailwind**
|
|
- Qualité : **ESLint**, **Prettier**
|
|
- Tests unitaires : **Vitest** avec **coverage**
|
|
|
|
### Base de données — double SGBD simultané (contrainte pédagogique)
|
|
|
|
Bien qu'il n'y ait pas réellement besoin de 2 SGBD, dans un but pédagogique les **deux bases doivent être gérées simultanément** :
|
|
|
|
- **MySQL** (conteneur Docker)
|
|
- **MongoDB** (conteneur Docker)
|
|
|
|
### Exigence architecturale majeure : couche d'accès aux données GÉNÉRIQUE
|
|
|
|
Les composants d'accès aux données doivent être **le plus générique possible**. Concrètement :
|
|
|
|
- Définir une **abstraction commune** (interface/repository générique, ex. `CardRepository`) exposant les opérations : `findAll`, `findById`, `create`, `update`, `delete`, `findRandom`, `findRandomByTheme`, `findThemes`.
|
|
- Fournir **deux implémentations** de cette abstraction : une pour MySQL, une pour MongoDB.
|
|
- **Aucun composant métier (service, route, UI) ne doit dépendre d'un SGBD précis** : il consomme uniquement l'abstraction.
|
|
- Les deux implémentations doivent être utilisables et activables (par config/DI/injection), et les tests doivent couvrir les deux.
|
|
|
|
### Déploiement
|
|
|
|
- **Docker** via **docker-compose**
|
|
- **Volumes nommés** pour la persistance des données des 2 SGBD
|
|
- Services au minimum : `web` (Next.js), `mysql`, `mongo`
|
|
|
|
---
|
|
|
|
## 5. Définition de fait (Definition of Done)
|
|
|
|
Une feature est « faite » si et seulement si :
|
|
|
|
- [x] Les tests unitaires (Vitest) passent, **coverage** généré et au-dessus du seuil défini
|
|
- [x] `lint` (ESLint) et `format` (Prettier — check) sans erreur
|
|
- [x] TypeScript strict compile sans erreur
|
|
- [x] L'implémentation est branchée sur la **couche générique d'accès aux données**
|
|
- [x] Les **deux SGBD** (MySQL + MongoDB) fonctionnent simultanément en local
|
|
- [x] Le comportement correspond aux critères d'acceptation de la section 2
|
|
- [x] Construit et lançable via docker-compose avec volumes persistants
|
|
|
|
---
|
|
|
|
## 6. Checklist de développement par phases
|
|
|
|
> Ordre d'exécution recommandé. Passer à la phase suivante uniquement si la DoD de la phase courante est remplie.
|
|
|
|
### Phase 0 — Scaffolding
|
|
|
|
- [ ] Initialiser le projet Next.js + TypeScript (strict)
|
|
- [ ] Configurer Tailwind
|
|
- [ ] Configurer ESLint + Prettier
|
|
- [ ] Configurer Vitest + rapport de coverage
|
|
- [ ] Fixer le seuil de coverage (à définir, ex. 80%)
|
|
- [ ] DoD : `lint`, `format`, `typecheck`, `test` s'exécutent sans erreur sur un squelette
|
|
|
|
### Phase 1 — Données et couche d'accès générique
|
|
|
|
- [ ] Schéma MySQL (table `cards`) + migration/seed
|
|
- [ ] Schéma MongoDB (collection `cards`) + seed
|
|
- [ ] Interface générique `CardRepository` (contrat complet)
|
|
- [ ] Implémentation `MysqlCardRepository`
|
|
- [ ] Implémentation `MongoCardRepository`
|
|
- [ ] Mécanisme d'activation/sélection de l'implémentation (config)
|
|
- [ ] Tests unitaires des deux implémentations
|
|
- [ ] DoD : phase 0 + les 2 repositories testés et interchangeables
|
|
|
|
### Phase 2 — API / services métier
|
|
|
|
- [ ] Service métier `CardService` reposant uniquement sur l'abstraction repository
|
|
- [ ] Routes API : liste, détail, création, modification, suppression
|
|
- [ ] Routes API : tirage aléatoire simple + tirage aléatoire par thème + liste des thèmes
|
|
- [ ] Validation des entrées (contrats TypeScript / schémas)
|
|
- [ ] Gestion d'erreurs cohérente (404 carte inconnue, 400 payload invalide…)
|
|
- [ ] Tests unitaires du service (mock du repository)
|
|
- [ ] DoD : phases précédentes + contexte de MCP de l'API
|
|
|
|
### Phase 3 — Interface utilisateur
|
|
|
|
- [x] Page/vue **liste des cartes** (F-08)
|
|
- [x] Page/vue **détail d'une carte** (F-09)
|
|
- [x] Formulaire **création** (F-05)
|
|
- [x] Formulaire **édition** (F-06)
|
|
- [x] **Suppression** avec confirmation (F-07)
|
|
- [x] Vue **jeu** : tirage aléatoire global + sélecteur de thème (F-01, F-02, F-03, F-04, F-10)
|
|
- [x] Navigation/flux SPA cohérent (routes Next.js)
|
|
- [x] DoD : phases précédentes + parcours utilisateur complet fonctionnel
|
|
|
|
### Phase 4 — Tests
|
|
|
|
- [x] Tests des composants UI (composants critiques)
|
|
- [x] Couverture des critères F-01 à F-10
|
|
- [x] Coverage au seuil défini (Phase 0)
|
|
- [x] DoD : toutes phases précédentes vertes + coverage ok
|
|
|
|
Traceabilité F-01 à F-10 (tests unitaires) :
|
|
|
|
| Ref | Critère | Couverture |
|
|
| ---- | ----------------------------------- | --------------------------------------------------------------------------------- |
|
|
| F-01 | Carte au hasard | `play-view.test.tsx`, `app/play/page.test.tsx`, API `random`, `card-service.test` |
|
|
| F-02 | Question visible, réponse cachée | `play-view.test.tsx` |
|
|
| F-03 | Révéler / masquer la réponse | `play-view.test.tsx` |
|
|
| F-04 | Tirage par thème | `play-view.test.tsx`, API `random`, `card-service.test` |
|
|
| F-05 | Créer une carte | `cards/new/page.test.tsx`, `card-form.test.tsx`, `cards/page.test.tsx`, API POST |
|
|
| F-06 | Modifier une carte (pré-remplie) | `cards/[id]/edit/page.test.tsx`, `card-form.test.tsx`, API PUT |
|
|
| F-07 | Supprimer avec confirmation | `card-delete.test.tsx`, API DELETE |
|
|
| F-08 | Lister les cartes | `cards/page.test.tsx`, `card-list.test.tsx`, API GET |
|
|
| F-09 | Consulter une carte spécifique | `cards/[id]/page.test.tsx`, `card-detail.test.tsx`, API GET `[id]` |
|
|
| F-10 | Thèmes issues des cartes existantes | `play-view.test.tsx`, `app/play/page.test.tsx`, API `themes` |
|
|
|
|
### Phase 5 — PWA, déploiement
|
|
|
|
- [x] Manifest PWA + service worker (installable, hors-ligne) — la stack SPA le permet
|
|
- [x] `docker-compose.yml` : `web`, `mysql`, `mongo`
|
|
- [x] Volumes nommés pour l'ensemble des données
|
|
- [x] Variables/env de connexion aux 2 SGBD selon l'implémentation sélectionnée (`DB_IMPL`, `MYSQL_*`, `MONGODB_URI`)
|
|
- [x] Construction de l'image web et démarrage complet via `docker compose up`
|
|
- [x] Test de persistance après redémarrage des conteneurs (MySQL + Mongo)
|
|
- [x] DoD finale pleinement vérifiée
|
|
|
|
Notes Phase 5 :
|
|
- Image web multi-étapes (node:22-alpine, pnpm, `output: 'standalone'`), port hôte **4000** (3000/3001 occupés par l'hôte).
|
|
- Correction UTF-8 du seed MySQL : `02-seed.sh` avec `mysql --default-character-set=utf8mb4` (le `.sql` brut importait en double-encodage) ; lignes seed réparées en base via `CONVERT(BINARY(CONVERT(... USING latin1)) USING utf8mb4)`.
|
|
- Correction `parseTags()` dans le repository MySQL (`mysql2` auto-parse les colonnes JSON en tableaux).
|
|
- Mongo : URI avec `?authSource=admin` (l'utilisateur root est créé dans `admin`).
|
|
|
|
---
|
|
|
|
## 7. Points à trancher / en attente de décision
|
|
|
|
- [x] Couverture : seuil de coverage exact (>= 80 % imposé, effectif ~95 % stmts)
|
|
- [ ] Selon cas : `Theme` en table dédiée vs dérivation des `theme` distincts
|
|
- [x] Choix par défaut de l'implémentation repository pour la prod (MySQL par défaut via `DB_IMPL`)
|
|
- [ ] Authentification éventuelle (hors périmètre README, à confirmer si nécessaire)
|
|
|
|
22/09: phase 3 terminée (jeu + navigation intégrés), `pnpm check` vert
|
|
22/09: phase 4 terminée (tests UI composants + pages, traceabilité F-01 à F-10, coverage ok)
|