On this page you can order tickets by clicking on the list items. Clicked items get grouped and then put in an empty container on the page. I added a sample view to clarify what the result should be.
At this point I am stuck. I’m able to insert objects, but I don’t know how to unpack whats inside the object. That should be the tickets one clicked. Hopefully someone here can point me in the right direction to solve this.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Page Title</title>
<style>
/* Styling bullets list items */
li {
list-style: none;
}
li:before {
content: "\1F3B8";
margin-right: 10px;
}
/* Styling for tickets ordered */
#order {
background-color: #b0c4de;
font-size: 120%;
}
.sample {
background-color: #b0c4de;
font-size: 120%;
}
</style>
</head>
<body>
<p>Here you'll find the prices for the tickets:</p>
<ul>
<li onclick="push(tckt1)">Saturday: €110</li>
<li onclick="push(tckt2)">Sunday: €110</li>
<li onclick="push(tckt3)">Monday: €110</li>
<li onclick="push(tckt4)">Weekend: €230</li>
</ul>
<div id="order">
</div>
<br>
// This is a sample of how the output should look.
<div >
Your order:<br>
3 Weekend-tickets à €230 = € 690<br>
1 Sunday-tickets à €110 = € 110<br>
Totaalbedrag: €800 - 10% korting à €80 = €720
</div>
<script>
const order = document.getElementById("order")
let tickets = [];
const tckt1 = {id: 1, name: "Saturday-tickets à €110", price: 110};
const tckt2 = {id: 2, name: "Sunday-tickets à €110", price: 110};
const tckt3 = {id: 3, name: "Monday-tickets à €110", price: 110};
const tckt4 = {id: 4, name: "Weekend-tickets à €230", price: 230};
// Push object in array tickets
function push(temp){
tickets.push(temp);
let res = tickets.reduce(function (x,cur){
let item = cur.id cur.name cur.price
if (!x[item]) x[item] = 0;
x[item] = x[item] 1
return x
}, {})
let results = []
for (const key in res) {
const count = res[key];
const id = key.slice(0, 1)
const day = key.slice(1, 24)
const price = key.slice(24)
results.push({
id: id,
name: day,
price: price,
count: count
})
}
console.log(results)
order.innerHTML =results[0];
}
</script>
</body>
</html>
CodePudding user response:
First: it is generally not a good idea to use inline event handlers. The next snippet uses event delegation to handle the clicks.
Second, i have refactored your code a bit. For identifying the originator of a click, it uses a data-attribute
. After clicking the
accessory ticket definition is pushed to an array (savedTickets
). That array is aggregated to an Object
(orders
) containing the total values, using ticket definitions name property as keys). From that, the result (div#orders
) is filled, using insertAdjacentHTML
. Text is aggregated using template literals
.
Third: I've used dutch language ;)
document.addEventListener(`click`, pushTicketAndShowResult);
const [savedTickets, tickets, discount] = initializeValues();
function pushTicketAndShowResult(evt) {
if (!evt.target.dataset.ticket) {
return;
}
const ticket = tickets[`tckt${evt.target.dataset.ticket}`];
savedTickets.push(ticket);
const orders = savedTickets.reduce((acc, t) => {
acc[t.name] = acc[t.name] || {};
acc[t.name].n = (acc[t.name].n || 0) 1;
acc[t.name].total = acc[t.name].n * t.price;
return acc;
}, {});
const result = document.querySelector(`#orders`);
const total = Object.values(orders).reduce( (acc, o) => acc o.total, 0);
const discountAmount = total * discount/100;
const totalWithDiscount = total - discountAmount;
const yourOrders = Object.entries(orders)
.map( ([name, val]) => `${val.n} ${name} = €${val.total},--`)
.join(`<br>`)
result.textContent = ``;
result.insertAdjacentHTML(`beforeend`, `<b>Uw bestelling</b><br>${
yourOrders}<br>Totaalbedrag: €${total},--<br>Korting ${
discount}% = €${discountAmount},--<br><b>U betaalt €${
totalWithDiscount},--</b>`);
}
function initializeValues() {
return [
[], {
tckt1: {
id: 1,
name: "zaterdag-ticket(s) à €110,--",
price: 110
},
tckt2: {
id: 2,
name: "zondag-ticket(s) à €110,--",
price: 110
},
tckt3: {
id: 3,
name: "maandag-ticket(s) à €110,--",
price: 110
},
tckt4: {
id: 4,
name: "weekend-ticket(s) à €230,--",
price: 230
}
},
10
];
}
body {
font: normal 12px/15px verdana, arial;
}
li {
list-style: none;
cursor: pointer;
}
li:before {
content: "\1F3B8";
margin-right: 10px;
}
#order {
background-color: #b0c4de;
font-size: 120%;
}
.sample {
background-color: #b0c4de;
font-size: 120%;
}
<p>Ticketprijzen. Klik op een prijs om te bestellen:</p>
<ul>
<li data-ticket="1">Zaterdag: €110,--</li>
<li data-ticket="2">Zondag: €110,--</li>
<li data-ticket="3">Maandag: €110,--</li>
<li data-ticket="4">Weekend: €230,--</li>
</ul>
<div id="orders">
</div>