fix+add: seats + seat-chooser
This commit is contained in:
parent
2c6745e812
commit
b0cc5b5278
31 changed files with 808 additions and 115 deletions
|
@ -171,3 +171,7 @@ tr {
|
|||
.op0 {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.mono {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
|
|
@ -168,3 +168,24 @@ form .form-group button:hover {
|
|||
filter: brightness(1.5);
|
||||
}
|
||||
|
||||
#showings {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#showings .showing {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr 1fr 0.25fr;
|
||||
gap: 0.5rem;
|
||||
margin: 0.5rem 0;
|
||||
padding: 1rem;
|
||||
background: var(--second-bg);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
#showings .showing .actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
@ -1,39 +1,95 @@
|
|||
:root {
|
||||
--spacing: 1rem;
|
||||
}
|
||||
/*
|
||||
* (C) (C) (C) (C) (C)
|
||||
(R) S S S S S
|
||||
(R) S S S S S
|
||||
(R) S S S S S
|
||||
(R) S S S S S
|
||||
...
|
||||
*/
|
||||
|
||||
.seat-chooser {
|
||||
padding: var(--spacing);
|
||||
#seat-chooser {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background: var(--second-bg);
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--cols), 1fr);
|
||||
grid-template-rows: repeat(var(--rows), 1fr);
|
||||
gap: var(--spacing);
|
||||
}
|
||||
|
||||
.seat-chooser .seat {
|
||||
position: relative;
|
||||
background: #5f5;
|
||||
border: 1px solid #ccc;
|
||||
#seat-chooser .row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#seat-chooser .row .seat {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin: 5px;
|
||||
border: 1px solid #000;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.seat-chooser .seat.seat-reserved {
|
||||
background: #f66;
|
||||
#seat-chooser .row .seat.linked-left {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.seat-chooser .seat:hover {
|
||||
background: var(--highlight-bg);
|
||||
#seat-chooser .row .seat.linked-right {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
#seat-chooser .row .no-seat {
|
||||
/* this seat DOES NOT EXISTS it's a filler for layout*/
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
cursor: default;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
#seat-chooser .row .seat.selected {
|
||||
background-color: #55f;
|
||||
}
|
||||
|
||||
#seat-chooser .row .seat.reserved {
|
||||
background-color: #f00;
|
||||
}
|
||||
|
||||
#seat-chooser .row .seat:hover {
|
||||
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;
|
||||
}
|
||||
|
|
129
public/js/seat-chooser.js
Normal file
129
public/js/seat-chooser.js
Normal file
|
@ -0,0 +1,129 @@
|
|||
// this file should contain a class that gets info from /api/showings/{id}
|
||||
// and renders the seat chooser
|
||||
// there may be multiple seats selected at once
|
||||
// the input is a matrix with null OR a seat object
|
||||
|
||||
class Seat {
|
||||
constructor(id, row, col, linked, reserved) {
|
||||
this.id = id; // database id
|
||||
this.row = row;
|
||||
this.col = col;
|
||||
this.linked = linked; // linked seat
|
||||
this.reserved = reserved;
|
||||
}
|
||||
}
|
||||
|
||||
class SeatChooser {
|
||||
constructor(showingId, container) {
|
||||
if (container.innerText === '') {
|
||||
container.innerText = 'Loading...';
|
||||
}
|
||||
this.showingId = showingId; // id of the showing
|
||||
this.container = container; // the container to render the seat chooser in
|
||||
|
||||
this.seats = []; // array of nulls and Seat objects
|
||||
|
||||
this.selectedSeats = []; // array of Seat objects
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
let showingJson = await (await fetch(`/api/showings/${this.showingId}`)).json();
|
||||
let roomMatrix = await (await fetch(`/api/showings/${this.showingId}/seatMatrix`)).json();
|
||||
// Matrix<json | null> -> Matrix<Seat | null>
|
||||
console.log("Matrix<json | null> -> Matrix<Seat | null>");
|
||||
this.seats = roomMatrix.map((row, rowIndex) => {
|
||||
return row.map((seat, colIndex) => {
|
||||
if (seat === null) {
|
||||
return null;
|
||||
}
|
||||
return new Seat(
|
||||
seat['seat_id'],
|
||||
seat['seat_row'],
|
||||
seat['seat_column'],
|
||||
seat['seat_linked_id'],
|
||||
seat['reserved']
|
||||
);
|
||||
});
|
||||
});
|
||||
console.log(this.seats);
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log("rendering");
|
||||
let linkedCache = false;
|
||||
// render the seat chooser
|
||||
this.container.innerHTML = '';
|
||||
// this -> row -> seat
|
||||
this.seats.forEach((row, rowIndex) => {
|
||||
let rowDiv = document.createElement('div');
|
||||
rowDiv.classList.add('row');
|
||||
row.forEach((seat, colIndex) => {
|
||||
let seatDiv = document.createElement('div');
|
||||
if (seat) {
|
||||
seatDiv.classList.add('seat');
|
||||
seatDiv.classList.add(seat.reserved ? 'reserved' : 'available');
|
||||
|
||||
if (seat.linked) {
|
||||
// if cache is false, then this is the first seat in the linked pair
|
||||
if (!linkedCache) {
|
||||
seatDiv.classList.add('linked-left');
|
||||
linkedCache = true;
|
||||
} else {
|
||||
seatDiv.classList.add('linked-right');
|
||||
linkedCache = false;
|
||||
}
|
||||
} else {
|
||||
linkedCache = false;
|
||||
}
|
||||
|
||||
seatDiv.innerText = `${seat.row}-${seat.col}`;
|
||||
|
||||
seatDiv.dataset.id = seat.id;
|
||||
seatDiv.dataset.row = seat.row;
|
||||
seatDiv.dataset.col = seat.col;
|
||||
|
||||
seatDiv.addEventListener('click', (e) => {
|
||||
this.toggleSeat(seat, e);
|
||||
});
|
||||
} else {
|
||||
seatDiv.classList.add('no-seat');
|
||||
}
|
||||
rowDiv.appendChild(seatDiv);
|
||||
});
|
||||
this.container.appendChild(rowDiv);
|
||||
});
|
||||
}
|
||||
|
||||
toggleSeat(seat, e) {
|
||||
// toggle the seat
|
||||
// because of linked seats, we need to toggle both seats
|
||||
if (seat.reserved) return;
|
||||
e.target.classList.toggle('selected');
|
||||
if (seat.linked) {
|
||||
// beware that you can click on the left or right seat
|
||||
// the left seat has class linked-left and the right seat has class linked-right
|
||||
let leftbool = e.target.classList.contains('linked-left');
|
||||
let linkedSeat = this.seats[seat.row - 1][leftbool ? seat.col - 1 : seat.col + 1];
|
||||
if (leftbool) e.target.nextElementSibling.classList.toggle('selected');
|
||||
else e.target.previousElementSibling.classList.toggle('selected');
|
||||
if (this.selectedSeats.includes(linkedSeat)) {
|
||||
this.selectedSeats.splice(this.selectedSeats.indexOf(linkedSeat), 1);
|
||||
this.selectedSeats.splice(this.selectedSeats.indexOf(seat), 1);
|
||||
} else {
|
||||
this.selectedSeats.push(linkedSeat);
|
||||
this.selectedSeats.push(seat);
|
||||
}
|
||||
} else {
|
||||
if (this.selectedSeats.includes(seat)) {
|
||||
this.selectedSeats.splice(this.selectedSeats.indexOf(seat), 1);
|
||||
} else {
|
||||
this.selectedSeats.push(seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let seatChooser = new SeatChooser(1, document.getElementById('seat-chooser'));
|
Loading…
Add table
Add a link
Reference in a new issue