Pure JavaScript Advanced shopping cart localstorage storage
const openCartBtn = document.querySelector(".open-cart"); | |
const closeCartBtn = document.querySelector(".close-cart"); | |
const clearCartBtn = document.querySelector(".clear-cart"); | |
const cartDOM = document.querySelector(".cart"); | |
const cartOverlay = document.querySelector(".cart-overlay"); | |
const cartItems = document.querySelector(".cart-items"); | |
const cartTotal = document.querySelector(".cart-total"); | |
const checkoutTotal = document.querySelector(".checkout-total"); | |
const itemTotal = document.querySelector(".item-total"); | |
const cartContent = document.querySelector(".cart-content"); | |
const checkoutContent = document.querySelector(".checkout-content"); | |
const placeOrderBtn = document.querySelector(".place-order-btn"); | |
const leaveNote = document.getElementById("leaveNote"); | |
const csrfToken = document.head.querySelector("[name~=csrf-token][content]").content; | |
let cart = []; | |
let buttonsDOM = []; | |
class Products { | |
async getProducts() { | |
try { | |
let result = await fetch('products'); | |
return await result.json(); | |
} | |
catch (error) { | |
console.log(error); | |
} | |
} | |
} | |
class UI { | |
getBagButtons() { | |
let buttons = [...document.querySelectorAll(".bag-btn")]; | |
buttonsDOM = buttons; | |
buttons.forEach(button => { | |
let id = parseInt(button.dataset.id); | |
let inCart = cart.find(item => item.id === id); | |
if (inCart) { | |
button.innerText = "In Cart"; | |
button.disabled = true; | |
} | |
button.addEventListener("click", event => { | |
// disable button | |
event.target.innerText = "In Cart"; | |
event.target.disabled = true; | |
// add to cart | |
let cartItem = { ...Storage.getProduct(id), amount: 1 }; | |
cart = [...cart, cartItem]; | |
Storage.saveCart(cart); | |
// add to DOM | |
this.setCartValues(cart); | |
this.addCartItem(cartItem); | |
this.addCheckoutItem(cartItem); | |
}); | |
}); | |
}; | |
setCartValues(cart) { | |
let tempTotal = 0; | |
let itemsTotal = 0; | |
cart.map(item => { | |
tempTotal += item.price * item.amount; | |
itemsTotal += item.amount; | |
}); | |
cartTotal.innerText = parseFloat(tempTotal.toFixed(2)); | |
cartItems.innerText = itemsTotal; | |
if (itemTotal) { | |
itemTotal.innerText = `(${itemsTotal})`; | |
checkoutTotal.innerText = parseFloat(tempTotal.toFixed(2)); | |
} | |
}; | |
addCartItem(item) { | |
const div = document.createElement("div"); | |
div.classList.add("cart-item"); | |
div.innerHTML = ` | |
<img src="/img/doner.jpg" alt="${item.title}"> | |
<div class="cart-item-info"> | |
<h4>${item.title}</h4> | |
<h5>$${item.price}</h5> | |
<span class="remove-item" data-id="${item.id}">remove</span> | |
</div> | |
<div class="chevrons"> | |
<span class="fas fa-chevron-up" data-id=${item.id}></span> | |
<span class="item-amount">${item.amount}</span> | |
<span class="fas fa-chevron-down" data-id=${item.id}></span> | |
</div> | |
`; | |
cartContent.appendChild(div); | |
}; | |
addCheckoutItem(item) { | |
const div = document.createElement("div"); | |
div.classList.add("checkout-item"); | |
div.innerHTML = ` | |
<div class="checkout-item-row"> | |
<div>${item.title}</div> | |
<div class="price">$${item.price}</div> | |
<div>X ${item.amount}</div> | |
</div> | |
`; | |
if(checkoutContent){ | |
checkoutContent.appendChild(div); | |
} | |
}; | |
showCart() { | |
cartOverlay.classList.add("transparentBcg"); | |
cartDOM.classList.add("showCart"); | |
}; | |
hideCart() { | |
cartOverlay.classList.remove("transparentBcg"); | |
cartDOM.classList.remove("showCart"); | |
}; | |
setupAPP() { | |
cart = Storage.getCart(); | |
this.setCartValues(cart); | |
this.populateCart(cart); | |
this.populateCheckout(cart); | |
openCartBtn.addEventListener("click", this.showCart); | |
closeCartBtn.addEventListener("click", this.hideCart); | |
if(placeOrderBtn) { | |
placeOrderBtn.addEventListener("click", this.placeOrderPost); | |
} | |
}; | |
populateCart(cart) { | |
cart.forEach(item => this.addCartItem(item)); | |
}; | |
populateCheckout(cart) { | |
cart.forEach(item => this.addCheckoutItem(item)); | |
}; | |
cartLogic() { | |
clearCartBtn.addEventListener("click", () => { | |
this.clearCart(); | |
}); | |
cartContent.addEventListener("click", event => { | |
if (event.target.classList.contains("remove-item")) { | |
let removeItem = event.target; | |
let id = parseInt(removeItem.dataset.id); | |
cartContent.removeChild(removeItem.parentElement.parentElement); | |
this.removeItem(id); | |
} else if (event.target.classList.contains("fa-chevron-up")) { | |
let addAmount = event.target; | |
let id = parseInt(addAmount.dataset.id); | |
let tempItem = cart.find(item => item.id === id); | |
tempItem.amount = tempItem.amount + 1; | |
Storage.saveCart(cart); | |
this.setCartValues(cart); | |
addAmount.nextElementSibling.innerText = tempItem.amount; | |
} else if (event.target.classList.contains("fa-chevron-down")) { | |
let lowerAmount = event.target; | |
let id = parseInt(lowerAmount.dataset.id); | |
let tempItem = cart.find(item => item.id === id); | |
tempItem.amount = tempItem.amount - 1; | |
if (tempItem.amount > 0) { | |
Storage.saveCart(cart); | |
this.setCartValues(cart); | |
lowerAmount.previousElementSibling.innerText = tempItem.amount; | |
} else { | |
cartContent.removeChild(lowerAmount.parentElement.parentElement); | |
this.removeItem(id); | |
} | |
} | |
}); | |
}; | |
clearCart(){ | |
let cartItems = cart.map(item => item.id); | |
cartItems.forEach(id => this.removeItem(id)); | |
while (cartContent.children.length > 0) { | |
cartContent.removeChild(cartContent.children[0]); | |
} | |
this.hideCart(); | |
}; | |
removeItem(id) { | |
cart = cart.filter(item => item.id !== parseInt(id)); | |
this.setCartValues(cart); | |
Storage.saveCart(cart); | |
let button = this.getSingleButton(id); | |
if(button) { | |
button.disabled = false; | |
button.innerHTML = `<span class="fas fa-shopping-cart"></span>add to bag`; | |
} | |
}; | |
getSingleButton(id) { | |
return buttonsDOM.find(button => parseInt(button.dataset.id) === id); | |
}; | |
itemListPlainText(cart) { | |
let template = ``; | |
for (let item of cart) { | |
template += `<span>${item.title} - x ${item.amount}</span>`; | |
} | |
return template; | |
}; | |
placeOrderPost() { | |
const order = { | |
user_id: parseInt(document.getElementById("userId").value), | |
item_list: this.itemListPlainText(cart), | |
total: parseFloat(document.querySelector(".checkout-total").innerHTML), | |
leave_note: leaveNote.value | |
}; | |
this.sendData(order); | |
}; | |
sendData(order) { | |
fetch('/orders', { | |
method: 'post', | |
body: JSON.stringify(order), | |
headers: { | |
'Conent-Type': 'application/json', | |
"X-CSRF-Token": csrfToken | |
} | |
}) | |
.then(response => { | |
if(response.status === 200) { | |
const placeOrderBtn = document.querySelector('.place-order-btn'); | |
placeOrderBtn.innerText = "THANK YOU FOR CHOOSING US !"; | |
placeOrderBtn.disabled = true; | |
setTimeout(() => { | |
placeOrderBtn.innerText = "PLACE ORDER"; | |
placeOrderBtn.disabled = false; | |
}, 15000); | |
} | |
return response.json(); | |
}) | |
.then(text => { | |
return console.log(text); | |
}) | |
.catch(error => console.error(error)); | |
} | |
} | |
class Storage { | |
static saveProducts(products) { | |
localStorage.setItem('products', JSON.stringify(products)); | |
} | |
static getProduct(id) { | |
let products = JSON.parse(localStorage.getItem('products')); | |
return products.find(product => product.id === id); | |
} | |
static saveCart(cart) { | |
localStorage.setItem("cart", JSON.stringify(cart)); | |
} | |
static getCart() { | |
return localStorage.getItem("cart") | |
? JSON.parse(localStorage.getItem("cart")) | |
: []; | |
} | |
} | |
document.addEventListener("DOMContentLoaded", () => { | |
const ui = new UI(); | |
const products = new Products(); | |
ui.setupAPP(); | |
products | |
.getProducts() | |
.then(products => { | |
Storage.saveProducts(products); | |
}) | |
.then(() => { | |
ui.getBagButtons(); | |
ui.cartLogic(); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment