Aller au contenu principal

Afficher une image

Rendre l’interface plus visuelle et moderne avec une image d’illustration

99_resultat_final.png


Notions théoriques

Pourquoi ajouter une image ?

Les images permettent de :

  • Rendre le quiz plus attrayant
  • Mieux illustrer certaines notions de cybersécurité (ex. : phishing, ransomware)
  • Stimuler la mémorisation visuelle

Où placer l’image à l'écran ?

Nous allons afficher l’image à gauche de la question, dans la carte déjà utilisée par les élèves.

Cela donnera une interface plus équilibrée :

Colonne gaucheColonne droite
ImageTexte + Réponses

Où stocker les images dans le projet ?

3 solutions sont possibles pour stocker les images
  • Dans Supabase (via le Storage intégré)
  • Dans le dossier /public de votre projet Next.js (solution simple pour débuter)
  • Depuis une URL externe (attention à la fiabilité du lien)

Dans cette séance, nous allons utiliser la méthode la plus simple : stocker les images localement dans le dossier /public/images.

Pour cette séance, nous allons stocker les images localement dans le dossier /public/images.

Ce dossier est accessible directement depuis le navigateur :

  • Exemple : /images/phishing.png sera visible à l’adresse http://localhost:3000/images/phishing.png

Où trouver des images gratuites ?

Pour illustrer une question sur le phishing, nous allons télécharger une image libre de droits représentant une tentative d’hameçonnage (phishing email).

Étape 1 — Trouver des images sur un site libre de droits

Voici 2 possibilités fiables :

  1. Unsplash
    Rechercher : phishing, cybersecurity, hacker, email fraud

    Exemple de lien : https://unsplash.com/s/photos/phishing

  2. Pixabay
    Rechercher : phishing, cyber attack, cybersecurity

    Exemple de lien : https://pixabay.com/images/search/phishing/

Étape 2 — Télécharger des images

Prenons un exemple concret sur Pixabay :

  1. Rendez-vous sur : https://pixabay.com/vectors/phishing-fraud-hacking-online-fraud-6926470/

pixabay_phishing.png

  1. Cliquez sur le bouton Download
  2. Choisissez une taille raisonnable (ex. : 640×457 PNG 44 kB)
  3. Cliquez sur le bouton Download

Étape 3 — Enregistrer les images dans votre projet

  1. Renommez l’image téléchargée en phishing.png
  2. Placez-la dans le dossier /public/images de votre projet Next.js :
/public/images/phishing.png
astuce

Si le dossier /public/images n’existe pas, créez le dossier /images dans /public.

public_images.png

Étape 4 — Vérifier que les images fonctionnent

Lancez votre serveur local (npm run dev) et ouvrez cette URL dans votre navigateur :

http://localhost:3000/images/phishing.png

public_phishing.png

attention

Trouvez, téléchargez et enregistrez des images pour vos autres questions.

Veillez à respecter les droits d’auteur et à utiliser des images libres de droits.


Le composant <Image />

Next.js propose un composant optimisé pour afficher les images :

import Image from 'next/image';

<Image
src="/images/phishing.png"
alt="Illustration"
width={300}
height={200}
/>

Disposition en 2 colonnes

Nous allons utiliser Flexbox avec Tailwind CSS pour afficher l’image à gauche et le texte à droite :

<div className="flex">
<div className="w-1/2">Image</div>
<div className="w-1/2">Texte + Réponses</div>
</div>

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

Nous allons modifier l’application Quiz Cyber pour :

  1. Ajouter une image à une question
  2. Afficher cette image à gauche de la carte
  3. Respecter les droits d’auteur (nom de l’auteur et lien vers la source)
  4. Utiliser les composants Image, Card, Alert, etc.
attention

Avant de commencer, pensez à créer une nouvelle branche Git !


Étape 1 — Ajouter des colonnes

Ajouter des colonnes dans Supabase

  • Allez dans Supabase > Table Editor
  • A droite de la table question, cliquez sur les 3 points ...

10_image_url.png

  • Cliquez sur Edit Table

11_image_url.png

  • Cliquez sur le bouton Add column
  • Saisissez les informations des nouvelles colonnes :
Nom de la colonneType
image_urltext
image_credit_nomtext
image_credit_urltext

12_image_url.png

  • Cliquez sur le bouton Save

13_image_url.png

  • Ensuite, modifiez une question existante pour y ajouter ces informations :

  • image_url : /images/phishing.png

  • image_credit_nom : Mohamed Hassan

  • image_credit_url : https://pixabay.com/users/mohamed_hassan-5229782/

astuce

Appuyez sur la touche Entrée pour enregistrer chaque modification.

attention

Enregistrez les informations des images pour vos autres questions. 14_image_url.png


Étape 2 — Energistrer vos images

Ajouter vos images dans le dossier public/images

  1. Téléchargez les image libre de droits (par exemple sur Pixabay)
  2. Placez-les dans le dossier /public/images/
  3. Vérifiez que les images sont bien accessibles dans votre navigateur :
