I'm working on a shopping cart functionality for a fictitious online store. The core of this functionality is a Cart
class that manages the information and performs calculations. This class doesn't interact with the HTML document or the DOM, it simply performs calculations.
The Cart
class haves methods to manage products. Each product has a SKU, title, price properties and I'm trying to add a quantity property too but it's not working I think. I have two buttons, addButton
and subtractButton
, for each product to increase or decrease the quantity.
I want to achieve the following:
- When the
addButton
is clicked, the quantity of the product should increase by 1, and the total price for that SKU should be updated in thetotal-SKU
span. - When the
subtractButton
is clicked, the quantity of the product should decrease by 1 (if it's greater than 0), and the total price for that SKU should be updated in thetotal-SKU
span. - The total price of all SKUs should be calculated and displayed in the
total
div.
Here's the code in jsFiddle: https://jsfiddle.net/mlpz2/edfjLhb2
Here's the code here:
class Cart {
constructor(products, currency) {
this.products = [];
this.currency = "";
}
initializeQuantity = () => {
for (let product of this.products) {
product.quantity = 0; // Initialize quantity to 0 for each product
}
console.log(this.products.quantity);
};
updateUnits = (sku, units) => {
// Update the number of units to be purchased for a product
let product = this.products.find((p) => p.sku === sku);
if (product) {
product.quantity = units;
console.log(this.products.quantity);
} else {
this.products.push({ sku: sku, quantity: units });
}
};
getProductInformation = (sku) => {
// Returns the data of a product along with the selected units
// For example:
// {
// "sku": "0K3QOSOV4V",
// "quantity": 3
// }
return this.products.find((p) => p.sku === sku);
};
getAllProducts = () => {
return this.products;
};
getCart = () => {
// Returns information about the products added to the cart
// Along with the calculated total of all products
// For example:
// {
// "total": "5820",
// "currency: "€",
// "products" : [
// {
// "sku": "0K3QOSOV4V"
// ..
// }
// ]}
let total = this.products.reduce(
(sum, p) => sum + p.quantity * p.price,
0
);
return { total: total, currency: this.currency, products: this.products };
};
}
let cart = new Cart();
cart.initializeQuantity();
const getProductsData = async () => {
let response = await fetch(
"https://jsonblob.com/api/jsonBlob/1241305513466912768"
);
let data = await response.json();
console.log(data);
return data; // return the full response
};
const showProducts = (products) => {
console.log(products);
let productsContainer = document.getElementById("productsContainer");
for (let product of products) {
let quantity = product.quantity || 0; // Initialize quantity here
let productElement = document.createElement("div");
productElement.innerHTML = `
<h2>${product.title}</h2>
<p>Ref: ${product.SKU}</p>
<p>Price: ${product.price}€/unit</p>
<button class="substractButton">-</button>
<span id="quantity-${product.SKU}">${quantity}</span>
<button class="addButton">+</button>
<p>Total: <span id="total-${product.SKU}">0</span>€</p>
`;
productElement.className = "product";
productsContainer.appendChild(productElement);
let addButtons = productElement.querySelectorAll(".addButton");
for (let i = 0; i < addButtons.length; i++) {
addButtons[i].addEventListener('click', () => updateQuantity(product.SKU, 1));
}
console.log(addButtons);
let subtractButtons = productElement.querySelectorAll(".substractButton");
for (let i = 0; i < subtractButtons.length; i++) {
subtractButtons[i].addEventListener('click', () => updateQuantity(product.SKU, -1));
console.log(typeof subtractButtons[i], subtractButtons[i]);
}
}
console.log(productsContainer);
};
const updateTotal = (sku) => {
let products = cart.getAllProducts(); // Assuming getCart returns an array of products
let total = 0;
console.log(products); // Check if the products are being fetched correctly
for (let product of products) {
total += product.quantity * product.price;
}
document.getElementById('total').textContent = `TOTAL: ${total}`; // Assuming 'total' is the id of the element displaying the total price
};
const updateQuantity = (sku, change) => {
let product = cart.getProductInformation(sku);
if (product) {
product.quantity += change;
if (product.quantity < 0) {
// Ensure the quantity doesn't go below 0
product.quantity = 0;
}
document.getElementById(`quantity-${sku}`).textContent = product.quantity;
document.getElementById(`total-${sku}`).textContent =
product.quantity * product.price;
updateTotal();
}
};
getProductsData().then((data) => {
if (data && data.products) {
cart.products = data.products;
cart.products = data.products.map((product) => {
return {
...product,
price: parseFloat(product.price),
};
}); // assign the currency to the cart object
showProducts(cart.products);
updateTotal();
} else {
console.error("Failed to fetch products");
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="productsContainer">
<div id="total">
<!-- The total will be shown here -->
</div>
</div>
<script src="script.js"></script>
</body>
</html>
#productsContainer {
display: flex;
flex-direction: column;
flex-wrap: wrap;
margin-top: 20px;
position: relative;
}
.product {
width: 200px;
margin: 10px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
text-align: center;
}
#total {
position: absolute;
font-size: 20px;
font-weight: bold;
bottom: -20px;
left: 10px;
background-color: #ececec;
}
@media (min-width: 768px) {
#productsContainer {
flex-direction: row;
}
}
The products are fetched from an API. I'm using jsonblob.com(https://jsonblob.com/api/jsonBlob/1241305513466912768) to create a mock API.
{
"currency": "€",
"products": [
{
"SKU": "0K3QOSOV4V",
"title": "iFhone 13 Pro",
"price": "938.99"
},
{
"SKU": "TGD5XORY1L",
"title": "Cargador",
"price": "49.99"
},
{
"SKU": "IOKW9BQ9F3",
"title": "Funda de piel",
"price": "79.99"
}
]
}
I think I'm not sure how to:
- Create new elements in the DOM for the product list.
- Listen for events to update the number of units for each product.
- Update the total price in the DOM whenever a change is made.
I'm not sure how to create the event listeners for the addButton
and subtractButton
and how to update the quantity and total price in the DOM.
I'm also open to any suggestions for improving the code. Any help would be appreciated!
Thank you for reading :)