:: Enseignements :: ESIPE :: E3INFO :: 2024-2025 :: Programmation Web avec JavaScript ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) |
TP noté d'Application Web - session 2
|
Le but de ce TP est de réaliser une application permettant d'acheter des articles
informatique en simulant un "Shopping Cart".
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 sauvegarder. 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 environnement 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
Le but de l'application est de visualiser des produits existants (ceux-ci sont définis par le serveur).
Puis de permettre à l'utilisateur d'ajouter des produits à un panier (il est possible de prendre plusieurs
articles d'un même produit, on indique pour cela une quantité).
Enfin, si le panier n'est pas vide, il est possible d'acheter (avec une requète au serveur)
les produits du panier.
Graphiquement, l'application est composé de 3 zones. La zone des produits qui contient
le titre "Product" ainsi qu'une liste des produits. La zone panier qui le titre "Cart"
suivi du prix du panier, puis les articles du panier. Et enfin, une zone achat, avec
le titre "Buy" qui possède un bouton "Buy" qui permet d'acheter les articles du panier.
Et voilà l'arbre DOM que l'on souhaite obtenir.
Exercice 1 - Cart
Dans un premier temps, récupérer un
tar.gz le contient la commande
esbuild
et les bibliothèques
react et
react-dom.
Décompresser l'archive (
tar zxvf cart-node-modules.tgz)
cart-node_modules.tgz
dans le répertoire
EXAM.
Rappel, pour transformer le fichier JSX en JS, on utilise la commande
./node_modules/.bin/esbuild cart.jsx --bundle --outfile=cart.js
L'API REST du serveur est définie comme ceci:
-
Obtenir tous les produits: GET /api/product
Cet appel renvoi l'ensemble des produits au format JSON.
Vous pouvez tester en copiant dans votre navigateur http://localhost:8080/api/product.
-
Acheter les articles d'un panier: POST /api/buy
Le JSON à envoyer doit être un objet qui à chaque id de produit indique la quantité
correspondante.
Par exemple, si on achète deux keyboard (id = "14") et trois headphones (id = "10"),
on doit envoyer l'objet suivant
{
"14": 2,
"10": 3
}
Cet appel renvoi un code 200 si cela s'est bien passé.
Pour démarrer, on va utiliser le fichier
cart.html suivant
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="icon" href="data:,">
<script src="cart.js" type="text/javascript"></script>
<style>
/* Main App Container */
.app {
max-width: 800px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
line-height: 1.6;
}
/* Section Headers */
.app h3 {
color: #333;
border-bottom: 2px solid #ddd;
padding-bottom: 10px;
margin: 30px 0 20px 0;
}
/* Product Section */
.product-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #f9f9f9;
}
.product-info h3 {
margin: 0 0 5px 0;
color: #333;
border: none;
padding: 0;
}
.product-info p {
margin: 0;
font-weight: bold;
color: #2c5530;
font-size: 1.1em;
}
/* Article Section */
.article-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #f0f8ff;
}
.article-info {
display: flex;
align-items: center;
gap: 15px;
font-weight: 500;
}
/* Buy Section */
.buy-content {
text-align: center;
padding: 20px;
}
button {
padding: 10px 20px;
border: none;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
min-width: 120px;
}
button:disabled {
cursor: not-allowed;
opacity: 0.6;
transform: none;
}
/* Button Color Variations */
.btn-add-cart {
background-color: #009e4f;
color: white;
}
.btn-remove-cart {
background-color: #ff007b;
color: white;
}
.btn-quantity {
background-color: #007bff;
color: white;
min-width: auto;
padding: 5px 12px;
font-size: 12px;
}
.btn-buy {
background-color: #ff7b00;
color: white;
font-size: 16px;
padding: 15px 30px;
min-width: 200px;
}
/* Responsive Design */
@media (max-width: 600px) {
.product-content, .article-content {
flex-direction: column;
gap: 15px;
text-align: center;
}
.article-info {
flex-direction: column;
gap: 10px;
}
}
</style>
</head>
<body>
<div id="App"></div>
</body>
</html>
Et pour le fichier
cart.jsx suivant
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
function App() {
return <div className="app">TODO</div>;
}
window.onload = () => {
const appDOM = document.getElementById("App");
const root = ReactDOM.createRoot(appDOM);
root.render(<App/>);
};
On utilisera de plus le serveur Java
JExpress.java
pour servir les fichiers
cart.html et
cart.js et l'API REST spécifique.
-
Utiliser esbuild pour ré-écrire le fichier JSX en fichier JS puis
lancer le serveur java --enable-preview JExpress.java dans le répertoire courant et
vérifier avec un navigateur que l'application s'affiche bien à l'adresse
http://localhost:8080/cart.html.
-
A partir de maintenant, on va modifier le fichier cart.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.
Créer un composant graphique ProductList qui permet d'afficher les produits (product),
un DIV par produit, le tout dans un grand DIV. Un produit est caractérisé par un id (id),
un nom (name) et un prix (price).
Pour trouver la structure exacte, utiliser l'image de l'arbre DOM (avec les bonnes classes).
Pour récupérer les produits au démarrage, faite un appel asynchrone avec fetch
à l'API su serveur dans un useEffect.
Note: penser que comme vous affichez une liste de produits, il ne faut pas oublier les clés pour React.
-
On veut maintenant s'occuper du panier.
Dans un premier temps, ajouter pour chaque produit un bouton "Add to Cart" qui permet d'ajouter
un produit au panier (Cart). Pour l'instant, lors de l'ajout du produit au panier,
la quantité est toujours 1.
Écrire le composant graphique Cart ainsi que le composant CartArticle
qui permettent de visualiser les articles sélectionnés par l'utilisateur dans le panier.
Note: pour l'instant, on ne s'occupe pas des boutons.
Note2: pour avoir la structure exacte, comme précédemment, utiliser l'image de l'arbre DOM.
-
Faire en sorte que le panier affiche le montant total, la somme des produits multipliés par
leur quantité, en haut du panier.
-
Ajouter un bouton "Remove From Cart" au niveau d'un article qui supprime
le produit du panier (quelle que soit la quantité !).
-
On souhaite changer le fonctionnement du bouton "Add to Cart" pour le rendre un peu
plus intélligent.
Si on appuie sur ce bouton la première fois,
un article correspondant au produit et avec la quantité 1 est ajouté au panier.
Si on appuie une seconde fois sur le bouton, pour le même produit, alors l'article
déjà présent correspondant au produit voit sa quantité incrémentée de 1.
-
Ajouter un niveau d'un article un bouton "+1" qui permet d'incrémenter la quatité
du produit de 1.
-
Créer le composant graphique correspondant à la section d'achat (Buy).
Faire en sorte d'afficher sur le bouton "Buy" le prix du panier.
-
Faire en sorte que si le panier est vide, le bouton "Buy" soit désactivé.
-
Enfin, faite en sorte que lorsque l'on clique sur le bouton d'achat "Buy",
l'application transfert le panier (au bon format !) puis si le serveur
a validé l'envoie, réinitialiser/vider le panier.
© Université de Marne-la-Vallée