http://localhost:3000/images/phishing.png

Étape 3 — Utiliser <Image />

Afficher l’image de manière optimisée dans l’interface avec le composant <Image />

Dans Next.js, le composant Image permet d’optimiser le chargement des images.

Voici un exemple d’utilisation :

import Image from "next/image";

<Image
src="/images/phishing.png"
alt="Illustration"
width={400}
height={300}
className="rounded"
/>

Le chemin src correspond à une image placée dans le dossier /public.


Étape 4 — Affichage en 2 colonnes

Organiser l’affichage en 2 colonnes pour afficher l’image à gauche et la question à droite

Utilisez Flexbox avec Tailwind CSS pour créer une disposition en 2 colonnes :

<div className="flex">
<div className="w-1/2">Image</div>
<div className="w-1/2">Texte + Réponses</div>
</div>

Chaque colonne occupe 50 % de la largeur de la carte.


Étape 5 — Afficher les droits d’auteur

Afficher les crédits de l’image pour respecter les droits d’auteur avec un lien cliquable

Utilisez les composants Alert et AlertDescription pour afficher les crédits sous l’image :

import { Alert, AlertDescription } from "@/components/ui/alert";
import Link from "next/link";

<Alert className="mt-4 text-sm text-muted-foreground">
<AlertDescription>
Image :{" "}
<Link
href="https://pixabay.com/users/mohamed_hassan-5229782/"
target="_blank"
rel="noopener noreferrer"
className="underline underline-offset-2 hover:text-primary"
>
Mohamed Hassan
</Link>
</AlertDescription>
</Alert>

Ce bloc s’affiche uniquement si les champs image_credit_nom et image_credit_url sont renseignés.

attention

Maintenant que votre nouvelle fonctionnalité est terminée, pensez à envoyer votre travail vers GitHub !

Code complet

Voici le code complet à placer dans le fichier app/page.tsx :

"use client";

import { useEffect, useState } from "react";
import { supabase } from "../lib/supabaseClient";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import Image from "next/image";
import Link from "next/link";

export default function Home() {
const [question, setQuestion] = useState<any>(null);

useEffect(() => {
async function fetchQuestion() {
const { data, error } = await supabase
.from("question")
.select(`
id,
texte,
image_url,
image_credit_nom,
image_credit_url,
reponses:reponse (
id,
texte,
est_correcte
)
`)
.order("id", { ascending: true });

if (error) {
console.error("Erreur Supabase :", error);
} else {
setQuestion(data?.[0]); // On prend la première question du tableau
}
}

fetchQuestion();
}, []);

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

return (
<div>
<Alert className="bg-blue-50 border-blue-300 text-blue-800 max-w-xl mx-auto mt-6">
<AlertTitle className="text-xl font-semibold">Bienvenue sur CyberQuiz</AlertTitle>
<AlertDescription>
Un quiz pour tester vos connaissances en cybersécurité.
</AlertDescription>
</Alert>

{question ? (
<Card className="max-w-4xl mx-auto mt-6">
<div className="flex">
{/* Colonne gauche : image + crédit */}
<div className="w-1/2 p-4">
{question.image_url ? (
<Image
src={question.image_url}
alt="Illustration de la question"
width={400}
height={300}
className="rounded"
/>
) : (
<div className="w-full h-[300px] bg-gray-100 flex items-center justify-center text-sm text-gray-500 rounded">
Aucune image disponible
</div>
)}

{question.image_credit_nom && question.image_credit_url && (
<Alert className="mt-4 text-sm text-muted-foreground">
<AlertDescription>
<span className="inline">
Image :{" "}
<Link
href={question.image_credit_url}
target="_blank"
rel="noopener noreferrer"
className="underline underline-offset-2 hover:text-primary"
>
{question.image_credit_nom}
</Link>
</span>
</AlertDescription>
</Alert>
)}
</div>

{/* Colonne droite : question + réponses */}
<div className="w-1/2 p-4">
<CardHeader className="p-0 mb-4">
<CardTitle>Question</CardTitle>
</CardHeader>
<CardContent className="p-0">
<p className="text-lg font-semibold mb-4">{question.texte}</p>
{question.reponses.map((reponse: any) => (
<Button
key={reponse.id}
onClick={() => handleClick(reponse)}
className="w-full justify-start mt-2"
variant="outline"
>
{reponse.texte}
</Button>
))}
</CardContent>
</div>
</div>
</Card>
) : (
<p className="text-center mt-6">Chargement de la question...</p>
)}
</div>
);
}

Résultat attendu

  • Une carte contenant :
    • Une image affichée à gauche
    • Le texte de la question et les réponses à droite
    • Le nom de l’auteur de l’image affiché sous l’image, avec un lien cliquable
  • Une interface sobre et claire, utilisant les composants ShadCN

99_resultat_final.png


Bonnes pratiques

  • Utiliser des images légères (moins de 200 Ko)
  • Vérifier que les liens de crédit sont valides et sécurisés (https)
  • Utiliser les composants fournis pour garantir l’homogénéité de l’interface