:: Enseignements :: ESIPE :: E3INFO :: 2025-2026 :: Web et Géomatique ::
[LOGO]

TP noté d'Application Web - session 2


Le but de ce TP est de réaliser une application qui permet de commander des pizzas, un "Pizza Order".

Vous devez créer vos fichiers dans le répertoire EXAM qui est un sous répertoire de votre répertoire home dans l'environnement de TP noté. Seuls les fichiers créés dans ce répertoire seront sauvegardés. Donc si vous ne créez pas les fichiers dans le répertoire EXAM mais dans un autre répertoire, ils ne seront pas sauvegardés, donc pas corrigés.
Comme l'environnement de TP noté coupe les communications TCP vers l'extérieur,

Il est important de faire attention à la qualité du code que vous allez rendre. Avoir un code qui semble marcher, mais qui n'est pas maintenable, pas compréhensible ou qui contient du code mort (qui ne sert à rien) sera fortement pénalisé.

Voilà une idée graphique de l'application que l'on veut réaliser

Et voilà l'arbre DOM (en 2 copies) que l'on souhaite obtenir.


Exercice 1 - Pizza Order

Dans un premier temps, récupérer le tar.gz qui contient la commande esbuild et les bibliothèques react et react-dom.
Décompresser l'archive (tar zxvf pizza-node-modules.tgz) pizza-node-modules.tgz dans le répertoire EXAM.
Rappel, pour transformer le fichier JSX en JS, on utilise la commande
                ./node_modules/.bin/esbuild pizza.jsx --bundle --outfile=pizza.js
            

L'API presque REST du serveur est définie comme ceci:
  • GET /api/pizza renvoie un tableau d'objets contenant le nom de la pizza, la quantité disponible en stock et son prix.
    Vous pouvez tester en copiant dans votre navigateur http://localhost:8080/api/pizza.
  • POST /api/order permet de passer une commande.
    La commande est envoyée sous forme d'un objet JSON dont les propriétés sont les noms des pizzas commandées et les valeurs les quantités souhaitées, par ex: { "regina" : 2, "hawaiian" : 1 }
    Cet appel renvoie un objet JSON contenant le prix total facturé, par ex: { "price" : 24.50 }

Pour démarrer, on va utiliser le fichier pizza.html suivant
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="icon" href="data:,">
    <link rel="stylesheet" type="text/css" href="pizza.css">
    <script src="pizza.js" type="text/javascript"></script>
  </head>
  <body>
    <div id="App"></div>
  </body>
</html>
            

Le fichier pizza.jsx suivant
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import App from './App';

window.onload = () => {
  const appDOM = document.getElementById("App");

  const root = ReactDOM.createRoot(appDOM);
  root.render(<App/>);
};
            
et le fichier App.jsx (pas fini) suivant
import * as React from 'react';
import { getPizzas, placeOrder } from './api';
import PizzaList from './PizzaList';
import CurrentOrder from './CurrentOrder';
import OrderFooter from './OrderFooter';

export default function App() {
  /* TODO */
}
            

Pour le CSS, on va utiliser le fichier pizza.css..
On utilisera de plus le serveur Java JExpress.java pour servir les fichiers pizza.html et pizza.js et l'API REST spécifiée ci-dessus.

L'application est composée de 3 parties:
  • la partie haute (PizzaList) qui affiche la liste des pizzas disponibles, sous forme de cartes cliquables.
  • La partie centrale (CurrentOrder), qui affiche la commande en cours, avec pour chaque pizza sélectionnée sa quantité (modifiable) et son sous-total.
  • La partie basse (OrderFooter), qui affiche le total de la commande et un bouton pour valider la commande.

En termes de développement, on va d'abord développer la partie haute, puis la partie centrale, puis enfin la partie basse.

  1. Utiliser esbuild pour réécrire le fichier JSX en fichier JS puis lancer le serveur java JExpress.java dans le répertoire courant et vérifier avec un navigateur que l'application s'affiche bien à l'adresse http://localhost:8080/pizza.html.

  2. A partir de maintenant, on va modifier les fichiers App.jsx, PizzaList.jsx CurrentOrder.jsx et OrderFooter.jsx pour créer notre application, et il ne faudra pas oublier après chaque modification de relancer esbuild ou alors, vous pouvez utiliser l'option --watch.
    Dans un premier temps, on va développer les composants App et PizzaList. Le composant App contient le tableau des pizzas. Le composant PizzaList est responsable de l'affichage de la grille des pizzas disponibles.
    Pour récupérer les pizzas, faites un appel asynchrone à l'API dans un useEffect.
    Chaque carte doit afficher le nom de la pizza, son prix et soit le nombre restant en stock, soit la mention "Sold out" si le stock est à 0 (dans ce cas la carte doit être désactivée, (disabled) donc non cliquable).
    Écrire les composants App et PizzaList et visualiser que l'affichage est correct.
    Note : pour l'instant, on ne s'occupe ni de la commande en cours ni du total.
    Note2 : si React vous engueule sur la console du navigateur web, il faut faire quelque chose !

  3. On souhaite maintenant que cliquer sur une carte de pizza l'ajoute à la commande en cours.
    Créer le composant CurrentOrder, qui affiche la liste des pizzas actuellement commandées, avec pour chacune sa quantité et son sous-total (prix unitaire × quantité).
    Quelle est à votre avis la structure de donnée que vous allez utiliser pour stocker la commande ? Êtes-vous vraiment sûr que c'est la bonne structure ?
    Si aucune pizza n'a encore été sélectionnée, afficher un message du type "Pick a pizza above to start your order."
    Chaque clic sur une carte en partie haute doit incrémenter la quantité commandée pour cette pizza, sans jamais dépasser la quantité disponible en stock.

  4. On veut maintenant pouvoir ajuster la quantité de chaque pizza directement depuis la commande en cours, à l'aide de deux boutons "+" et "−" à côté de chaque ligne de CurrentOrder.
    Le bouton "−" doit être désactivé si la quantité est à 0, le bouton "+" doit être désactivé si la quantité atteint le stock disponible pour cette pizza.
    Faites les changements qui s'imposent.

  5. On veut maintenant ajouter la partie basse de l'application.
    Créer le composant OrderFooter, qui affiche le prix total de la commande en cours (somme des sous-totaux) ainsi qu'un bouton "Order".
    Ce bouton doit être désactivé tant qu'il n'y a rien à commander.
    Note: il y a un bonus si vous utilisez un appel à reduce pour calculer le prix total.

  6. On veut maintenant que cliquer sur le bouton "Order" envoie effectivement la commande au serveur.
    Une fois la commande passée avec succès, on veut afficher un message de confirmation indiquant le prix facturé (renvoyé par le serveur), remettre la commande en cours à zéro, et recharger la liste des pizzas depuis le serveur (pour que les quantités en stock soient à jour).
    Comment allez-vous procéder pour que le message de confirmation disparaisse dès que l'utilisateur recommence à modifier sa commande ?

  7. Enfin, on veut gérer proprement le cas où le serveur a un problème, que ce soit lors du chargement de la liste des pizzas ou lors de l'envoi de la commande.
    Note: pour tester, au niveau du code du serveur Java, chercher un "if (false) {" et remplacer le false par true.
    Faites les changements qui s'imposent.