← Retour au cours
Exercice bonus

Planning d'école multi-utilisateur

Construisez un planning hebdomadaire partagé avec Firebase Authentication et la synchronisation en temps réel

2 à 3 heures Intermédiaire Bonus du Jour 2

Ce que vous allez construire

Un écran de planning partagé où plusieurs étudiants d'une même école de commerce consultent et gèrent leur emploi du temps de la semaine. Chacun voit ses propres tâches, mais aussi les disponibilités de ses camarades : la coordination des projets de groupe devient simple.

Notions clés

  • Authentification : qui utilise l'application ? (Firebase Auth)
  • Données multi-utilisateurs : chaque utilisateur a ses propres événements, mais le planning est partagé
  • Synchronisation en temps réel : les modifications apparaissent instantanément chez tous les utilisateurs connectés (Firestore)

Prérequis

  • Avoir terminé les exercices 1 à 4 du TP 2 (projet Next.js qui tourne en local)
  • Un compte Google (pour accéder à la console Firebase)

Cet exercice est facultatif. Il s'adresse aux étudiants qui terminent les travaux pratiques en avance ou qui veulent un défi supplémentaire. Il peut aussi se faire à la maison.

Étape 1 ~20 min

Configurer Firebase

Firebase est la plateforme de Google pour créer des applications sans gérer de serveurs. Elle fournit l'authentification, une base de données en temps réel et l'hébergement, le tout avec une offre gratuite généreuse.

Créer un projet Firebase

  1. Allez sur console.firebase.google.com et connectez-vous avec votre compte Google
  2. Cliquez sur « Create a project » (créer un projet) et nommez-le school-planner
  3. Désactivez Google Analytics (inutile pour cet exercice) et cliquez sur Create
  4. Une fois le projet créé, cliquez sur l'icône Web (</>) pour enregistrer une application web
  5. Nommez-la school-planner-web et cliquez sur Register app (enregistrer l'application)
  6. Copiez l'objet de configuration Firebase : vous en aurez besoin à l'étape suivante

L'objet de configuration ressemble à ceci. Gardez-le sous la main, vous allez bientôt le coller dans votre code :

const firebaseConfig = {
  apiKey: "AIza...",
  authDomain: "school-planner-xxxxx.firebaseapp.com",
  projectId: "school-planner-xxxxx",
  storageBucket: "school-planner-xxxxx.appspot.com",
  messagingSenderId: "123456789",
  appId: "1:123456789:web:abc123"
};

Activer l'authentification

  1. Dans la barre latérale de la console Firebase, allez dans Build → Authentication
  2. Cliquez sur Get Started (commencer)
  3. Activez Email/Password (e-mail et mot de passe) comme fournisseur de connexion
  4. Vous pouvez aussi activer la connexion Google, plus confortable pour l'utilisateur

Activer la base Firestore

  1. Allez dans Build → Firestore Database
  2. Cliquez sur Create database (créer la base)
  3. Sélectionnez Start in test mode (mode test : toutes les lectures et écritures sont autorisées pendant 30 jours, ce qui suffit pour apprendre)
  4. Choisissez la région la plus proche (par exemple europe-west1) et cliquez sur Enable (activer)

Point d'étape : vous avez un projet Firebase avec l'authentification (e-mail et mot de passe) et Firestore activés.

Étape 2 ~15 min

Installer et configurer le SDK Firebase

Installez le SDK JavaScript de Firebase dans votre projet Next.js et créez un fichier de configuration.

Installer le paquet

Dans le terminal de votre projet :

npm install firebase

Créer le fichier de configuration

Demandez à Antigravity de générer la configuration Firebase :

Crée un fichier src/lib/firebase.ts qui :
- initialise Firebase avec ma configuration (ci-dessous)
- exporte l'instance d'authentification (getAuth)
- exporte l'instance de la base Firestore (getFirestore)
- vérifie que Firebase n'est pas initialisé deux fois

Voici ma configuration Firebase :
[collez ici votre objet de configuration]

Le fichier généré doit ressembler à ceci :

import { initializeApp, getApps } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';

const firebaseConfig = {
  apiKey: "your-api-key",
  authDomain: "your-project.firebaseapp.com",
  projectId: "your-project-id",
  storageBucket: "your-project.appspot.com",
  messagingSenderId: "123456789",
  appId: "your-app-id"
};

const app = getApps().length === 0
  ? initializeApp(firebaseConfig)
  : getApps()[0];

export const auth = getAuth(app);
export const db = getFirestore(app);

Remarque : dans une application de production, ces clés iraient dans des variables d'environnement (.env.local). Pour cet exercice, les placer directement dans le fichier est acceptable : les clés d'API Firebase peuvent être exposées dans le code front-end sans danger (elles sont protégées par les règles de sécurité, pas par le secret).

Point d'étape : src/lib/firebase.ts existe et exporte auth et db. Votre projet compile toujours sans erreur.

Étape 3 ~25 min

Construire l'écran de connexion

Créez une page de connexion et d'inscription pour que chaque étudiant puisse créer un compte et se connecter.

Créer la page de connexion

Demandez à Antigravity :

Crée une page de connexion dans src/app/auth/page.tsx avec :
- une bascule entre les modes "Se connecter" et "S'inscrire"
- un champ e-mail (obligatoire)
- un champ mot de passe (obligatoire, 6 caractères minimum)
- un bouton de validation qui appelle Firebase Auth :
  - inscription : createUserWithEmailAndPassword
  - connexion : signInWithEmailAndPassword
- l'affichage des messages d'erreur sous le formulaire si la
  connexion échoue (par exemple "mot de passe incorrect",
  "e-mail déjà utilisé")
- après une connexion réussie, une redirection vers /planning
- en option : un bouton "Se connecter avec Google" qui utilise
  signInWithPopup et GoogleAuthProvider
Utilise Tailwind CSS pour le style.
Importe auth depuis "@/lib/firebase".

Tester la page de connexion

  1. Ouvrez http://localhost:3000/auth
  2. Créez un compte avec n'importe quelle adresse e-mail et n'importe quel mot de passe
  3. Vérifiez dans la console Firebase → Authentication → Users : votre nouvel utilisateur doit apparaître
  4. Déconnectez-vous puis reconnectez-vous pour vérifier que la connexion fonctionne

Astuce : utilisez des adresses de test simples comme alice@school.com et bob@school.com : Firebase ne vérifie pas les adresses e-mail en mode test.

Point d'étape : vous pouvez créer un compte et vous connecter. L'utilisateur apparaît dans la console Firebase Authentication.

Étape 4 ~20 min

Créer le contexte d'authentification

Il vous faut un moyen de savoir quel utilisateur est connecté depuis n'importe quelle page de l'application. C'est le rôle d'un contexte React.

Qu'est-ce qu'un contexte ?

Voyez-le comme une variable globale que n'importe quel composant peut lire. Au lieu de transmettre l'objet utilisateur à la main de page en page, le contexte le rend disponible partout.

Générer le contexte d'authentification

Demandez à Antigravity :

Crée un contexte AuthProvider dans
src/context/AuthContext.tsx qui :
- utilise onAuthStateChanged de Firebase pour suivre
  l'utilisateur actuellement connecté
- fournit : l'objet user, un booléen loading et une
  fonction signOut
- exporte un hook useAuth() pour y accéder facilement
Ensuite, enveloppe l'application dans AuthProvider dans
src/app/layout.tsx (le provider doit être un composant
client avec "use client").
Si loading vaut true, affiche un indicateur de chargement
ou "Chargement..."

Protéger les routes

Demandez à Antigravity de protéger la page de planning :

Dans src/app/planning/page.tsx (ou dans un layout), vérifie
si l'utilisateur est connecté avec le hook useAuth().
S'il ne l'est pas, redirige vers /auth.
S'il l'est, affiche le contenu de la page.

Ajouter un bouton de déconnexion

Ajoutez à la barre de navigation un bouton de déconnexion qui appelle signOut(auth) et redirige vers /auth.

Point d'étape : ouvrir /planning sans être connecté redirige vers /auth. Une fois connecté, vous accédez à la page de planning. Le bouton de déconnexion fonctionne.

Étape 5 ~40 min

Construire l'écran de planning

C'est la fonctionnalité principale : une grille de calendrier hebdomadaire où tous les étudiants d'une école gèrent ensemble leur emploi du temps.

Le modèle de données

Avant de construire l'interface, comprenez comment les données sont organisées dans Firestore :

schools (collection)
  └── my-school (document)
        └── events (sub-collection)
              ├── event1: { userId, userName, title,
              │             day, startHour, endHour,
              │             color, type }
              ├── event2: { ... }
              └── event3: { ... }

Chaque événement appartient à un utilisateur (userId) mais reste visible par toute l'école.

Générer la page de planning

Demandez à Antigravity de construire la vue complète du planning :

Crée une page de planning dans src/app/planning/page.tsx :

MISE EN PAGE :
- une grille de calendrier hebdomadaire du lundi au vendredi
- des créneaux de 8:00 à 18:00 (une ligne par heure)
- chaque cellule représente une heure d'un jour
- une ligne d'en-tête avec le nom des jours

AJOUT D'ÉVÉNEMENTS :
- un clic sur une cellule vide ouvre une fenêtre modale avec :
  - un titre (champ texte)
  - un type (liste : class / study / group-project / free)
  - l'heure de début et l'heure de fin (listes déroulantes)
- à la validation, enregistre dans Firestore :
  chemin de la collection : schools/my-school/events
  champs : userId, userName (issus de auth), title, day,
  startHour, endHour, color (selon le type), type

AFFICHAGE DES ÉVÉNEMENTS :
- les événements apparaissent en blocs colorés sur la grille
- couleur selon le type : violet=class, cyan=study,
  émeraude=group-project, ambre=free
- affiche le titre de l'événement et le nom de l'utilisateur
  sur chaque bloc
- les événements de l'utilisateur courant ont une bordure ou
  une mise en valeur discrète pour les distinguer

DROITS :
- tous les utilisateurs voient tous les événements
- seul le propriétaire d'un événement peut le modifier ou
  le supprimer
- n'affiche les boutons modifier/supprimer que sur les
  événements de l'utilisateur

TEMPS RÉEL :
- utilise onSnapshot de Firestore pour écouter les changements
- quand un autre utilisateur ajoute, modifie ou supprime un
  événement, l'écran se met à jour automatiquement

Utilise Tailwind CSS. Importe db et auth depuis
"@/lib/firebase". Utilise le hook useAuth().

C'est un gros prompt ! Antigravity peut générer le code en plusieurs étapes. Relisez chaque étape avant de passer à la suivante. Si quelque chose ne fonctionne pas, décrivez le problème à Antigravity et demandez-lui de le corriger.

Point d'étape : la grille de la semaine s'affiche correctement. Vous pouvez cliquer sur une cellule, remplir la fenêtre modale et voir l'événement apparaître dans le calendrier. Vérifiez Firestore dans la console : le document de l'événement doit s'y trouver.

Étape 6 ~15 min

Tester à plusieurs utilisateurs

Tout l'intérêt de cet exercice, c'est que plusieurs utilisateurs collaborent sur le même planning. Vérifions que cela fonctionne.

Ouvrir deux sessions

  1. Ouvrez votre application dans Chrome et connectez-vous en tant que alice@school.com
  2. Ouvrez une fenêtre de navigation privée (ou Firefox) et connectez-vous en tant que bob@school.com
  3. Placez les deux fenêtres côte à côte pour les voir en même temps

Tester la synchronisation en temps réel

  1. En tant qu'Alice : ajoutez un événement, « Cours de maths » le lundi de 9:00 à 11:00
  2. Regardez l'écran de Bob : l'événement doit apparaître en 1 à 2 secondes, sans recharger la page
  3. En tant que Bob : ajoutez un événement, « Groupe de travail » le lundi de 14:00 à 16:00
  4. Regardez l'écran d'Alice : l'événement de Bob doit apparaître automatiquement

Tester les droits

  1. En tant que Bob : essayez de modifier ou de supprimer l'événement d'Alice : les boutons modifier/supprimer ne doivent pas être visibles
  2. En tant qu'Alice : modifiez votre propre événement (par exemple son titre) : la modification doit apparaître sur l'écran de Bob
  3. En tant qu'Alice : supprimez votre propre événement : il doit disparaître des deux écrans

Travaillez en binôme ! Si vous êtes à côté d'un camarade, connectez-vous tous les deux à la même école et ajoutez des événements en même temps. C'est la façon la plus amusante de tester la synchronisation en temps réel.

Point d'étape : deux utilisateurs peuvent se connecter, ajouter des événements et voir les mises à jour de l'autre en temps réel. Personne ne peut modifier ou supprimer un événement qui appartient à quelqu'un d'autre.

Synthèse

Idées bonus et synthèse

Défis bonus

S'il vous reste du temps, choisissez l'une de ces améliorations :

  • Choix de l'école : ajoutez une liste déroulante pour passer d'une école à l'autre (chaque école a sa propre sous-collection d'événements). L'application peut ainsi servir à plusieurs classes.
  • Profils utilisateurs : enregistrez les noms affichés et les couleurs d'avatar dans une collection users, pour que les événements de chacun aient une apparence cohérente.
  • Glisser et redimensionner : permettez de faire glisser un événement vers un autre créneau ou de le redimensionner pour changer sa durée.
  • Détection des conflits : mettez en évidence les créneaux où deux étudiants ou plus ont des événements qui se chevauchent, pratique pour caler une réunion de groupe.
  • Export vers un agenda : ajoutez un bouton qui exporte les événements de la semaine dans un fichier .ics, importable dans Google Agenda ou Outlook.

Ce que vous avez appris

Notion À quoi elle sert
Firebase Auth Gère l'inscription, la connexion et les sessions des utilisateurs
Firestore Base de données NoSQL synchronisée en temps réel sur tous les clients
React Context Partage l'état d'authentification entre toutes les pages sans le transmettre de composant en composant (prop drilling)
onSnapshot Écoute les changements en temps réel et met à jour l'interface automatiquement
Autorisation Détermine qui peut modifier ou supprimer une donnée selon son propriétaire

Livrables

Ressources

Vue d'ensemble des étapes