Devoir React S4 - 21 mars 2025

Durée 1H20

Tous documents autorisés sauf les IA génératives

Si une fraude est détectée, un procès verbal sera dressé par l'enseignant qui surveille l'épreuve.

Le devoir est à remettre sur le moodle du cours.

open food fact

Fonctionalités

Le sujet de ce devoir consiste à réaliser en REACT (et TypeScript) une application (one page) permettant de chercher des livres d'auteurs de romans puis de sélectionner ceux que l'on souhaite se faire offrir.

La vidéo suivant illustre le résultat final attendu.

Chaque question permet d'avancer pas à pas vers cet objectif. Les 8 premières questions peuvent se faire de manière indépendantes. Tout code sera évalué, donc ne restez pas bloqués !

API Livre

L'API est très simple d'utilisation. Il n'y a que deux routes (get) .

Si vous rencontrez un problème avec l'API

Si jamais le jour du devoir l'API n'est plus disponible pour une raison ou une autre, veuillez créer un fichier JSON vous même et copiez-y les données en annexe données à la fin du sujet.

Débuter ce devoir

Ce devoir se présente sous la forme d'un projet disponible ici. Désarchivez-le, faites npm install puis faites npm start (ou npm run dev)

Nous vous donnons toute l'architecture du projet. Plusieurs morceaux de composants sont déjà codés. L'idée de ce devoir est, pour chaque question, de vous faire compléter puis tester un composant.

Chaque composant est testable de manière indépendante. Dans le fichier App.tsx, il faudra décommenter les composants tests (que je vous ai préparés) permettant de tester vos propres composants.

Question 1 (1 point)

Dans models/livre.model.tsx, le type LivreModel est défini. Tous les types de ses attributs ont été mis à any. Affectez le type adéquat à chaque attribut.

Pour rappel, voici un extrait du JSON côté serveur

{
"titre": "Les Misérables",
"auteur": "Victor Hugo",
"genres": ["Roman historique", "Drame"],
"datePublication": 1862,
"notes": [5, 4, 5, 3]
"img" : "default.jpeg"
"prix" : 3
},
{
"titre": "1984",
"auteur": 102,
"genres": ["Science-fiction", "Politique"],
"datePublication": 1949,
"notes": [4, 5, 5, 5, 2],
"img" : "default.jpeg"
"prix" : 11
}

Vous remarquerez que l'attribut selectionne n'est pas issu du JSON retourné par l'API. C'est une donnée qui est locale à votre application. Cet attribut servira plus tard à savoir si le livre a été sélectionné ou pas par l'utilisateur (par défaut c'est false)

Testez en décommentant la ligne <TestQuestion1/>

vous devriez voir dans la console :

Question 2 (2 points)

Dans services/livres.services.ts, complétez le code de la méthode getLivre permettant de faire une requête paramétrée au endPoint /livre et d'afficher ce qui est retourné par le serveur.

Décommenter les trois lignes <TestQuestion2/>. Vous deveriez voir dans la console (l'ordre peut changer selon quelle requête est revenue avant l'autre) :

Vous remarquerez ici que l'attribut selectionne est affiché. Comme ce n'est pas une information stockée sur le serveur, c'est bien à vous, dans le code de retourner les données du serveur auxquelles vous ajoutez l'attribut selectionne fixé à false

Question 3 (2 points)

Dans services/livres.services.ts, complétez le code de la méthode getOeuvres permettant de faire une requête paramétrée au endPoint /oeuvres et d'afficher ce qui est retourné par le serveur (toutes les oeuvres associées au nom de l'auteur passé en paramètre).

Décommenter les trois lignes <TestQuestion3/>. Vous deveriez voir dans la console (l'ordre peut changer selon quelle requête est revenue avant l'autre) :

Vous remarquerez ici que l'attribut selectionne de chaque livre est affiché. Comme ce n'est pas une information stockée sur le serveur, c'est bien à vous, dans le code de retourner les données du serveur auxquelles vous ajoutez l'attribut selectionne fixé à false pour chaque livre.

Question 4 (2 points)

Dans services/livres.services.ts, complétez le code de la méthode calculerMoyenneNotes. Cette méthode prend un livre en paramètre et retourne la moyenne des notes. S'il n'y a pas de notes, cette méthode retourne null. Pour avoir les deux points il faut utiliser reduce().

Décommenter la ligne <TestQuestion4/>. Vous deveriez voir dans la console :

Question 5 (2 points)

