Aller au contenu principal

Afficher les réponses

Afficher les réponses possibles d'une question à choix multiples.

00_afficher_reponses.png


Notions théoriques

Les composants interactifs

info

Un composant interactif est un composant sur lequel l'utilisateur peut cliquer, écrire, faire une action... et le composant va réagir.

Dans notre projet, nous voulons que l'utilisateur puisse cliquer sur une réponse.

Pour cela, nous allons utiliser :

  • des composants visuels (comme les boutons de ShadCN/UI),
  • et des fonctions JavaScript qui se déclenchent au clic.

Les événements en React

Un événement est une action faite par l'utilisateur : un clic, une touche pressée, un mouvement de souris, etc.

En React, on utilise souvent l’événement onClick.

Exemple :

<button onClick={() => alert("Vous avez cliqué !")}>
Cliquez ici
</button>

Ici, au clic, une alerte s’affiche.


Afficher une liste

Afficher une liste de réponses cliquables

Nous avons déjà une question avec plusieurs réponses possibles. Ces réponses sont stockées dans un tableau.

Exemple :

const question = {
texte: "Quel est le mot de passe le plus sécurisé ?",
reponses: [
"123456",
"azerty",
"Une phrase longue avec des caractères spéciaux"
],
};

Pour afficher chaque réponse dans un bouton cliquable, on utilise .map() :

{question.reponses.map((reponse, index) => (
<button key={index} onClick={() => handleClick(reponse)}>
{reponse}
</button>
))}

Afficher un bouton

Utiliser un composant pour les boutons

ShadCN propose un composant Button très pratique.

Pour l’installer :

npx shadcn@latest add button

Ensuite, on peut remplacer les <button> classiques par :

<Button onClick={() => handleClick(reponse)}>
{reponse}
</Button>

Exemple pratique

Afficher des réponses cliquables

Voici un exemple complet d'affichage d'une question avec ses réponses cliquables :

import { Button } from "@/components/ui/button";

const question = {
texte: "Quel est le mot de passe le plus sécurisé ?",
reponses: [
"123456",
"azerty",
"Une phrase longue avec des caractères spéciaux",
],
};

function handleClick(reponse: string) {
console.log("Vous avez choisi :", reponse);
}

return (
<div>
<h2>{question.texte}</h2>
{question.reponses.map((reponse, index) => (
<Button key={index} onClick={() => handleClick(reponse)} className="mt-2 block">
{reponse}
</Button>
))}
</div>
);

Décryptage du code

code_exemple_afficher_reponses.png

code_exemple_afficher_reponses_2.png


Quelques méthodes à connaître

MéthodeDescription
console.log()Affiche une information dans la console
.map()Parcourt un tableau et retourne un nouvel élément JSX pour chaque élément
Button (ShadCN)Composant stylisé pour les boutons
key={index}Permet à React d’identifier chaque élément de liste
onClick={() => ...}Déclenche une action lorsque l'utilisateur clique

Test de mémorisation / compréhension


Quelle méthode permet d’afficher plusieurs boutons à partir d’un tableau ?


Quel événement est utilisé pour détecter un clic ?


Pourquoi faut-il une `key` dans une boucle `.map()` ?


Quelle commande permet d’ajouter le composant `Button` de ShadCN ?


Que fait `console.log(reponse)` dans une fonction `handleClick` ?



TP pour réfléchir et résoudre des problèmes

Afficher les réponses d’une question dans la page, sous forme de boutons cliquables.

Contexte

Pour l'instant, le fichier app/page.tsx affiche uniquement une seule question, récupérée depuis Supabase.

afficher_question.png

Nous allons maintenant :

  1. Modifier la requête Supabase pour récupérer aussi les réponses associées à cette question.
  2. Afficher ces réponses sous forme de boutons cliquables.
  3. Afficher un message lorsque l’utilisateur clique sur une réponse, indiquant si elle est correcte ou non.

Étape 1 : Créer une nouvelle branche Git

git checkout -b affichage-reponses

Étape 2 — Structure des données

Comprendre la structure des données

supabase-question_reponse.png

Tables concernées

  • question : contient les champs id, texte, etc.
  • reponse : contient les champs id, texte, est_correcte, et une clé étrangère id_question vers question.id.

Relation

Chaque question peut avoir plusieurs réponses.
Chaque réponse appartient à une seule question (via id_question).


Étape 3 — Désactiver les RLS

Désactiver les RLS pour la table reponse

Pour que notre application puisse lire les réponses, il faut désactiver les RLS (Row Level Security) pour la table reponse.

  • Allez dans Supabase > Table Editor > reponse

    10_disable_RLS_reponse.png

  • Cliquez sur le bouton Add RLS policy

    11_disable_RLS_reponse.png

  • Cliquez sur le bouton Disable RLS.

    12_disable_RLS_reponse.png

  • Cliquez sur le bouton Confirm.

astuce
  • La RLS sera réactivée plus tard (pour la sécurité). Nous verrons, à une étape ultérieure, comment faire ça bien.
  • Pour l’instant, nous voulons juste récupérer des données facilement.

Étape 4 — Préparer l’IDE

