megacommit

This commit is contained in:
Didier Slof 2023-02-02 08:17:38 +01:00
parent 2451ab45cb
commit 34ed81516b
Signed by: didier
GPG key ID: 01E71F18AA4398E5
51 changed files with 1200 additions and 251 deletions

24
public/js/freq.js Normal file
View file

@ -0,0 +1,24 @@
class FreqManager {
#store;
static getInstance() {
if (this._instance === null) {
this._instance = new FreqManager();
}
return this._instance;
}
constructor() {
this.#store = {};
}
set(key, value) {
this.#store[key] = value;
}
get(key) {
return this.#store[key];
}
}
window.freq = FreqManager.getInstance();

106
public/js/order.js Normal file
View file

@ -0,0 +1,106 @@
// DEPENDS ON seat-chooser.js
(async () => {
let scDiv = document.querySelector('#seat-chooser');
let summaryDiv = document.querySelector('#summary-dyn');
let showingId = scDiv.getAttribute('data-showing-id');
let ticketTypes = await (await fetch(`/api/showing/${showingId}/prices`)).json();
let sc = new SeatChooser(
showingId,
scDiv,
(sc, s, add) => {
// seat click callback
// sc is the seat chooser
// s is the seat // but it's better to look at sc.selectedSeats
// add is a boolean indicating whether the seat is being added or removed
// update the summary
summaryDiv.innerHTML = '';
sc.selectedSeats.forEach((seat, index) => {
// set seat ticket if ticket is not set
if (!seat.ticket) seat.ticket = ticketTypes[0];
let seatDiv = document.createElement('div');
seatDiv.classList.add('seat');
let ticketSelect = document.createElement('select');
ticketTypes.forEach((ticketType, index) => {
let option = document.createElement('option');
option.value = index;
option.innerText = ticketType.price_type;
ticketSelect.appendChild(option);
});
ticketSelect.classList.add('ticket-select');
ticketSelect.value = ticketTypes.indexOf(seat.ticket);
ticketSelect.addEventListener('change', (e) => {
seat.ticket = ticketTypes[e.target.value];
updateTicket(sc, seat, seatDiv);
updateTotal(sc);
});
seatDiv.appendChild(ticketSelect);
seatDiv.appendChild(document.createTextNode(' '));
let seatSpan = document.createElement('span');
seatSpan.innerText = `Row ${seat.row}, Seat ${seat.col}`;
seatSpan.classList.add('seat-span');
seatDiv.appendChild(seatSpan);
seatDiv.appendChild(document.createTextNode(' '));
let priceSpan = document.createElement('span');
priceSpan.classList.add('price');
seatDiv.appendChild(priceSpan);
summaryDiv.appendChild(seatDiv);
updateTicket(sc, seat, seatDiv);
});
updateTotal(sc);
if (sc.selectedSeats.length == 0) document.querySelector('button#order-button').disabled = true;
else document.querySelector('button#order-button').disabled = false;
}
);
window.freq.set('seat-chooser', sc);
})();
let total = 0;
function updateTicket(sc, seat, seatDiv) {
seatDiv.querySelector('span:last-child').innerText = `${seat.ticket.price}`;
}
function updateTotal(sc) {
total = 0;
sc.selectedSeats.forEach(_seat => {
total += Number(_seat.ticket.price);
});
document.querySelector('#summary-total').innerText = `Total: €${total}`;
}
document.querySelector('button#order-button').addEventListener('click', (e) => {
let seats = [];
window.sc.selectedSeats.forEach(seat => {
seats.push({
seat: seat.id,
ticket: seat.ticket.id
});
});
fetch(`/api/order`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
showing: sc.showingId,
seats: seats
})
}).then(res => {
if (res.ok) {
window.location = '/order/complete';
} else {
alert('Error placing order');
}
});
});

View file

@ -26,19 +26,21 @@ class SeatChooser {
status.style.textAlign = 'center';
this.container.appendChild(status);
}
// set the message
this.container.querySelector('#seat-chooser-status-message').innerText = msg;
// set the message if it exists
if (this.container.querySelector('#seat-chooser-status-message'))
this.container.querySelector('#seat-chooser-status-message').innerText = msg;
}
constructor(showingId, container, submitCallback) {
constructor(showingId, container, seatClickCallback = (sc, s) => {}, submitCallback = null) {
this.showingId = showingId; // id of the showing
this.container = container; // the container to render the seat chooser in
this.submitCallback = submitCallback; // callback function to call when the user submits the form
this.setLoadingStatus("Initializing...");
this.seats = []; // array of nulls and Seat objects
this.submitCallback = submitCallback; // callback function to call when the user submits the form
this.seatClickCallback = seatClickCallback; // callback function to call when the user clicks on a seat
this.seats = []; // array of nulls and Seat objects
this.selectedSeats = []; // array of Seat objects
this.init();
@ -171,15 +173,17 @@ class SeatChooser {
});
buttonContainer.appendChild(clearButton);
// submit button
let submitButton = document.createElement('button');
submitButton.classList.add('button');
submitButton.style.margin = '1rem';
submitButton.innerText = 'Submit';
submitButton.addEventListener('click', () => {
this.submitCallback(this);
});
buttonContainer.appendChild(submitButton);
if (this.submitCallback !== null) {
// submit button
let submitButton = document.createElement('button');
submitButton.classList.add('button');
submitButton.style.margin = '1rem';
submitButton.innerText = 'Submit';
submitButton.addEventListener('click', () => {
this.submitCallback(this);
});
buttonContainer.appendChild(submitButton);
}
this.container.appendChild(buttonContainer);
}
@ -209,6 +213,7 @@ class SeatChooser {
this.selectedSeats.push(seat);
}
}
this.seatClickCallback(this, seat, this.selectedSeats.includes(seat));
}
clearSelection() {
@ -219,21 +224,3 @@ class SeatChooser {
this.selectedSeats = [];
}
}
let seatChooser = new SeatChooser(1, document.getElementById('seat-chooser'), (sc) => {
// gray overlay and show selected seats
let overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100vw';
overlay.style.height = '100vh';
overlay.style.backgroundColor = 'rgba(0,0,0,0.5)';
overlay.style.display = 'flex';
overlay.style.justifyContent = 'center';
overlay.innerText = 'You selected the following seats: ' + sc.selectedSeats.map(seat => `${seat.row}-${seat.col}`).join(', ');
overlay.addEventListener('click', () => {
overlay.remove();
});
sc.container.appendChild(overlay);
});