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

View file

@ -130,6 +130,19 @@ a.button:hover {
color: var(--secondary-color-text);
}
button.button:active,
a.button:active {
background: var(--primary-color);
color: var(--primary-color-text);
}
button.button:disabled,
a.button:disabled {
background: var(--inactive-item-bg);
color: var(--dim-text);
cursor: not-allowed;
}
table {
border-collapse: collapse;
width: 100%;
@ -175,3 +188,14 @@ tr {
.mono {
font-family: monospace;
}
input.text {
/* generic input adjustments */
background: var(--second-bg);
color: var(--default-text);
border: none;
outline: none;
padding: 0.5rem;
border-radius: 0.5rem;
font-size: 1rem;
}

View file

@ -68,9 +68,16 @@ main {
justify-content: flex-end;
align-items: center;
opacity: 0;
padding: 1rem;
max-width: calc(100% - 2rem);
transition: opacity 0.5s;
}
#movies a .details span {
overflow: hidden;
text-overflow: ellipsis;
}
#movies a:hover .details {
opacity: 1;
}

View file

@ -46,22 +46,30 @@ header div a {
color: var(--default-text);
display: block;
margin-top: 0.5rem;
transition: all 0.5s;
}
#sidebar a:hover {
filter: brightness(1.5);
background: var(--second-bg);
color: var(--default-text);
}
#sidebar a.active {
background: var(--highlight-bg);
border-left: 0.5rem solid var(--highlight-bg);
background-color: var(--default-bg);
color: var(--highlight-text);
}
#sidebar a.child {
padding-left: 2rem;
margin-top: 0;
/* nice visual*/
border-left: 1rem solid var(--second-bg);
/* nice visual*/
border-left: 0.5rem solid var(--second-bg);
}
#sidebar a.child.active {
border-left: 1rem solid var(--highlight-bg);
}
main {
@ -135,10 +143,10 @@ main {
margin: 0.5rem 0;
}
form .form-group button,
form .form-group select,
form .form-group textarea,
form .form-group input {
.form .form-group button,
.form .form-group select,
.form .form-group textarea,
.form .form-group input {
padding: 0.5rem;
border-radius: 0.5rem;
background: var(--default-bg);
@ -147,14 +155,14 @@ form .form-group input {
border: none;
}
form .form-group button:hover,
form .form-group select:hover,
form .form-group textarea:hover,
form .form-group input:hover,
form .form-group button:focus,
form .form-group select:focus,
form .form-group textarea:focus,
form .form-group input:focus {
.form .form-group button:hover,
.form .form-group select:hover,
.form .form-group textarea:hover,
.form .form-group input:hover,
.form .form-group button:focus,
.form .form-group select:focus,
.form .form-group textarea:focus,
.form .form-group input:focus {
filter: brightness(1.5);
}
@ -189,3 +197,15 @@ form .form-group button:hover {
justify-content: center;
align-items: center;
}
.warning {
background-color: rgba(255, 0, 0, 0.5);
padding: 1rem;
border-radius: 0.5rem;
margin: 1rem 0;
min-width: 25vw;
}
.warning h3 {
margin: 0;
}

53
public/css/order.css Normal file
View file

@ -0,0 +1,53 @@
body {
/* center with spacing on the left and right*/
margin: 0 auto;
width: 100%;
max-width: 1000px;
padding: 0 20px 3rem;
}
#seat-chooser {
border: 1px solid black;
padding: 2rem;
}
#summary {
background-color: var(--second-bg);
border-radius: 5px;
padding: 1rem;
margin: 1rem 0;
}
#summary-dyn .seat {
background-color: var(--darkest-bg);
color: var(--primary-color-text);
border-radius: 5px;
padding: 0.5rem;
margin: 0.5rem;
}
#summary-dyn .seat select.ticket-select {
background-color: var(--primary-color);
color: var(--primary-color-text);
border: 0;
border-radius: 5px;
padding: 0.5rem;
margin: 0.5rem;
}
#summary-dyn .seat .seat-span {
background-color: var(--primary-color);
color: var(--primary-color-text);
border-radius: 5px;
padding: 0.5rem;
margin: 0.5rem;
}
#summary-dyn .seat .price {
background-color: var(--secondary-color);
color: var(--darkest-bg);
border-radius: 5px;
padding: 0.5rem;
margin: 0.5rem;
float: right;
}

View file

@ -12,8 +12,6 @@
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
--seat-width: 2.5rem;
--seat-height: var(--seat-width);
@ -95,24 +93,7 @@
filter: brightness(0.8);
}
#load-screen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
div.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 2s linear infinite;
#seat-chooser #seat-chooser-status {
text-align: center;
margin: 1rem;
}

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);
});