Préparer l’environnement de développement

  1. Démarrer VSCode et ré-ouvrir le dossier du projet :

  1. Ouvrir le terminal intégré dans VS Code. Menu TerminalNew Terminal.

  1. Lancer le serveur de développement (si ce n’est pas déjà fait) :
npm run dev

13_ouvrir_vscode.png


Étape 5 — Modifier la requête Supabase

Dans la fonction fetchQuestion(), il faut remplacer :

.select('*')

par une requête avec jointure, pour récupérer les réponses liées à la question :

.select(`
id,
texte,
reponses:reponse (
id,
texte,
est_correcte
)
`)

Cette nouvelle requête permet de :

  • Récupérer les champs id et texte de la question
  • Récupérer les réponses associées via la table reponse, et les renommer localement sous le champ reponses

13_select.png


Étape 6 — Afficher des boutons

Afficher les réponses sous forme de boutons

Objectif : afficher les réponses d'une question sous forme de boutons cliquables.

Maintenant que la requête Supabase a été modifiée pour récupérer également les réponses associées à la question, il est temps d’afficher ces réponses dans l’interface utilisateur.

1. Importer le composant Button

https://ui.shadcn.com/docs/components/button

Le composant Button permet d’afficher des boutons stylisés de manière moderne et cohérente avec le reste de l’interface.

14_shadcn_Button.png

npx shadcn@latest add button

Ensuite, importez le composant dans votre fichier app/page.tsx :

import { Button } from "@/components/ui/button";

15_shadcn_Button.png


2. Parcourir les réponses avec .map()

Pour afficher chaque réponse, vous allez utiliser la méthode .map() sur le tableau question.reponses.

Voici un exemple de code à insérer dans le rendu du composant (return) :

{question.reponses.map((reponse: any) => (
<Button
key={reponse.id}
onClick={() => handleClick(reponse)}
className="w-full justify-start mt-4"
variant="outline"
>
{reponse.texte}
</Button>
))}

Chaque bouton représente une réponse possible. Lorsqu’un utilisateur clique sur un bouton, la fonction handleClick est appelée avec la réponse sélectionnée en paramètre.

16_reponses_map.png


3. Créer la fonction handleClick

Vous devez maintenant créer une fonction qui réagit lorsqu’un utilisateur clique sur une réponse. Cette fonction va vérifier si la réponse est correcte ou non, et afficher un message en conséquence.

Ajoutez cette fonction dans votre composant Home :

function handleClick(reponse: any) {
if (reponse.est_correcte) {
alert("Bonne réponse !");
} else {
alert("Mauvaise réponse.");
}
}

Cette fonction utilise une condition if pour vérifier la propriété est_correcte de la réponse. Elle affiche ensuite un message avec alert().

17_handleClick.png


Étape 7 — Tester le fonctionnement

Objectif : vérifier que l'ensemble fonctionne correctement

Voici les actions que vous devez effectuer pour valider cette étape :

  1. Redémarrez le serveur de développement si besoin (npm run dev).
  2. Ouvrez votre navigateur à l’adresse http://localhost:3000.
  3. Observez l’affichage : une question doit apparaître, accompagnée de plusieurs boutons (chaque bouton représentant une réponse).
  4. Cliquez sur une réponse : un message doit s’afficher indiquant si la réponse est correcte ou non.

18_test_fonctionnement.png


Étape 8 — Ajouter ORDER BY

Si vous souhaitez que les questions s’affichent toujours dans le même ordre, vous pouvez ajouter un ORDER BY dans la requête Supabase, en ajoutant la ligne suivante : .order('id', { ascending: true }); dans votre code Javascript.

      const { data, error } = await supabase
.from('question')
.select(`
id,
texte,
reponses:reponse (
id,
texte,
est_correcte
)
`)
.order('id', { ascending: true });

Étape 9 : Mettre à jour le dépôt sur GitHub

  1. Une fois que votre modification est terminée, pensez à commiter votre travail.

    git add .
    git commit -m "Ajout de l'affichage des réponses"
  2. Puis, revenez sur main et fusionnez votre branche.

    Voici la commande pour revenir sur la branche main :

    git checkout main  

    Voici la commande pour fusionner la branche affichage-reponses dans la branche main :

    git merge affichage-reponses  
  3. Et enfin, pensez à enregistrer votre travail sur GitHub.

    Voici la commande pour "pousser" la branche main :

    git push  

Pour plus de détails sur l'utilisation de Git, consultez le tutoriel Git.


Corrigé complet

Une solution

Résultat attendu

  • Une question s’affiche dans une carte.
  • Les réponses apparaissent en dessous sous forme de boutons.
  • Lorsque l’utilisateur clique sur une réponse, un message s’affiche pour indiquer si la réponse est correcte ou non.

Bonus, pour aller plus loin

Voici quelques pistes d'amélioration que vous pouvez explorer :

AméliorationDescription
Message visuelRemplacer les alert() par une zone de texte dans la page (ex. : carte verte ou rouge)
Désactiver les boutonsUne fois qu’une réponse est cliquée, désactiver tous les boutons pour éviter plusieurs clics
Passer à la question suivanteCharger automatiquement une nouvelle question après quelques secondes
Ajouter un scoreCompter le nombre de bonnes réponses et l’afficher à l’utilisateur