Dans services/livres.services.ts, complétez le code de la méthode trierLivresParMoyenne. Cette méthode prend un OrdreTri (défini dans models/livres.model.ts) et un tableau de livres en paramètres et trie par ordre croissant (ou décroissant) de moyennes de notes. S'il n'y a pas de notes, pour un livre, vous pouvez consisérer (dans l'ordre du tri) que la moyenne vaut 0. Ce n'est pas obligatoire, mais je vous conseille d'utiliser sort pour ecrire facilement ce code.

Décommenter la ligne <TestQuestion5/>. Vous deveriez voir dans la console :

Question 6 (3 points)

Dans composants/Etoiles.tsx, complétez le code du composant Etoiles. Ce composant :

Pour afficher une étoile pleine ou vide il faut simplement générer ce html.

          <span style="color: gold; font-size: 24px">★</span>
          <span style="color: gold; font-size: 24px">☆</span>
        
Copiez-collez les caractères ☆ et ★ dans votre code React. Ne perdez pas de temps à les générer en css.

Décommenter la ligne <TestQuestion6/>. Vous deveriez voir sur la page :

Question 7 (2 points)

Dans composants/LivreCard.tsx, complétez le code du composant LivreCard. Ce composant :

Question 8 (3 points)

Dans composants/Toggle.tsx, complétez le code du composant Toggle. Ce composant

Dans composants/LivreCardInteractif.tsx, copiez-y le code du composant LivreCard que vous venez de créer à la question précédente. Il faut maintenant le faire évoluer :

Décommenter la ligne <TestQuestion8/>. Vous deveriez voir sur la page l'une ou l'autre de ces deux copies d'écrans selon que vous avez appuyé ou non sur le boutton "cliquer ici":

Question 9 (3 points)

Dans composants/RechercheLivres.tsx, complétez le code du composant RechercheLivres. Ce composant

C'est dans cette question que vous devez utiliser toutes les fonctions et composants codés dans les questions précédentes.

Annexes

En cas de problème avec l'API, voici le json dont vous avez besoin.

Si le serveur est hors service le jour de l'évaluation, à la place de l'image affichez simplement son URL

  [
    {
        "id": 1,
        "titre": "Les Misérables",
        "auteur": "Victor Hugo",
        "genres": ["Roman historique", "Drame"],
        "datePublication": 1862,
        "notes": [5, 4, 5, 3],
        "img" : "images/miserables.jpg",
        "prix" : 3
    },
    {
        "id": 2,
        "titre": "1984",
        "auteur": "Orson Welles",
        "genres": ["Science-fiction", "Politique"],
        "datePublication": 1949,
        "notes": [4, 5, 5, 5, 2],
        "img" : "images/1984.jpg",
        "prix" : 11
    },
    {
        "id": 3,
        "titre": "L'Étranger",
        "auteur": "Albert Camus",
        "genres": ["Philosophie"],
        "datePublication": 1942,
        "notes": [5, 5, 0, 4],
        "img" : "images/etranger.jpg",
        "prix" : 5
    },
    {
        "id": 4,
        "titre": "To Kill a Mockingbird",
        "auteur": "Harper Lee",
        "genres": ["Drame", "Social"],
        "datePublication": 1960,
        "notes": [0],
        "img" : "images/mock.jpg",
        "prix" : 12
    },
    {
        "id": 5,
        "titre": "Le Petit Prince",
        "auteur": "Antoine de Saint-Exupéry",
        "genres": ["Fiction", "Philosophie"],
        "datePublication": 1943,
        "notes": [],
        "img" : "images/prince.jpg",
        "prix" : 3
    },
    {
        "id": 6,
        "titre": "Moby Dick",
        "auteur": "Herman Melville",
        "genres": ["Aventure"],
        "datePublication": 1851,
        "notes": [4, 4],
        "img" : "images/moby.jpeg",
        "prix" : 10
    },
    {
        "id": 7,
        "titre": null,
        "auteur": "Leo Tolstoy",
        "genres": ["Roman historique"],
        "datePublication": 1877,
        "notes": [2],
        "img" : "images/anna.jpg",
        "prix" : 1
    },
    {
        "id": 8,
        "titre": "War and Peace",
        "auteur": "Leo Tolstoy",
        "genres": ["Roman historique", "Drame", "Philosophie"],
        "datePublication": 1869,
        "notes": [5],
        "img" : "images/war.jpg",
        "prix" : 1
    },
    {
        "id": 9,
        "titre": "Brave New World",
        "auteur": "Aldous Huxley",
        "genres": ["Science-fiction"],
        "datePublication": 1932,
        "notes": [4, 5],
        "img" : "images/brave.jpg",
        "prix" : 6
    },
    {
        "id": 10,
        "titre": "Don Quixote",
        "auteur": "Miguel de Cervantes",
        "genres": ["Aventure", "Comédie"],
        "datePublication": 1605,
        "notes": [1, 5, 4, 5],
        "img" : "images/don.jpg",
        "prix" : 5
    },
    {
        "id": 11,
        "titre": "Crime and Punishment",
        "auteur": "Fyodor Dostoevsky",
        "genres": ["Psychologie", "Drame"],
        "datePublication": 1866,
        "notes": [],
        "img" : "images/crime.jpg",
        "prix" : 3
    },
    {
        "id": 12,
        "titre": "The Catcher in the Rye",
        "auteur": null,
        "genres": ["Roman initiatique"],
        "datePublication": 1951,
        "notes": [4, 3],
        "img" : "images/rye.jpg",
        "prix" : 8
    },
    {
        "id": 13,
        "titre": "Notre-Dame de Paris",
        "auteur": "Victor Hugo",
        "genres": ["Roman historique", "Gothique"],
        "datePublication": 1831,
        "notes": [5, 0, 4, 5],
        "img" : "images/dame.jpg",
        "prix": 5
    },
    {
        "id": 14,
        "titre": "L'Homme qui rit",
        "auteur": "Victor Hugo",
        "genres": ["Drame", "Roman philosophique"],
        "datePublication": 1869,
        "notes": [4, 1],
        "img" : "images/rit.jpg",
        "prix": 16
    },
    {
        "id": 15,
        "titre": "The Doors of Perception",
        "auteur": "Aldous Huxley",
        "genres": ["Essai", "Philosophie"],
        "datePublication": 1954,
        "notes": [5, 0, 4],
        "img": "images/doors.jpeg",
        "prix": 7
    }
]