Plan d'enseignement - Cours 141
Vue d'ensemble des 15 séances
| Séance | Date | Thème | Contenu principal |
|---|---|---|---|
| 1 ✓ | 21.01 | Introduction | Environnement, Vue DevTools, Structure projet |
| 2 ✓ | 28.01 | Création projet + Bases | Vuetify, Vue DevTools, ref(), ESLint |
| 3 ✓ | 04.02 | Bases Vue.js + Exercices | Demo Vue.js, Exercices Classroom, Début Infomaniak |
| 4 ✓ | 11.02 | Déploiement Infomaniak/Vercel | Projet individuel, GitHub Actions, FTP, Vercel |
| 5 ✓ | 25.02 | Cycle de vie & Watchers | Tuto 8-10, Exercices 5-7, Présentation lifecycle |
| 6 ✓ | 04.03 | Composants Vue.js | Props, Emits, Slots, Tuto 11-14, Exercices 8-9 |
| 7 ✓ | 11.03 | Vuetify + API | Démo Rick & Morty Explorer, lancement projet perso |
| 8 ✓ | 25.03 | Setup Pokédex + Composants + Routes | fetch API, grille, PokemonCard, pages, navigation |
| 9 ✓ | 01.04 | Pinia (state management) | Créer le store, migrer fetch, storeToRefs |
| 10 ✓ | 22.04 | Axios, .env et robustesse API | fetch → Axios, .env, loading/error |
| 11 ✓ | 29.04 | Recherche, filtre et tri | computed chaînés, filtre type, tri |
| 12 ✓ | 06.05 | Favoris et persistance | toggleFavorite, localStorage, page favoris |
| 13 | 13.05 | Formulaires, auth et suppression | v-form, POST, authStore, guards, DELETE |
| 14 | 20.05 | UX, responsive et finalisation | Thème, responsive, README, déploiement |
| 15 | 27.05 | Rendu projet + Examen oral | Rendu projet, oral 20 min |
Semaines sans cours
- 18 février (vacances)
- 18 mars (vacances)
- 8 avril (vacances de Pâques)
- 15 avril (vacances de Pâques)
Séance 1 - 21 janvier 2026 ✓
Thème : Introduction à Vue.js et Vuetify
Objectifs :
- Mettre en place l'environnement de développement
- Comprendre Vue.js et Vuetify
- Installer Vue DevTools
- Créer sa première application Vue
Contenu couvert :
- Reconnexion WebStorm/GitHub
- Création projet avec
npm create vuetify - Explication npm et npmjs.com (packages)
- Choix TypeScript vs JavaScript (JS pour débutants)
- Lancement serveur avec
npm run dev - Installation et utilisation Vue DevTools (Firefox/Brave)
- Inspection des composants avec DevTools
- Structure projet :
public/vssrc/ - Flux de démarrage : index.html → main.js → App.vue
- Hot Reload (rechargement automatique)
- Modification du template App.vue
Ressources :
Devoirs : Tutoriel Vue.js officiel (étapes 1-7)
Séance 2 - 28 janvier 2026 ✓
Thème : Création projet Vuetify et bases Vue.js
Objectifs :
- Créer un nouveau projet Vuetify
- Comprendre la structure d'un projet Vue.js
- Découvrir les variables réactives et les directives
Devoirs préalables : Tutoriel Vue.js officiel (étapes 1 à 7)
Contenu couvert :
Configuration environnement (15 min)
- Reconnexion WebStorm/GitHub (token)
- Vérification Git et terminal
Création projet Vuetify (30 min)
- Commande
npm create vuetify - Preset "Everything" (toutes les options)
- Choix JavaScript (pas TypeScript pour débutants)
- Installation dépendances avec npm
- Explication npm et npmjs.com
- Commande
Lancement et outils (20 min)
- Lancement serveur
npm run dev - Installation Vue DevTools (Firefox/Brave)
- Inspection des composants
- Lancement serveur
Structure projet Vue.js (30 min)
- Dossier
public/: fichiers statiques (favicon, images) - Dossier
src/: fichiers traités par Vue.js - Flux de démarrage : index.html → main.js → App.vue
- Hot Reload (rechargement automatique)
- Dossier
Bases Vue.js - Pratique (60 min)
- Modification App.vue
- Variables réactives avec
ref() - Interpolation
- Directive
v-model(liaison bidirectionnelle) - Directive
v-bind(liaison d'attributs)
Configuration ESLint (15 min)
- Fichier eslint.config.js
- Activer "Run eslint --fix on save" dans WebStorm
- Formatage automatique du code
Reporté à la séance 3 :
- Publication sur GitHub
- Hébergement Infomaniak
- Correction tutoriel Vue.js (étapes 1-7)
Ressources :
Séance 3 - 4 février 2026 ✓
Thème : Bases de Vue.js et début Infomaniak
Objectifs :
- Approfondir les bases de Vue.js en codant ensemble
- Distribuer les exercices pratiques
- Démarrer la configuration Infomaniak
Devoirs préalables : Relire le tutoriel Vue.js (étapes 1 à 7)
Contenu :
Rappels et démarrage projet (15 min)
- Démarrer le serveur (
npm run devou panneau NPM WebStorm) - Ouvrir la console du navigateur (débogage)
- Vue DevTools pour inspecter les composants
- Démarrer le serveur (
Demo Vue.js - Coder ensemble (90 min)
- Rappel structure composant :
<script>,<template>,<style>→ Anatomie d'une application - Flux de démarrage : index.html → main.js → App.vue
- Variables réactives
ref()et.value - Interpolation
etv-model - Événements
@clicket fonctions - Raccourci clavier
@keyup.enter - Références d'éléments
useTemplateRef()pour le focus - Propriétés calculées
computed()pour filtrer un tableau - Checkbox avec
v-model(booléen) - Débogage : console, messages d'erreur, ligne/caractère
- Rappel structure composant :
Distribution exercices "Bases de Vue.js" (30 min)
- Exercices via GitHub Classroom
- Clonage du dépôt dans WebStorm (File > New > Project from Version Control)
npm install+npm run dev- Exercice 1 réalisé ensemble en classe
- Solutions : kode.ch/vue-bases/
Début configuration Infomaniak (30 min)
- Activation compte étudiant gratuit
- Création hébergement web et nom de domaine
- Création utilisateur FTP
Reporté à la séance 4 :
- Finalisation déploiement Infomaniak (workflow GitHub Actions)
- Introduction SASS/SCSS
Ressources :
- Exercices "Bases de Vue.js"
- Exercices - Solutions
- Déployer sur GitHub Pages
- Déployer sur Infomaniak (FTP)
- Tutoriel Vue.js officiel
- Infomaniak - Programme étudiant
Séance 4 - 11 février 2026 ✓
Thème : Déploiement Infomaniak/Vercel et présentation du projet
Objectifs :
- Finaliser le déploiement automatisé sur Infomaniak
- Déployer l'application sur Vercel
- Présenter le projet individuel
Contenu couvert :
Correction exercices 1 à 4 (30 min)
- Revue des exercices "Bases de Vue.js" en classe
- Correction des exercices 1, 2, 3 et 4 ensemble
Présentation du projet individuel (15 min)
- Projet Vue.js 3 avec Vuetify, Pinia et API externe
- Système d'évaluation (30 pts projet + 50 pts oral)
- Critères d'une bonne API (images, endpoint liste + détail, contenu riche)
- Utilisation de Postman pour tester les APIs
- 👉 Détails du projet
Finalisation déploiement Infomaniak (~2h30)
- Configuration compte FTP (mots de passe sécurisés)
- Secrets GitHub (FTP_USER, FTP_PASSWORD, FTP_SERVER)
- Workflow GitHub Actions pour déploiement automatique via tags/releases
- Staging (GitHub Pages) vs Production (Infomaniak)
- Dépannage individuel (configuration, erreurs de déploiement)
- Importance de l'automatisation pour la sécurité (plus de mots de passe FTP partagés)
Déploiement sur Vercel (30 min)
- Création d'un compte Vercel par les apprentis
- Connexion avec GitHub
- Déploiement automatique de l'application
Reporté à la séance 5 :
- Tutoriel Vue.js étapes 8-10 (cycle de vie, computed, watchers)
- Exercices 5 à 7
Note : Le déploiement Infomaniak a pris beaucoup plus de temps que prévu (dépannage individuel). Pas de devoirs donnés.
Ressources :
Séance 5 - 25 février 2026 ✓
Thème : Cycle de vie & Watchers
Objectifs :
- Comprendre le cycle de vie d'un composant
- Découvrir les watchers (
watch,watchEffect) - Pratiquer avec le tutoriel et les exercices
Devoirs préalables : Terminer exercices 1 à 4 (GitHub Classroom)
Contenu couvert :
Rappel séance 4 (10 min)
- Recap déploiement : CI/CD, GitHub Actions, Infomaniak, Vercel
- Vercel pour les POC (Proof of Concept), test smartphone
- Question technique : cloner un projet sur un autre PC (ne jamais copier un dossier Git)
Présentation théorique - Cycle de vie & Watchers (30 min)
- Cycle de vie : hooks (crochets),
onMounted,onUnmounted - Exemples concrets : appel API avant affichage, confirmation avant perte de données
- Skeleton loaders avec Vuetify (
v-skeleton-loader) - Problématique scroll dans les SPA
- Rappel
computed(): cache intelligent vs fonctions watch()etwatchEffect(): surveiller des données réactives- Bonnes pratiques : computed pour données dérivées, watch pour effets
- Cycle de vie : hooks (crochets),
Tutoriel Vue.js - Étapes 8 à 10 (travail autonome)
- Étape 8 : Cycle de vie (
onMounted,onUnmounted) - Étape 9 : Propriétés calculées (
computed) - Étape 10 : Observateurs (
watch,watchEffect)
- Étape 8 : Cycle de vie (
Exercices "Bases de Vue.js" 5 à 7 (travail autonome)
- Exercice 5 : Computed
- Exercice 6 : Watch
- Exercice 7 : WatchEffect
Devoirs pour la séance 6 :
- Terminer tout le tutoriel Vue.js officiel (étapes 1 à 15)
- Terminer les exercices "Bases de Vue.js" 1 à 7
Ressources :
Séance 6 - 4 mars 2026 ✓
Thème : Composants Vue.js — Props, Emits & Slots
Objectifs :
- Comprendre le découpage en composants
- Passer des données avec les props (
defineProps) - Communiquer via les événements (
defineEmits) - Injecter du contenu avec les slots
Devoirs préalables :
- Terminer tout le tutoriel Vue.js officiel (étapes 1 à 15)
- Terminer les exercices "Bases de Vue.js" 1 à 7
Contenu couvert :
Présentation théorique - Composants (~1h15)
- Introduction aux composants : découpage, import, réutilisation
- Lien avec le vibe coding (composants = meilleure testabilité avec l'IA)
- Démo interactive sur le Playground Vue.js :
- Créer un composant enfant et l'importer
- PascalCase vs kebab-case pour les balises
scopedCSS : portée limitée au composant
- Props :
defineProps(), passage statique vs dynamique (:) - Props en lecture seule, validation avec
v-if - Emits :
defineEmits(), communication enfant → parent - Slots : injection de contenu HTML (défaut, nommés, valeur par défaut)
- Exemple concret avec les slots Vuetify (
v-card,v-text-field)
Choix des API pour le projet personnel
- Validation des API choisies par les apprentis
- Vérification : gratuite, publique, avec images
Travail autonome (~1h30)
- Tutoriel Vue.js étapes 11-14 (composants)
- Exercices "Bases de Vue.js" 8 et 9
- Finalisation du choix d'API
Ressources :
Séance 7 - 11 mars 2026 ✓
Thème : Vuetify + API — Rick & Morty Explorer
Voir la démo en ligne | Dépôt GitHub
Objectifs :
- Consommer une API REST et afficher des données dans Vuetify
- Découvrir les composants Vuetify (
v-card,v-img,v-chip,v-list) - Comprendre le routage Vue Router (2 pages, navigation drawer)
Devoirs préalables :
- Terminer le tutoriel Vue.js (étapes 1 à 15)
- Terminer les exercices "Bases de Vue.js" 1 à 9
Récupérer le projet Rick & Morty Explorer
Étape 1 — Créer votre copie du projet
- Ouvrir le dépôt template : github.com/fallinov/esig-141-demo-vuetify-api
- Cliquer sur le bouton vert "Use this template" → "Create a new repository"

- Cocher "Include all branches" (pour avoir la branche
solution) - Repository name :
esig-141-demo-vuetify-api - Visibilité : Public
- Cliquer sur "Create repository"

Étape 2 — Cloner et ouvrir dans WebStorm
- Copier l'URL de votre dépôt :
https://github.com/VOTRE-PSEUDO/esig-141-demo-vuetify-api.git

- Dans WebStorm : File → New → Project from Version Control...
- Coller l'URL et cliquer sur Clone
- Ouvrir le terminal intégré et lancer :
npm install
npm run dev- L'application s'ouvre sur http://localhost:3000
Contenu
P1-P2 : Démo collective — Rick & Morty Explorer (~1h30)
- Suivre le guide étape par étape (étapes 0 à 5, + bonus étape 6)
- Appel API avec
fetch()dansonMounted— Les 3 états d'un appel API : loading, error, data - Affichage dans des
v-cardavecv-img,v-chipet grille responsive - Page statique À propos avec
v-card,v-list,v-icon - Navigation :
v-navigation-draweravec hamburger etv-list-item :to→ Vue Router - Déploiement sur Vercel
P3-P4 : Mise en pratique individuelle (~1h30)
- Créer un projet Vuetify : devjs.ch/vue/creer-app-vuetify (
npm create vuetify, preset Recommended) - Créer un dépôt GitHub et pousser le projet
- Rédaction du README (nom, API, description)
- Test de l'API avec Bruno ou Postman
- Reproduction de la démo avec leur propre API
- Déploiement sur Vercel
- Suivre la checklist du projet personnel en bas du guide
- Créer un projet Vuetify : devjs.ch/vue/creer-app-vuetify (
Objectif de fin de séance : chaque apprenti a une app Vuetify qui affiche les données brutes de son API.
Ressources :
- Guide étape par étape — Rick & Morty Explorer
- Dépôt GitHub du projet (branche
main= code de départ, branchesolution= résultat final) - Créer un projet Vuetify
- Projet individuel C141
- Introduction à Vue et Vuetify
- Anatomie d'un projet Vuetify
- API — Introduction
- API — Utilisation en projet
- Vue Router — Introduction
Progression pédagogique
À partir de cette séance, chaque nouveau concept est d'abord appris via le Pokédex (exercice guidé) puis transposé dans le projet personnel (application autonome). La progression technique suit le même chemin dans les deux projets : fetch() brut → Pinia → Axios.
Séance 8 - 25 mars 2026 ✓
Thème : Setup Pokédex + Composants + Routes
Objectifs :
- Mettre en place le projet Pokédex et consommer l'API avec
fetch() - Découper l'interface en composants réutilisables (
defineProps,defineEmits, slots) - Créer les pages et la navigation avec le file-based routing
Devoirs préalables : Projet personnel initialisé avec fetch() fonctionnel et liste affichée
Contenu :
P1 : Setup Pokédex + fetch API (~45 min)
- Suivre E1 — Fetch API + grille
- Cloner le squelette Pokédex,
npm install,npm run dev - Démarrer le serveur API local (Pokédex API)
- Anatomie du projet Vuetify (dossiers, fichiers clés, plugins auto-import)
- Layout :
v-app,v-app-bar,v-main,v-footer - Appel API avec
fetch()dansonMounted— Introduction aux API - Grille responsive :
v-container,v-row,v-col+v-cardavecv-for
P2 : Composants réutilisables (~45 min)
- Suivre E2 — Composants (props, slots)
- Extraire
PokemonCard.vuedepuis la grille (defineProps) - Créer
AppFooter.vueavec un slot - defineEmits — communication enfant → parent (optionnel, montrer le concept)
Encart oral — Props vs Emits
Props = le parent envoie des données à l'enfant (sens unique, lecture seule). Emits = l'enfant notifie le parent qu'un événement s'est produit. Analogie : les props sont un courrier recommandé (parent → enfant), les emits sont un accusé de réception (enfant → parent).
P3 : Pages et navigation (~45 min)
- Suivre E3 — Pages et navigation + E4 — Page détail
- File-based routing : créer un fichier dans
src/pages/= créer une route - Créer les pages :
favoris.vue,a-propos.vue,pokemon/[id].vue - Compléter
AppHeader: menu avecv-btn :to+ icônes MDI - Rendre
PokemonCardcliquable → navigation vers/pokemon/:id - Page détail basique :
useRoute().params.id, afficher un Pokémon - Bouton retour avec
router.push('/')
P4 : Transposition projet personnel (~45 min)
- Suivre E5 — Récap + projet perso
- Extraire son
ItemCard.vue(ou équivalent) avecdefineProps - Créer ses pages (liste, détail, favoris)
- Navigation adaptée à son projet
- Premier commit avec message clair
Checklist projet perso :
- ≥ 3 composants avec props typées
- ≥ 3 pages avec navigation fonctionnelle
- Route dynamique
/item/:idavec page détail - Commit poussé sur GitHub
Ressources :
Séance 9 - 1er avril 2026 ✓
Thème : Pinia — Centraliser les données
Objectifs :
- Comprendre le problème du prop drilling et le rôle d'un store
- Créer un store Pinia from scratch (state, getters, actions)
- Utiliser
storeToRefs()pour destructurer sans perdre la réactivité
Devoirs préalables : Pokédex avec composants et pages fonctionnels (résultat séance 8)
Point de départ — Branche etape-6-start
Si votre Pokédex n'est pas à jour, vous pouvez repartir de la branche etape-6-start qui contient le code solution des étapes 1 à 5 :
# Ajouter le dépôt du prof (une seule fois)
git remote add prof https://github.com/fallinov/esig-141-pokedex-vuetify.git
# Récupérer les branches et basculer
git fetch prof
git checkout -b etape-6-start prof/etape-6-start
npm installContenu couvert :
Rappels et mise à jour (15 min)
- Quelques absents en début de cours
- Installation outil de gestion de classe (Leptis) — code d'activation distribué
- Rappel de l'état attendu : Pokédex avec 3 pages (accueil, favoris, à propos), file-based routing, route dynamique
[id].vue, bouton retour - Rappel : démarrer l'API locale (
npm run devdans pokedex-api, port 3535) avant le projet
P1 : Git — Ajouter le remote du prof (15 min)
- Explication : on peut avoir plusieurs origines (remotes) sur un dépôt Git
- Commande :
git remote add prof https://github.com/fallinov/esig-141-pokedex-vuetify.git - Puis
git fetch profpour récupérer toutes les branches git checkout -b etape-6-start prof/etape-6-startpour repartir du bon pied- Vérification dans WebStorm : Remote → origin + prof visibles
- Utile pour les absents ou ceux en retard : chaque leçon a sa branche de départ
P1 : Théorie Pinia au tableau (~30 min)
- Pourquoi un store ? : chaque composant fait son propre
fetch()→ duplication, incohérence - Schéma au tableau : avant (chaque page → API) vs après (pages → magasin → API)
- Analogie du restaurant : le serveur (store) prend les commandes de tout le monde, pas le téléphone arabe entre convives
- Analogie de l'escape room : le maître du jeu connaît tout, chaque joueur n'a qu'une partie de l'info
- Quand utiliser Pinia : dès que 2+ pages partagent les mêmes données, ou dès qu'il y a du prop drilling sur 2+ niveaux
- Anatomie d'un store — 3 parties :
- Règle : toujours initialiser le state avec des valeurs par défaut (tableau vide, false, null)
- Les getters ne modifient jamais les données, ils les retournent sous un autre format
- Pourquoi un store ? : chaque composant fait son propre
P1-P2 : Live coding — Créer
pokemonStore.js(~45 min)- Créer
src/stores/pokemonStore.js— Click droit → New → JavaScript file import { defineStore } from 'pinia'defineStore('pokemon', { state, getters, actions })- State :
pokemons: [],types: [],isLoading: true,error: null - Getter
totalPokemons:(state) => state.pokemons.length— rappel syntaxe arrow function (raccourci sans accolades ni return) - Getter
getPokemonById: utilisestate.pokemons.find()— retourne une fonction - Action
fetchPokemons:async,await fetch(...), testresponse.ok,throw new Error,this.pokemons = await response.json()— rappelthispour accéder au state dans les actions - Action
fetchTypes: copier-coller de fetchPokemons, adapter URL et state cible - Action
init:try/catch/finally,this.isLoading = true,await Promise.all([this.fetchPokemons(), this.fetchTypes()]), finallythis.isLoading = false - Explication
Promise.all: lance les 2 requêtes en parallèle, attend que les 2 aient répondu (plus efficace que 2 await séquentiels) - Digression : IDs modernes sont des UUID (pas des séquences 1, 2, 3 comme en Oracle), générés par algorithme, quasi-uniques
- Commit sur branche étape-6
- Créer
P2 : Live coding — Connecter le store (~30 min)
- App.vue : import
usePokemonStore,const pokemonStore = usePokemonStore(),onMounted(() => pokemonStore.init()) - Vérification dans Vue DevTools → onglet Pinia : le magasin Pokémon apparaît avec toutes les données
- index.vue : supprimer l'ancien
fetch()local, remplacer par le store - Démo sans
storeToRefs: destructuration classiqueconst { pokemons } = usePokemonStore()→ ça affiche les pokémons mais perd la réactivité → supprimer un pokémon dans DevTools → l'UI ne change pas - Démo avec
storeToRefs:const { pokemons } = storeToRefs(usePokemonStore())→ supprimer/modifier un pokémon dans DevTools → l'UI se met à jour instantanément - Explication de la destructuration JS (
const { pokemons } = objest un raccourci pourconst pokemons = obj.pokemons) - Aperçu localStorage pour les favoris (séance 12)
- Commit
- App.vue : import
P3-P4 : Travail autonome (~1h30)
- Les élèves ont choisi de faire le début ensemble plutôt que seuls
- E6 — Créer le store Pokémon : refaire le store
- E7 — Connecter les pages au store : migration,
storeToRefs - E8 — Transposition projet perso : créer son propre store
- Aide individuelle
Observations :
- La majorité des élèves étaient à jour avec l'exercice et le projet perso
- Le live coding collectif a pris plus de temps que prévu (P1 entière + début P2)
- Les élèves ont voté pour faire ensemble plutôt que seuls
- Le concept de
storeToRefsa bien fonctionné grâce à la démo avant/après dans DevTools
Checklist projet perso :
- Store Pinia créé avec state, ≥ 1 getter, ≥ 1 action
-
storeToRefs()utilisé dans les composants -
fetch()migré du composant vers le store - Pages connectées au store
- Commit poussé sur GitHub
Ressources :
- Pinia — Introduction
- Pinia — Créer un store
- Pinia — State
- Pinia — Getters
- Pinia — Actions
- E6 — Créer le store Pokémon
- E7 — Connecter les pages au store
- E8 — Transposition projet perso
- Documentation officielle Pinia
Séance 10 - 22 avril 2026 ✓
Thème : Axios, variables d'environnement et robustesse API
Objectifs :
- Comprendre les limites de
fetch()brut et l'intérêt d'Axios - Configurer une instance Axios avec
axios.create() - Utiliser les variables d'environnement (
.env,VITE_API_URL) - Gérer les 3 états d'un appel API (loading, error, data)
Devoirs préalables : Store Pinia fonctionnel avec fetch()
Point de départ — Branche etape-9-start
Si votre Pokédex n'est pas à jour, vous pouvez repartir de la branche etape-9-start qui contient le code solution des étapes précédentes :
# Ajouter le dépôt du prof (une seule fois)
git remote add prof https://github.com/fallinov/esig-141-pokedex-vuetify.git
# Récupérer les branches et basculer
git fetch prof
git checkout -b etape-9-start prof/etape-9-start
npm installContenu couvert :
P1 : Migration fetch → Axios (~30 min)
- Live coding : remplacement de
fetch()parapi.get()dans le store - Configuration de l'instance Axios avec
axios.create()+ variableVITE_API_URL
- Live coding : remplacement de
P2 : Gestion des images manquantes avec
v-img(~15 min)- Question d'élève : que faire quand les images ne chargent pas ?
- Découverte dans la doc Vuetify :
v-slot:erroretv-slot:placeholdersurv-img - Live coding : ajout d'un
<template #error>dans PokemonCard avec une image par défaut
P3 : Travail autonome (~45 min)
- Les élèves migrent leur store de
fetch()vers Axios sur leur projet perso - Aide individuelle (debugging Axios, structure du store)
- Les élèves migrent leur store de
P4 : Démo Vercel (~20 min)
- Vercel vs GitHub Pages vs Infomaniak : Vercel analyse l'app automatiquement, pas de config
- Visualisation des branches déployées sur Vercel
- Erreur de build : un fichier non commité causait une erreur → toujours faire
npm run builden local avant de pousser
Reporté à la séance 11 :
Observations :
- Axios et
.envétaient déjà configurés par certains élèves depuis la séance 9 - Vercel a pris du temps (debugging individuel)
Checklist projet perso :
- Axios installé et configuré avec
axios.create() -
.envavecVITE_API_URL+.env.example -
.envdans.gitignore -
fetch()remplacé paraxios.get()dans le store - Commit poussé sur GitHub
Ressources :
- Axios — Client HTTP
- API — Bonnes pratiques
- API — Utilisation en projet
- Exercice Pokédex Vuetify
- Pokédex API
Séance 11 - 29 avril 2026 ✓
Thème : Recherche, filtre et tri
Note historique — édition 2025-2026
P1 (mock local + Vercel) fait en démo collective. Pour P2 et P3, les apprentis ont préféré travailler en autonomie sans démo collective afin de transposer plus rapidement dans leur projet personnel.
Bugs Vercel découverts pendant le cours et documentés le jour même : voir Déployer sur Vercel (VITE_BASE_URL + vercel.json).
Le mock local a été retiré du cours suite à cette séance — concept dispensable, charge cognitive trop élevée.
Objectifs :
- Utiliser
computed()pour filtrer et trier sans modifier les données source - Chaîner les computed (recherche → filtre → tri)
- Implémenter un filtre par catégorie/type
Devoirs préalables : Axios configuré, fetch() migré vers Axios dans le store
Point de départ — Branche etape-12-start
Si votre Pokédex n'est pas à jour, vous pouvez repartir de la branche etape-12-start qui contient le code solution des étapes précédentes :
# Ajouter le dépôt du prof (une seule fois)
git remote add prof https://github.com/fallinov/esig-141-pokedex-vuetify.git
# Récupérer les branches et basculer
git fetch prof
git checkout -b etape-12-start prof/etape-12-start
npm installContenu :
P1 : Loading/erreurs + Vercel (~45 min)
- Revue de code E10 (~10 min) — déjà intégré dans
etape-12-start, pas de live coding- Ouvrir
src/plugins/axios.js,src/pages/index.vueavec les apprentis - Repérer
v-skeleton-loader(loading) +v-alert(erreur) - Les 3 états d'un appel API : loading, error, data
- Ouvrir
- Démo Vercel (~35 min)
- Push sur GitHub → Vercel redéploie automatiquement
- Variables d'environnement sur Vercel : Settings → Environment Variables →
VITE_API_URLavec l'URL de l'API - Pièges fréquents : voir Déployer sur Vercel (
VITE_BASE_URL,vercel.jsonrewrite SPA) - Les apprentis vérifient que leur projet est bien déployé sur Vercel
- Revue de code E10 (~10 min) — déjà intégré dans
P2 : Pokédex — Recherche (~45 min, travail autonome)
- Suivre E12 — Recherche par nom
computed(): filtre les données sans les modifier (données source intactes)v-modelsurv-text-fieldpour la recherche en temps réelArray.filter()+String.includes()+toLowerCase()- Pokédex : recherche par nom de Pokémon
v-alert"Aucun résultat trouvé" si la liste filtrée est vide
P3 : Pokédex — Filtre par type et tri (~45 min, travail autonome)
- Suivre E13 — Filtre par type + tri
- Filtre par type :
v-selectavec les types disponibles - Utiliser
pokemonStore.typescomme source duv-select - Chaîner les computed : filtre type → recherche → tri
- Tri alphabétique / numérique :
Array.sort(),localeCompare() v-btnavectoggleSort()pour inverser l'ordre de tri
P4 : Transposition projet personnel (~45 min)
- Suivre E14 — Récap + projet perso
- Recherche par texte (nom, titre, etc.)
- Filtre par catégorie/type propre à son API
- Tri pertinent pour ses données (alphabétique, date, note, etc.)
- Commit
Checklist projet perso :
- Recherche par texte fonctionnelle
- Filtre par catégorie/type avec
v-select - Tri (au moins 2 options)
- Message "Aucun résultat" si liste vide
- Commit poussé sur GitHub
Pièges connus / à anticiper :
sort()mute : sans[...arr].sort(), le tableau d'origine est modifié → recherche cassée la fois suivante.includes()casse : oublier.toLowerCase()des deux côtés (query ET nom).v-selecttypes vide : sipokemonStore.typesn'est pas encore chargé, le select est vide — vérifier queinit()charge les types avant d'autoriser le filtre.- Vercel cache : modif
.envVercel → forcer le redéploiement (Settings → Deploy → Redeploy). - Où initialiser le store ? Question fréquente : l'appel
init()se fait dansApp.vue(une seule fois au démarrage), pas dans chaque page. Si l'appel est dans une page, les données sont perdues à chaque navigation.
Ressources :
Séance 12 - 6 mai 2026 ✓
Thème : Favoris et persistance
Note historique — édition 2025-2026
P1 + P2 faits en démo collective. localStorage démontré en live (ouverture/fermeture navigateur, onglet Stockage DevTools), JSON.stringify/parse expliqué. .stop.prevent expliqué avec la métaphore du bubbling. Transition projet personnel en P3-P4 — ambiance positive.
Objectifs :
- Implémenter un système de favoris avec toggle
- Persister les données avec
localStorage - Créer une page dédiée aux favoris
Devoirs préalables : Recherche, filtre et tri fonctionnels
Point de départ — Branche etape-15-start
Si votre Pokédex n'est pas à jour, vous pouvez repartir de la branche etape-15-start qui contient le code solution des étapes précédentes :
# Ajouter le dépôt du prof (une seule fois)
git remote add prof https://github.com/fallinov/esig-141-pokedex-vuetify.git
# Récupérer les branches et basculer
git fetch prof
git checkout -b etape-15-start prof/etape-15-start
npm installContenu :
- P1 : Théorie + Pokédex — Favoris dans le store (~45 min)
- Suivre E15 — Favoris dans le store
localStorage:setItem,getItem,removeItem,JSON.parse/stringify- Pattern toggle : ajouter si absent, retirer si présent
- Pokédex : ajouter au store
pokemonStore:- State :
favorites(tableau d'IDs) - Action :
toggleFavorite(pokemon)— ajoute/retire l'ID + sauvegarde localStorage - Getter :
isFavorite(pokemon)— retourne true/false - Getter :
getFavorites— retourne les objets Pokémon complets des favoris - Actions :
loadFavorites()/saveFavorites()— lecture/écriture localStorage
- State :
Encart oral — localStorage
localStorage stocke des chaînes de caractères uniquement. Pour stocker un tableau ou un objet : JSON.stringify() à l'écriture, JSON.parse() à la lecture. Les données persistent même après fermeture du navigateur (contrairement à sessionStorage).
P2 : Pokédex — UI favoris (~45 min)
- Suivre E16 — Interface favoris
- Icône cœur conditionnelle sur
PokemonCard(mdi-heart/mdi-heart-outline) @click.stop.preventsur l'icône :.stopstoppe la propagation versv-card,.preventempêche lerouter-linksous-jacent- Créer la page
favoris.vue: réutiliserPokemonCardavecgetFavorites v-alert"Pas encore de favoris" si la liste est vide + bouton vers l'accueil- Correction collective
P3-P4 : Transposition projet personnel (~1h30)
- Suivre E17 — Récap + projet perso
- Ajouter les favoris dans son store (state, actions, getters)
- Icône toggle sur sa carte
- Page ou section dédiée aux favoris
- Tester : ajouter des favoris, recharger la page → ils persistent
- Commit
Checklist projet perso :
-
toggleFavorite()dans le store - Icône conditionnelle sur la carte (favori oui/non)
- Page favoris fonctionnelle
- Favoris persistants après rechargement (localStorage)
- Commit poussé sur GitHub
Pièges connus / à anticiper :
JSON.parse(null): si la clé n'existe pas encore en localStorage,getItem()retournenull→JSON.parse(null)retournenull. Initialiser avec|| [].- Oublier
JSON.stringify: stocker un tableau sans sérialisation →"[object Object]"en localStorage, silencieux et difficile à déboguer. - Comparer les IDs, pas les objets :
isFavoritedoit fairefavorites.includes(pokemon.id), pasfavorites.includes(pokemon). @click.stop.prevent(les deux) :.stopstoppe la propagation versv-card,.preventempêche le comportement par défaut durouter-linksous-jacent. L'un sans l'autre ne suffit pas.- Ordre dans
init():loadFavorites()doit être appelé aprèsfetchPokemons()pour quegetFavoritespuisse croiser les IDs avec les objets chargés.
Ressources :
Séance 13 - 13 mai 2026
Thème : Formulaires, authentification et suppression
🎯 Kahoot révision mi-parcours en fin de séance — ne pas oublier ! (ref/reactive, computed, Pinia, .env, Vue Router, props/emits)
Objectifs :
- Créer un formulaire avec validation (
v-form,:rules) - Envoyer des données à l'API (POST, DELETE avec Axios)
- Comprendre l'authentification et la protection de routes (démo)
- 🎯 Kahoot révision mi-parcours (15 min)
Concepts avancés — Démo uniquement
Les formulaires, l'authentification et la suppression sont présentés pour compléter la culture technique et préparer l'oral. Ils ne sont pas requis dans le projet personnel.
Devoirs préalables : Favoris fonctionnels avec persistance
Point de départ — Branche etape-18-start
Si votre Pokédex n'est pas à jour, vous pouvez repartir de la branche etape-18-start qui contient le code solution des étapes précédentes :
# Ajouter le dépôt du prof (une seule fois)
git remote add prof https://github.com/fallinov/esig-141-pokedex-vuetify.git
# Récupérer les branches et basculer
git fetch prof
git checkout -b etape-18-start prof/etape-18-start
npm installContenu :
P1 : Pokédex — Formulaire d'ajout (~45 min)
- Suivre E18 — Formulaire d'ajout
v-formavec@submit.prevent- Champs :
v-text-field,v-textarea,v-select,v-checkbox - Validation avec
:rules(champ requis, longueur min/max, format) - Action
addPokemon(data)dans le store →axios.post() v-snackbarde confirmation après ajout réussi- Redirection vers l'accueil avec
router.push('/')
P2 : Pokédex — Authentification (~45 min)
- Suivre E19 — Authentification + guards
- Créer
stores/authStore.js(login/logout simulé,isAuthenticated) - Page login : formulaire email + mot de passe avec validation
- Protection de routes :
router.beforeEach()— guard de navigation (section 5 de la doc) - Affichage conditionnel dans le menu (
v-ifsurisAuthenticated)
Encart oral — Guards de navigation
Un guard est comme un videur : il vérifie une condition avant de laisser entrer sur une page. router.beforeEach((to) => { ... }) s'exécute avant chaque navigation. Si la condition échoue, on redirige vers /login.
P3 : Pokédex — Suppression (~45 min)
- Suivre E20 — Suppression
- Bouton supprimer visible uniquement si connecté (
v-if="authStore.isAuthenticated") v-dialogde confirmation avant suppression- Action
deletePokemon(id)dans le store →axios.delete() v-snackbarde confirmation + retour à l'accueil- Correction collective
P4 : Projet personnel — Avancement libre (~45 min)
- Avancer le projet (rattrapage, polish, fonctionnalités manquantes)
- Aide individuelle
🎯 Kahoot révision mi-parcours (15 min en fin de séance) : ref vs reactive, computed, Pinia, .env, Vue Router, props/emits
Ressources :
Séance 14 - 20 mai 2026
Thème : UX, responsive et finalisation du projet
Objectifs :
- Rendre l'application responsive et professionnelle
- Personnaliser le thème Vuetify
- Finaliser le projet personnel (README, déploiement, polish)
Devoirs préalables : Projet personnel avec toutes les fonctionnalités de base (liste, détail, recherche, filtre, tri, favoris)
Point de départ — Branche etape-22-start
Si votre Pokédex n'est pas à jour, vous pouvez repartir de la branche etape-22-start qui contient le code solution des étapes précédentes :
# Ajouter le dépôt du prof (une seule fois)
git remote add prof https://github.com/fallinov/esig-141-pokedex-vuetify.git
# Récupérer les branches et basculer
git fetch prof
git checkout -b etape-22-start prof/etape-22-start
npm installContenu :
P1 : Pokédex — Responsive et thème (~45 min)
- Suivre E22 — Navigation responsive + E23 — Thème + détail enrichi
- Navigation drawer responsive :
v-navigation-drawer+ hamburger sur mobile - Breakpoints Vuetify (
xs,sm,md,lg,xl) etv-coladaptatif - Personnalisation du thème dans
plugins/vuetify.js(couleurs primary, secondary) - Page détail enrichie : chips de types colorés, barres de stats, grande image
- Favicon + titre personnalisés dans
index.html
P2 : Démo — Transformer une web app en application mobile (~45 min)
- Introduction : native vs hybride vs PWA
- Démo live PWA : transformer le Pokédex en application installable
- Ajouter
vite-plugin-pwa(5 min de config) - Configurer le manifest (nom, icônes, couleurs)
- Builder et tester : installer l'app depuis le navigateur sur mobile
- Ajouter
- Résultat : l'app s'installe comme une vraie application, fonctionne hors ligne
- Alternative mentionnée : Capacitor (Ionic) pour un vrai APK Android/iOS
Pas requis dans le projet personnel
La PWA est une démonstration pour montrer les possibilités. Ce n'est pas évalué dans le projet personnel, mais c'est un plus si vous le faites.
- P3-P4 : Finalisation projet personnel (~1h30)
- Design personnel : couleurs, typographie, icônes
- Navigation responsive (drawer ou menu adaptatif)
- Feedback UX : loading, erreurs, snackbar
- README.md complet : description, installation, API, captures d'écran
- Vérifier
.env.example,.gitignore - Déploiement sur Vercel ou GitHub Pages
- Tester sur mobile (responsive)
- 0 erreurs console
- Dernier commit + push
🎯 Kahoot préparation oral (15 min en fin de séance) : questions types de l'examen oral
Checklist finale projet perso :
- Application déployée et fonctionnelle (URL en ligne)
- Page d'accueil avec liste/grille
- Page de détail avec route dynamique
:id - Navigation fonctionnelle (header ou drawer)
- Recherche par texte
- Filtre par catégorie/type
- Tri (au moins 2 options)
- Système de favoris persistants (localStorage)
- Feedback utilisateur (snackbar, loading, erreurs)
- Design responsive (testé mobile + desktop)
- Store Pinia (state, getters, actions)
- Axios configuré avec
.env -
.env.exampleprésent (sans secrets) - README.md complet avec captures d'écran
- Commits réguliers avec messages clairs
- 0 erreurs dans la console
Ressources :
Séance 15 - 27 mai 2026
Rendu du projet + Examen oral
Rendu du projet :
- Application en ligne (Vercel ou GitHub Pages)
- Dépôt GitHub propre et structuré
- README.md complet
Préparation orale (début de séance) :
- Relire son code (comprendre chaque fonction)
- Préparer la démo (2-3 min, parcours utilisateur)
- Lister les améliorations possibles
- Simulation d'oral en binôme
Examen oral (3 juin après-midi) :
- Démo de l'application : 2-3 min
- Présentation des améliorations possibles
- Questions théoriques : 3 questions × 6 pts = 18 pts
- Questions pratiques (sur le code) : 3 questions × 9 pts = 27 pts
- Durée : ~20 min par candidat
Ressources :
Récapitulatif des compétences
| Compétence | Séances |
|---|---|
| Vue.js 3 — Composition API | 1-6 |
| Composants (props, emits, slots) | 6, 8 |
| Déploiement (GitHub Pages, Infomaniak, Vercel) | 4, 7, 14 |
| Vuetify — Material Design | 7-14 |
| File-based routing (Vue Router) | 8-14 |
| Appel API (fetch) | 7-9 |
| Pinia — State management | 9-14 |
| Appel API (Axios, .env) | 10-14 |
| Recherche, filtre, tri (computed) | 11-14 |
| Favoris et persistance (localStorage) | 12-14 |
| Formulaires et validation | 13 |
| Authentification et guards | 13 |
| CRUD complet (POST, DELETE) | 13 |
| UX, responsive, theming | 14 |
| PWA — App mobile (démo) | 14 |
| Projet personnel (API externe) | 7-15 |