docs: regrouper la documentation dans docs/ (hors README)
This commit is contained in:
1 parent
087945472a
commit
8ff530bf99
4 files changed
+1
-1
No files matched your search
@@ -0,0 +1,36 @@
|
||||
# Application web Flashcards
|
||||
|
||||
Flashcards est application web SPA PWA permet d'afficher des cartes sur des sujets de code, de développement ou de culture tech.
|
||||
|
||||
## Principe du jeu
|
||||
|
||||
Le jeu consiste à afficher une carte au hasard.
|
||||
une question ou un terme apparaît. La réponse est cachée. Si l'utilisateur souhaite consuletr la réponse, il peut faire dérouler la réponse.
|
||||
|
||||
Il est néanmoins possible de sélectionner une carte au hasard sur un thème plus précis : code, langage, etc...
|
||||
|
||||
L'utilisateur peut créer, modifier ou supprimer une carte (CRUD).
|
||||
|
||||
L'utilisatuer peut afficher la liste des cartes ou consulter une carte spécifique.
|
||||
|
||||
## Stack technique
|
||||
|
||||
- Framework : Next Js
|
||||
- Typescript
|
||||
- Tailwind
|
||||
- Eslint, Prettier
|
||||
- Test unitaires : Vitest avec coverage
|
||||
|
||||
### Base de données
|
||||
|
||||
Bien qu'il n'y ait réellement pas besoin de 2 SGBD, dans un but pédagogique, il faudra gérer les 2 bases de données simultanément.
|
||||
|
||||
Les composants d'accès aux données devront être le plus génériques possibles.
|
||||
|
||||
- Mysql (conteneur Docker)
|
||||
- Mongo Db (conteneur Docker)
|
||||
|
||||
### Déploiement
|
||||
|
||||
- Docker via docker-compose
|
||||
- Volumes managés
|
||||
@@ -0,0 +1,91 @@
|
||||
# MOD_OP — Mode opératoire (lancement et exploitation)
|
||||
|
||||
Procédure pas à pas pour lancer, vérifier, développer et arrêter l'application flashcards (web + MySQL + MongoDB en conteneurs Docker).
|
||||
|
||||
## 1. Prérequis
|
||||
|
||||
- Docker + Docker Compose installés et démarrés.
|
||||
- Node.js >= 20.19.0 et pnpm >= 9 (uniquement pour le mode dev local, étape 5).
|
||||
|
||||
## 2. Démarrage complet (production-like)
|
||||
|
||||
Depuis la racine du projet :
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
- `--build` : construit l'image du service web (nécessaire à la première exécution).
|
||||
- Le service `web` attend que `mysql` et `mongo` soient **healthy** (`depends_on` + healthchecks).
|
||||
|
||||
Résultat attendu (3 conteneurs up) :
|
||||
|
||||
| Service | Conteneur | Image | Port hôte | Port interne |
|
||||
| ------- | ---------------- | --------- | --------- | ------------ |
|
||||
| web | flashcards-web | (build .) | **4000** | 3000 |
|
||||
| mysql | flashcards-mysql | mysql:8.4 | 13306 | 3306 |
|
||||
| mongo | flashcards-mongo | mongo:8.2 | 27018 | 27017 |
|
||||
|
||||
> **Attention** : le port hôte 4000 a été retenu car 3000/3001 sont souvent occupés par d'autres processus. Le web écoute donc sur **http://localhost:4000**.
|
||||
|
||||
## 3. Vérifications
|
||||
|
||||
```bash
|
||||
docker compose ps # 3 services "running" (mysql/mongo "healthy")
|
||||
curl http://localhost:4000/api/themes
|
||||
curl http://localhost:4000/api/cards
|
||||
```
|
||||
|
||||
- La liste des thèmes doit répondre `["docker","git","javascript","react","typescript"]` (seed).
|
||||
- Ouvrir **http://localhost:4000** : accueil, puis `/play` (tirage de cartes), `/cards` et `/cards/new` (CRUD).
|
||||
|
||||
## 4. Choisir l'implémentation SGBD (`DB_IMPL`)
|
||||
|
||||
L'application est branchée sur une couche générique : MySQL (`mysql`, défaut) ou MongoDB (`mongo`).
|
||||
|
||||
```bash
|
||||
docker compose stop web
|
||||
DB_IMPL=mongo docker compose up -d web # bascule sur MongoDB
|
||||
DB_IMPL=mysql docker compose up -d web # retour sur MySQL (défaut)
|
||||
```
|
||||
|
||||
## 5. Mode développement local (hot reload)
|
||||
|
||||
Les bases restent en Docker, l'appli tourne en local :
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
docker compose up -d mysql mongo # bases seules
|
||||
pnpm install
|
||||
pnpm dev # http://localhost:3000
|
||||
```
|
||||
|
||||
Le `.env` pointe vers les ports exposés des conteneurs (`localhost:13306`, `localhost:27018`) et `DB_IMPL=mysql` par défaut.
|
||||
|
||||
## 6. Ré-initialiser le seed
|
||||
|
||||
Les scripts `docker/init/*` ne s'exécutent **qu'à la première création des volumes** (y compris l'encodage UTF-8 forcé par `02-seed.sh`). Pour repartir d'un état vierge :
|
||||
|
||||
```bash
|
||||
docker compose down -v # ⚠️ supprime les données des volumes nommés
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## 7. Arrêt / redémarrage / nettoyage
|
||||
|
||||
```bash
|
||||
docker compose stop # arrêt (données conservées)
|
||||
docker compose start # redémarrage
|
||||
docker compose restart web # redémarrage du web seul
|
||||
docker compose down # arrêt + suppression des conteneurs (volumes conservés)
|
||||
docker compose down -v # arrêt + suppression des conteneurs ET des volumes
|
||||
```
|
||||
|
||||
## 8. Dépannage rapide
|
||||
|
||||
| Symptôme | Action |
|
||||
| --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| Le web ne démarre pas | `docker compose logs web` (il attend le healthy des bases) |
|
||||
| `Authentication failed` (Mongo) | Vérifier `?authSource=admin` dans `MONGODB_URI` |
|
||||
| Caractères accentués illisibles (MySQL) | Seed importé sans utf8mb4 → réinitialiser via l'étape 6 |
|
||||
| Port déjà utilisé | Le web est sur le port hôte 4000 (modifiable dans `docker-compose.yml`) |
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
# 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)
|
||||
Reference in new issue
Block a user