Created
July 27, 2021 12:43
-
-
Save medkhelifi/8c2fbaeea21ce813f1936354d257f355 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const cart = document.getElementById("cart-list"); //section ou l'ensemble des information lié a page panier sont affiché. | |
const emptyCart = document.getElementById("empty-cart"); //balise qui s'affiche tant que le panier est vide. | |
let cartPrice = document.getElementById("cart-price"); | |
cartPrice.style.display = "none"; | |
const finalPrice = document.createElement("div"); //balise qui affichera le prix total de la commande. | |
finalPrice.classList.add("text-end"); //style bootstraps qui affichera le prix total sur la droite du panier. | |
finalPrice.classList.add("fs-4"); | |
finalPrice.classList.add("pb-2"); | |
let products = [], contact = {}; //variables néccessaire a l'appel et la réponse de l'API de commande. | |
let total = 0; //total = prix de l'ensemble du panier. | |
let counter = -1; | |
let gap = false; //permet d'éviter des probleme avec levent de selection quantité | |
//constante contenant le nombre de produit différents dans le panier, permettant l'itération de la boucle suivante.* | |
let supCount = 0; | |
let cartCounter = Number(localStorage.getItem("cart-counter")); | |
const quantityContainer = document.getElementsByClassName("quantity"); | |
const supProduct = document.getElementsByClassName("trash"); | |
//get all cart elements | |
const allCartItems = []; // Array to hold the keys | |
// Iterate over localStorage and insert the keys that meet the condition into allCartItems | |
for (var i = 0; i < localStorage.length; i++){ | |
if (localStorage.key(i).substring(0,5) == 'cart-') { | |
allCartItems.push(localStorage.key(i)); | |
} | |
} | |
allCartItems.sort(); | |
/** | |
* Initialisation du panier | |
* @returns | |
*/ | |
async function initialyse(){ //permet l'affichage initial des différents produits dans le panier et la mise en place des évenement | |
try{ | |
for(let i =0; i<allCartItems.length-1; i++){ | |
const onCart = JSON.parse(localStorage.getItem(allCartItems[i])); | |
const baseProductHTML = document.createElement("article"); | |
let gen = await genCartProductInfos(baseProductHTML, onCart.id, onCart); | |
quantityContainer[i].addEventListener('input', changeQuantity); | |
supProduct[i].addEventListener('click', cartSuppression) | |
} | |
/* | |
@TODO TO BE DELETED | |
for (i=1; i<= cartCounter; ++i) { | |
//crée un objet a partir de la chaine de caractere représentant les articles dans le localStorage pour | |
//ensuite construire le HTML de ces produit. | |
const onCart = JSON.parse(localStorage.getItem("cart-" + i)); | |
const baseProductHTML = document.createElement("article"); | |
let gen = await genCartProductInfos(baseProductHTML, onCart.id, onCart); | |
if( cart.children.length-1 == cartCounter){ | |
for(l = 0; l <= cartCounter-1; ++l){ | |
quantityContainer[l].addEventListener('input', changeQuantity); | |
supProduct[l].addEventListener('click', cartSuppression) | |
} | |
} | |
} | |
*/ | |
} | |
catch (error) { | |
console.error("erreur dans l'initialisation du panier: " + error); | |
alert("erreur dans l'initialisation du panier:" + error); | |
return; | |
} | |
} | |
/** | |
* récupération des informations d'un produit | |
* @param {*} elementHTML | |
* @param {*} id | |
* @param {*} oneProductOnCartInfo | |
* @returns | |
*/ | |
async function genCartProductInfos(elementHTML, id, oneProductOnCartInfo) { //appel l'ensembles des autres fonctions de génération du html | |
try { | |
const data = await getProductAPIInfo(id); | |
const genProduct = await genProductHTML(elementHTML,data, oneProductOnCartInfo); | |
const genQuantitySelection = await genProductSelectQuantity(oneProductOnCartInfo); | |
const genPrice = await genCartFinalPrice(data, oneProductOnCartInfo); | |
} | |
catch (error) { | |
console.error("erreur dans les compilations des informations de génération du panier: " + error); | |
alert("erreur dans les compilations des informations de génération du panier: " + error); | |
return; | |
} | |
} | |
/** | |
* Récuperrer les informations d'un produit | |
* @param {*} id | |
* @returns | |
*/ | |
async function getProductAPIInfo(id) { // récupération des informations d'un produit fournis pas l'API. | |
try { | |
const url = "http://localhost:3000/api/cameras/" + id; | |
const response = await fetch(url); | |
const data = await response.json(); | |
return data; | |
} catch (error) { | |
console.error("erreur de connexion à l'api : " + error); | |
alert("erreur de connexion à l'api : " + error); | |
return; | |
} | |
} | |
/** | |
* Construction de l'html d'un produit | |
* @param {*} elementHTML | |
* @param {*} data | |
* @param {*} oneProductOnCartInfo | |
* @returns | |
*/ | |
async function genProductHTML(elementHTML, data, oneProductOnCartInfo){ //création de l'element qui contiendra le html du produit dans le panier. | |
try{ | |
const productHTMLElement = elementHTML; | |
//ajout des element crée dans la balise de section du HTML | |
if (productHTMLElement.innerHTML.length == 0){ | |
cart.appendChild(productHTMLElement); | |
} | |
//création de l'affichage (HTML) des différents produits | |
productHTMLElement.innerHTML = | |
"<div class='container border-bottom mb-3 pb-3'>" + | |
" <div class='row'>" + | |
" <a class='product-image col' href='product.html?id=" + oneProductOnCartInfo.id + "'>" + | |
" <img class='img-fluid' src='" + data.imageUrl + "' alt=''>" + | |
" </a>" + | |
" <div class='product-description col fs-5'>" + | |
" <a class='link-warning text-decoration-none' href='product.html?id=" + oneProductOnCartInfo.id + "'>" + | |
" <h2 class='mb-4'>" + data.name + "</h2>" + | |
" </a>" + | |
" <span class='lens'>Lentille : <strong>" + oneProductOnCartInfo.spe + "</strong></span><br>"+ | |
" <div class='quantity mt-3'> Quantité : </div> " + | |
" </div>" + | |
" <div class='container col row'>" + | |
" <div class='product-price col fs-4 text-end'>" + | |
" <strong class='fs-4'>" + (data.price/100)*Number(oneProductOnCartInfo.num) + "€</strong><br>" + | |
" <span class='fst-italic fs-5'>" + (data.price/100) + "€/unité</span><br>" + | |
" </div>" + | |
" <div class='container d-flex justify-content-end align-items-end'>" + | |
" <div class='border trash py-2 px-2' id='trash-btn-"+oneProductOnCartInfo.id+"__"+oneProductOnCartInfo.spe+"'>"+ | |
" <input type='hidden' value='trash-hdn-spe-"+oneProductOnCartInfo.spe+"'"+ | |
" <div class='fas fa-trash fa-2x'></div>"+ | |
" </div>" + | |
" </div>" + | |
" </div>" + | |
" </div>"+ | |
"</div>"; | |
} | |
catch(error){ | |
console.error("erreur lors de la génération du HTML : " + error); | |
alert("erreur lors de la génération du HTML : " + error); | |
return; | |
} | |
} | |
/** | |
* | |
* @param {*} oneProductOnCartInfo | |
* @returns | |
*/ | |
async function genProductSelectQuantity(oneProductOnCartInfo){ //création de l'élément de selection et d'affichage des quantité des produits | |
try{ | |
const quantitySelectionLabel = document.createElement("label"); | |
if( gap == false){ | |
counter++ | |
quantityContainer[counter].appendChild(quantitySelectionLabel); | |
products.push(oneProductOnCartInfo.id); | |
} | |
else{ | |
quantityContainer[k].appendChild(quantitySelectionLabel); | |
quantityContainer[k].addEventListener('input', changeQuantity); | |
} | |
//balise qui premettra de reselectionné a nouveau un nombre d'objet | |
const quantitySelection = document.createElement("select"); | |
quantitySelection.setAttribute("id", "qte-slct-"+oneProductOnCartInfo.id+"__"+oneProductOnCartInfo.spe) | |
quantitySelectionLabel.appendChild(quantitySelection); | |
if (Number(oneProductOnCartInfo.num) > 9){ | |
for(j=1; j <= Number(oneProductOnCartInfo.num); j++){ incrementeProductSelectOption(quantitySelection, j); } | |
} | |
else{ | |
for(j=1; j<=9; j++){ incrementeProductSelectOption(quantitySelection, j); } | |
} | |
quantitySelection.selectedIndex = Number(oneProductOnCartInfo.num)-1; | |
//ajout de l'ID du produit ajouté au tableau product, nécéssaire a l'appel de l'API de commande. | |
} | |
catch(error){ | |
console.error("erreur dans la génération de la séléction du nombre de produit : " + error); | |
alert("erreur dans la génération de la séléction du nombre de produit : " + error); | |
return; | |
} | |
} | |
/** | |
* | |
* @param {*} quantitySelectHTMLElement | |
* @param {*} num | |
*/ | |
function incrementeProductSelectOption(quantitySelectHTMLElement, num){ //ajoute le nombre d'option nécessaire dans le select des quantité de chaque produit | |
const quantitySelectionOption = document.createElement("option"); | |
quantitySelectionOption.textContent = num; | |
quantitySelectHTMLElement.appendChild(quantitySelectionOption); | |
} | |
/** | |
* | |
* @param {*} data | |
* @param {*} oneProductOnCartInfo | |
* @returns | |
*/ | |
async function genCartFinalPrice(data, oneProductOnCartInfo){ //mes à jour le total de la commande et le html en rapport | |
if(allCartItems.length>0){ | |
emptyCart.style.display = "none"; | |
cartPrice.style.display = "block"; | |
form.style.display = "block"; | |
total = total+(data.price/100)*Number(oneProductOnCartInfo.num); | |
finalPrice.innerHTML = "Sous-total : <strong>" + total + "€ </strong>"; | |
cart.appendChild(finalPrice); | |
}else{ | |
emptyCart.style.display = "block"; | |
cartPrice.style.display = "none"; | |
form.style.display = "none"; | |
} | |
/* | |
// @TODO TO BE DELETED | |
try{ | |
//ajout du prix de l'article au total de la commande | |
total = total+(data.price/100)*Number(oneProductOnCartInfo.num); | |
//permet affichage du prix et de celui de certain élément en fonction de l'état du panier (vide/remplis) | |
if (cart.children.length == cartCounter) { | |
finalPrice.innerHTML = "Sous-total : <strong>" + total + "€ </strong>"; | |
cart.appendChild(finalPrice); | |
form.style.display = "block"; | |
emptyCart.style.display = "none"; | |
cartPrice.style.display = "block"; | |
} | |
} | |
catch(error){ | |
console.error("erreur dans l'écriture du total de la commande : " + error); | |
alert("erreur dans l'écriture du total de la commande : " + error); | |
return; | |
} | |
*/ | |
} | |
initialyse(); | |
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~CHANGEMENT ARTICLE DANS LE PANIER//Supression~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ | |
async function changeQuantity(e){ | |
try{ | |
/* | |
// @TODO TO BE DELETED | |
let changeProductElementHTML = e.composedPath()[6]; | |
changeProductElementHTML.classList.add("change-cart-item"); | |
*/ | |
const changeProductSelect = e.composedPath()[0]; | |
let itemToDelete = e.target.id; | |
itemToDelete = itemToDelete.replace("qte-slct-",""); | |
let itemToDeleteArr = itemToDelete.split("__"); | |
console.log(itemToDeleteArr); | |
if(itemToDeleteArr.length>=2){ | |
for (m = 0; m < allCartItems.length; m++){ | |
onCart = JSON.parse(localStorage.getItem(allCartItems[m])); | |
if(onCart.id == itemToDeleteArr[0] && onCart.spe == itemToDeleteArr[1]){ | |
localStorage.setItem(allCartItems[m], '{"product":"' + onCart.product + '","spe":"' + onCart.spe + '","num":"' + changeProductSelect.value + '","id":"' + onCart.id + '"}'); | |
window.location.href = "panier.html"; | |
} | |
} | |
}else{ | |
// @TODO THROW EXCEPTION | |
} | |
/* | |
// @TODO TO BE DELETED | |
for (k = 0; k <= (cart.children.length-(1)); k++){ | |
if(changeProductElementHTML == cart.children[k]){ | |
const onCartChange = JSON.parse(localStorage.getItem("cart-" + (Number(k)+(1-supCount)))); | |
localStorage.setItem("cart-" + (Number(k)+(1-supCount)), '{"product":"' + onCartChange.product + '","spe":"' + onCartChange.spe + '","num":"' + changeProductSelect.value + '","id":"' + onCartChange.id + '"}'); | |
window.location.href = "panier.html"; | |
const onCartChange2 = JSON.parse(localStorage.getItem("cart-" + (Number(k)+(1-supCount)))); | |
let data = await getProductAPIInfo(onCartChange.id); | |
total = (total - ((data.price/100)*(Number(onCartChange.num))))+((data.price/100)*(Number(onCartChange2.num))); | |
finalPrice.innerHTML = "Sous-total : <strong>" + total + "€ </strong>"; | |
let regenHTML = await genProductHTML(changeProductElementHTML, data, onCartChange2); | |
gap = true; | |
let regenSelectQuantity = await genProductSelectQuantity(onCartChange2); | |
gap = false; | |
} | |
} | |
document.querySelector(".change-cart-item .trash").addEventListener('click', cartSuppression); | |
changeProductElementHTML.classList.remove("change-cart-item"); | |
*/ | |
} | |
catch(err){ | |
console.log(err); | |
} | |
} | |
/** | |
* Suppression d'un article | |
* @param {*} e | |
*/ | |
async function cartSuppression(e){ | |
let onCart; | |
let supButton; | |
let supArticle; | |
let alreadyPass = false; | |
let itemToDelete = e.target.id; | |
itemToDelete = itemToDelete.replace("trash-btn-",""); | |
let itemToDeleteArr = itemToDelete.split("__"); | |
if(itemToDeleteArr.length>=2){ | |
for (m = 0; m < allCartItems.length; m++){ | |
onCart = JSON.parse(localStorage.getItem(allCartItems[m])); | |
console.log(onCart); | |
if(onCart.id == itemToDeleteArr[0] && onCart.spe == itemToDeleteArr[1]){ | |
localStorage.removeItem(allCartItems[m]); | |
window.location.href = "panier.html"; | |
} | |
} | |
}else{ | |
// @TODO THROW EXCEPTION | |
} | |
/* | |
@TO BE DELETED | |
for (m = 0; m <= cartCounter-1; m++){ | |
if ((e.composedPath()[0] == supProduct[m])||(e.composedPath()[1] == supProduct[m])){ | |
if(e.composedPath()[0] == supProduct[m]){ | |
supButton = e.composedPath()[0]; | |
supArticle = e.composedPath()[5]; | |
} | |
else{ | |
supButton = e.composedPath()[1]; | |
supArticle = e.composedPath()[6]; | |
} | |
onCart = JSON.parse(localStorage.getItem("cart-" + (Number(m)+1))) | |
if (m+2 > cartCounter){ | |
localStorage.removeItem("cart-" + ((m)+1)); | |
} | |
else{ | |
for(n = m+2; n <= (cartCounter); n++){ | |
console.log(n); | |
let itemAfter = localStorage.getItem("cart-" + (n)); | |
console.log(itemAfter) | |
localStorage.setItem("cart-" + (n-1), itemAfter); | |
localStorage.removeItem("cart-" + (n)); | |
} | |
} | |
cartCounter--; | |
localStorage.setItem("cart-counter", actualCart); | |
} | |
if(supArticle != undefined){ | |
supArticle.style.display = "none"; | |
supButton.classList.remove('trash'); | |
if(alreadyPass == false){ | |
alreadyPass = true; | |
let data = await getProductAPIInfo(onCart.id); | |
total = total - ((data.price/100)*Number(onCart.num)); | |
console.log((data.price/100)*Number(onCart.num)); | |
supCount++; | |
} | |
finalPrice.innerHTML = "Sous-total : <strong>" + total + "€ </strong>"; | |
} | |
} | |
if(actualCart == 0){ | |
form.style.display = "none"; | |
emptyCart.style.display = "block"; | |
finalPrice.style.display = "none"; | |
cartPrice.style.display = "none"; | |
} | |
*/ | |
} | |
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~FORMULAIRE DE COMMANDE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ | |
//le formulaire de contact | |
const form = document.getElementById("form"); | |
//les différents inputs du formulaire de contact | |
const lastName = document.getElementById("lastname"); | |
const firstName = document.getElementById("firstname"); | |
const address = document.getElementById("address"); | |
const city = document.getElementById("city"); | |
const zip = document.getElementById("zip"); | |
const email = document.getElementById("email"); | |
//les différentes REGEX permettant d'avoir des informations aux bon format dans le formulaire. | |
const regexText = /^[a-zÀ-ú]{2}[a-zÀ-ú\s\-]*$/i; | |
const regexPostalcode = /^\d{5}$/; | |
const regexAddress = /^[a-z0-9\s,]{8,}$/i; | |
const regexMail = /^[a-z0-9\._-]+@[a-z0-9\._-]+\.[a-z]{2,6}$/i; | |
//les différents événements lié aux champs des inputs | |
lastName.addEventListener( 'change', formChangementText); | |
firstName.addEventListener( 'change', formChangementText); | |
city.addEventListener( 'change', formChangementText); | |
address.addEventListener( 'change', formChangementAddress); | |
zip.addEventListener( 'change', formChangementPostalCode); | |
email.addEventListener( 'change', formChangementMail); | |
//fonction permettant feed-back a l'utilisateur sur sa completion des champs des différents inputs | |
function goodText(){ | |
event.target.nextElementSibling.innerHTML = "<span style='font-size:20px;'>✅</span>"} | |
function badText(){ event.target.nextElementSibling.innerHTML = "<span style='font-size:20px;'>❌</span>"} | |
//les différentes fonctions lié aux feed back de la correcte completion des inputs | |
function formChangementText(event){ | |
const result = event.target.value; | |
if(regexText.test(result)) {goodText();} | |
else {badText();}; | |
} | |
function formChangementAddress(event){ | |
const result = event.target.value; | |
if(regexAddress.test(result)) {goodText();} | |
else{badText();}; | |
} | |
function formChangementPostalCode(event){ | |
const result = event.target.value; | |
if(regexPostalcode.test(result)) {goodText();} | |
else {badText();}; | |
} | |
function formChangementMail(event){ | |
const result = event.target.value; | |
if(regexMail.test(result)) {goodText();} | |
else {badText();}; | |
} | |
//événement lié au bouton commande du formulaire. | |
form.addEventListener("submit", sendCommand); | |
function sendCommand(event){ | |
//empeche l'envoi normal du formulaire au back-end | |
event.preventDefault(); | |
//vérifie si les champs des inputs sont correctement remplie | |
if(regexText.test(lastName.value) && regexText.test(firstName.value) && | |
regexAddress.test(address.value) && regexPostalcode.test(zip.value) && | |
regexText.test(city.value) && regexMail.test(email.value)){ | |
//les deux constantes suivante permettent de crée un tableau avec les différentes valeurs contenue dans les inputs du formulaires | |
const formData = new FormData(form); | |
const constructContact = Array.from(formData); | |
//la boucle suivante permet d'ajouter à l'objet contact les informations contenue dans le formulaire | |
for (i = 0; i <= 5; i++ ){ | |
if (i != 4){ | |
contact[constructContact[i][0]] = constructContact[i][1]; | |
} | |
//ajoute le code postale au city dans l'objet contact | |
else{ | |
contact[constructContact[i-1][0]] += " " + constructContact[i][1]; | |
} | |
} | |
//constante contenant le header du fetch d'appel a l'API suivante | |
const options = { | |
method: "POST", | |
body: JSON.stringify({contact, products}), | |
headers: { "Content-Type": "application/json" }, | |
}; | |
//appel a l'API | |
fetch("http://localhost:3000/api/cameras/order", options) | |
.then((res) => res.json()) | |
.then((order) => { | |
//vide le localStorage pour pouvoir réaliser une nouvelle commande. | |
localStorage.clear(); | |
//Ajoute les infos à afficher sur la page de confirmation de commande. | |
localStorage.setItem("order", order.orderId); | |
localStorage.setItem("name", order.contact.firstName); | |
localStorage.setItem("commandPrice", total) | |
//redirige l'utilisateur vers la page de finalisation de sa commande. | |
window.location.replace("commande.html"); | |
}) | |
.catch((err) => { | |
alert("Il y a eu une erreur : " + err); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment