diff --git a/ENONCE_final_boss.md b/ENONCE_final_boss.md
index 9f7eea1..1e25aa0 100644
--- a/ENONCE_final_boss.md
+++ b/ENONCE_final_boss.md
@@ -1,21 +1,30 @@
-# đ ĂnoncĂ© FINAL â « Boss de fin » đ
+# đ ĂnoncĂ© FINAL â « Boss de fin »
-Dernier jour ! đ Tu as dĂ©jĂ tout l'arsenal : composants, props, state, lifting state up, `useEffect`, **`fetch`**, formulaire, tri, filtre, **React Router**, **`localStorage`**. Aujourd'hui on **s'amuse** : 4 modules courts et stylĂ©s. Fais-en autant que tu veux, dans l'ordre que tu veux â mais le **Module L** est le vrai boss, attaque-le en premier. đȘ
+Dernier jour. Tu as tout l'arsenal : composants, props, state, lifting state up, `useEffect`, `fetch`, formulaire, tri, filtre, React Router, `localStorage`. Aujourd'hui, place Ă la pratique libre.
-| Module | Tu fais | Niveau | Fun |
-|---|---|---|---|
-| L | La page dĂ©tail **complĂšte** (state remontĂ© au routeur) | âââ | đ |
-| M | Bouton **đČ Â« Au hasard »** (page d'un jeu alĂ©atoire) | ââ | đ |
-| N | **đ Le Hall of Fame** des jeux les plus likĂ©s | ââ | đ„ |
-| O | **đ ThĂšme sombre** qui se souvient de ton choix | ââ | đ |
+Un seul module est **obligatoire** : le **Module L** (la page détail, le vrai boss). Les autres forment un **menu** : pioche dans l'ordre que tu veux, fais-en le plus possible. Chacun est court et indépendant.
+
+| Module | Tu fais | Niveau |
+|---|---|---|
+| **L** | Page dĂ©tail **complĂšte** (donnĂ©es centralisĂ©es dans `App`) â *obligatoire* | âââ |
+| M | Bouton « au hasard » (`useNavigate`) | ââ |
+| N | Le Hall of Fame des jeux les plus likĂ©s | ââ |
+| O | Bouton « supprimer » un jeu | ââ |
+| P | ThĂšme sombre qui se souvient du choix | ââ |
+| Q | Mode Versus : deux jeux s'affrontent | ââ |
+| R | Filtre par Type (2d / 3d) | ââ |
+| S | Statistiques (total, moyenne d'annĂ©e) | ââ |
+| T | Page « 404 » pour les URL inconnues | ââ |
+| U | Tri ascendant â descendant | â |
+| V | Custom hook `useLocalStorage` (refacto) | âââ |
---
-## đ Module L â Le boss : centraliser les donnĂ©es dans `App`
+## đ Module L â Le boss : centraliser les donnĂ©es dans `App` (obligatoire)
-Dans `CORRECTION_page_detail.md` tu as fait une version simple (la page détail re-`fetch` toute seule). Ses limites : les jeux **ajoutés au formulaire** et les **likes** n'arrivent pas dans le détail, parce que chacun vit dans son coin. On corrige ça **proprement**.
+Dans `CORRECTION_page_detail.md` tu as fait une version simple (la page détail re-`fetch` toute seule). Ses limites : les jeux **ajoutés au formulaire** et les **likes** n'arrivent pas dans le détail, parce que chacun vit dans son coin. On corrige ça proprement.
-**L'idĂ©e :** le `fetch`, la liste `jeux` **et** les likes doivent vivre **au-dessus** des deux pages â dans `App`. `App` les passe ensuite **en props** aux routes.
+L'idĂ©e : le `fetch`, la liste `jeux` **et** les likes doivent vivre **au-dessus** des deux pages â dans `App`, qui les passe ensuite **en props** aux routes.
### L.1 â Remonter le `fetch` et les Ă©tats dans `App.jsx`
```jsx
@@ -61,68 +70,65 @@ function App() {
}
```
-> đ§© **Le dĂ©clic :** une route reçoit des props comme n'importe quel composant â `element={}`. C'est ça qui « branche » la donnĂ©e sur les deux pages.
+> Le dĂ©clic : une route reçoit des props comme n'importe quel composant â `element={}`. C'est ça qui « branche » la donnĂ©e sur les deux pages.
-> đ **Nouveau rĂ©flexe likes :** avant, chaque `Carte` gardait son like dans son coin (`localStorage.getItem("likes-" + id)`). Maintenant c'est **un seul objet** `likes` (genre `{ "2": 3, "4": 1 }`) rangĂ© d'un coup. C'est ce qui rend possible le **podium** du Module N (impossible quand chaque like est Ă©parpillĂ©).
+> Nouveau réflexe likes : avant, chaque `Carte` gardait son like dans son coin (`localStorage.getItem("likes-" + id)`). Maintenant c'est **un seul objet** `likes` (genre `{ "2": 3, "4": 1 }`) rangé d'un coup. C'est ce qui rend possible le Hall of Fame du Module N (impossible quand chaque like est éparpillé).
### L.2 â `Accueil` et `Carte` lisent via les props
- `Accueil({ jeux, setJeux, likes, onLike })` : enlĂšve son `useState(jeux)` et son `fetch` (ils sont dans `App`). Garde `recherche`, `tri`, les champs du formulaire en local.
- Passe Ă chaque carte le bon compteur : `likes={likes[jeu.id] || 0}` et `onLike={() => onLike(jeu.id)}`.
- Dans `Carte`, supprime le `useState`/`useEffect` de likes : affiche `props.likes` et appelle `props.onLike` au clic.
-### L.3 â `Detail` affiche le vrai jeu **avec ses likes**
+### L.3 â `Detail` affiche le vrai jeu avec ses likes
```jsx
import { useParams, Link } from "react-router-dom";
function Detail({ jeux, likes }) {
const { id } = useParams();
const jeu = jeux.find((j) => String(j.id) === id);
- if (!jeu) return
Introuvable đ€· â retour
;
+ if (!jeu) return Introuvable â retour
;
return (
â Retour
{jeu.titre}
-
đčïž {jeu.console} â đ
{jeu.annee} â đź {jeu.Type}
+
{jeu.console} â {jeu.annee} â {jeu.Type}
â€ïž Likes : {likes[jeu.id] || 0}
);
}
```
-**â
Test du boss :** ajoute un jeu au formulaire â clique « dĂ©tails » dessus â **il s'affiche** (alors qu'avant il Ă©tait introuvable). Like-le sur l'accueil â son dĂ©tail affiche bien le bon nombre. Recharge la page â les likes sont **toujours lĂ **. đ
+**Test du boss :** ajoute un jeu au formulaire â clique « dĂ©tails » dessus â il s'affiche (alors qu'avant il Ă©tait introuvable). Like-le sur l'accueil â son dĂ©tail affiche le bon nombre. Recharge la page â les likes sont toujours lĂ .
-> đ§ **Ce que tu viens de faire** s'appelle « **lifting state up** » poussĂ© jusqu'au routeur : l'Ă©tat monte au plus petit ancĂȘtre commun (`App`) des composants qui en ont besoin. C'est **le** rĂ©flexe d'archi en React.
+> Ce que tu viens de faire s'appelle « lifting state up » poussĂ© jusqu'au routeur : l'Ă©tat monte au plus petit ancĂȘtre commun (`App`) des composants qui en ont besoin. C'est le rĂ©flexe d'archi central en React.
---
-## đČ Module M â « Au hasard »
+## Module M â Bouton « au hasard »
-Un bouton qui t'envoie sur la fiche d'un jeu **au hasard**. On découvre `useNavigate` (naviguer en JS, pas via un clic sur un ``).
+Un bouton qui t'envoie sur la fiche d'un jeu au hasard. On découvre `useNavigate` (naviguer en JS, pas via un clic sur un ``).
```jsx
import { useNavigate } from "react-router-dom";
-function Accueil({ jeux /* ... */ }) {
- const navigate = useNavigate();
-
- function hasard() {
- const i = Math.floor(Math.random() * jeux.length);
- navigate(`/jeu/${jeux[i].id}`);
- }
- // ...
+const navigate = useNavigate();
+function hasard() {
+ const i = Math.floor(Math.random() * jeux.length);
+ navigate(`/jeu/${jeux[i].id}`);
}
+//
```
-> đ `` = naviguer **au clic** sur un lien. `useNavigate()` = naviguer **depuis du code** (aprĂšs un calcul, un envoi de formulaireâŠ). Deux outils, deux usages.
+> `` = naviguer au clic sur un lien. `useNavigate()` = naviguer depuis du code (aprĂšs un calcul, un envoi de formulaireâŠ).
-**â
Test :** clique đČ plusieurs fois â tu tombes sur des jeux diffĂ©rents.
+**Test :** clique plusieurs fois â tu tombes sur des jeux diffĂ©rents.
---
-## đ Module N â Le Hall of Fame
+## Module N â Le Hall of Fame
-En haut de l'accueil, le **Top 3** des jeux les plus likĂ©s, avec des mĂ©dailles. (Possible **uniquement** parce que les likes sont centralisĂ©s depuis le Module L đ)
+En haut de l'accueil, le Top 3 des jeux les plus likés, avec des médailles. (Possible uniquement parce que les likes sont centralisés depuis le Module L.)
```jsx
const medailles = ["đ„", "đ„", "đ„"];
@@ -131,25 +137,41 @@ const top = [...jeux]
.sort((a, b) => (likes[b.id] || 0) - (likes[a.id] || 0))
.slice(0, 3);
-
-
đ Hall of Fame
- {top.map((j, index) => (
-
{medailles[index]} {j.titre} â {likes[j.id] || 0} â€ïž
- ))}
-
+//
+// {top.map((j, index) => (
+//
{medailles[index]} {j.titre} â {likes[j.id] || 0} â€ïž
+// ))}
+//
```
-> đ `.slice(0, 3)` = « garde les indices 0, 1, 2 ». Le **2á” paramĂštre** de `.map((j, index) => ...)`, c'est la **position** â parfait pour choisir la mĂ©daille.
+> `.slice(0, 3)` garde les indices 0, 1, 2. Le 2á” paramĂštre de `.map((j, index) => ...)`, c'est la position â parfait pour la mĂ©daille.
-**â
Test :** spamme le like sur un jeu â il grimpe en haut du Hall of Fame en direct.
+**Test :** like beaucoup un jeu â il grimpe en haut du Hall of Fame en direct.
---
-## đ Module O â ThĂšme sombre (qui se souvient)
+## Module O â Supprimer un jeu
-Un bouton đ / âïž qui bascule toute la page en sombre **et garde ton choix** aprĂšs un refresh â exactement le rĂ©flexe `localStorage` que tu connais dĂ©jĂ des likes.
+Un bouton « supprimer » sur chaque carte. La clé : l'immutabilité (un nouveau tableau **sans** l'élément).
+
+```jsx
+function supprimer(id) {
+ setJeux(jeux.filter((j) => j.id !== id));
+}
+// sur la Carte :
+// et dans Accueil : onDelete={() => supprimer(jeu.id)}
+```
+
+> `filter` renvoie un **nouveau** tableau contenant tout sauf l'élément visé. On ne touche jamais l'ancien (immutabilité, comme pour l'ajout).
+
+**Test :** clique đïž â la carte disparaĂźt, les autres restent.
+
+---
+
+## Module P â ThĂšme sombre (qui se souvient)
+
+Un bouton qui bascule la page en sombre et garde le choix aprĂšs un refresh â exactement le rĂ©flexe `localStorage` que tu connais des likes.
-### O.1 â L'Ă©tat + la mĂ©moire (dans `App`)
```jsx
const [sombre, setSombre] = useState(
() => localStorage.getItem("theme") === "sombre"
@@ -157,43 +179,157 @@ const [sombre, setSombre] = useState(
useEffect(() => {
localStorage.setItem("theme", sombre ? "sombre" : "clair");
}, [sombre]);
-```
-### O.2 â Une classe pilotĂ©e par le state
-```jsx
-
-
- {/* Header + Routes + Footer */}
-
+//
+//
```
-
-### O.3 â Le CSS (dans `App.css`)
```css
.sombre { background-color: #1a1a2e; color: #eaeaea; }
.sombre .carte { background-color: #16213e; color: #eaeaea; }
```
-> 𧩠Tu fais piloter du **CSS par du state** : `className` change selon `sombre`, le navigateur applique les bonnes rÚgles. C'est comme ça que marchent **tous** les dark modes.
+> Tu fais piloter du CSS par du state : `className` change selon `sombre`, le navigateur applique les bonnes rÚgles. C'est comme ça que marchent tous les dark modes.
-**â
Test :** passe en sombre â recharge (F5) â c'est **toujours** sombre. đ
+**Test :** passe en sombre â recharge (F5) â c'est toujours sombre.
---
-## â
Checklist du dernier jour
-- [ ] L â `fetch` + `jeux` + `likes` remontĂ©s dans `App`, page dĂ©tail complĂšte (ajouts + likes) đ
-- [ ] M â bouton đČ avec `useNavigate`
-- [ ] N â Hall of Fame Top 3 (`sort` + `slice` + `index` du `map`)
-- [ ] O â thĂšme sombre persistant (`localStorage` + classe CSS pilotĂ©e par state)
+## Module Q â Mode Versus
-## đ Si tu finis tout (true endgame)
-- đ **Confetti au like** : une petite animation CSS quand le compteur monte.
-- âïž **Mode Versus** : 2 `