├── README.md ├── script.js ├── style.css └── index.html /README.md: -------------------------------------------------------------------------------- 1 | ## Movie Seat Booking 2 | 3 | Display movie choices and seats in a theater to select from in order to purchase tickets 4 | 5 | ## Project Specifications 6 | 7 | - Display UI with movie select, screen, seats, legend & seat info 8 | - User can select a movie/price 9 | - User can select/deselect seats 10 | - User can not select occupied seats 11 | - Number of seats and price will update 12 | - Save seats, movie and price to local storage so that UI is still populated on refresh 13 | 14 | Design inspiration from [Dribbble](https://dribbble.com/shots/3628370-Movie-Seat-Booking) 15 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | const container = document.querySelector(".container"); 2 | const seats = document.querySelectorAll(".row .seat:not(.sold)"); 3 | const count = document.getElementById("count"); 4 | const total = document.getElementById("total"); 5 | const movieSelect = document.getElementById("movie"); 6 | 7 | populateUI(); 8 | 9 | let ticketPrice = +movieSelect.value; 10 | 11 | // Save selected movie index and price 12 | function setMovieData(movieIndex, moviePrice) { 13 | localStorage.setItem("selectedMovieIndex", movieIndex); 14 | localStorage.setItem("selectedMoviePrice", moviePrice); 15 | } 16 | 17 | // Update total and count 18 | function updateSelectedCount() { 19 | const selectedSeats = document.querySelectorAll(".row .seat.selected"); 20 | 21 | const seatsIndex = [...selectedSeats].map((seat) => [...seats].indexOf(seat)); 22 | 23 | localStorage.setItem("selectedSeats", JSON.stringify(seatsIndex)); 24 | 25 | const selectedSeatsCount = selectedSeats.length; 26 | 27 | count.innerText = selectedSeatsCount; 28 | total.innerText = selectedSeatsCount * ticketPrice; 29 | 30 | setMovieData(movieSelect.selectedIndex, movieSelect.value); 31 | } 32 | 33 | 34 | // Get data from localstorage and populate UI 35 | function populateUI() { 36 | const selectedSeats = JSON.parse(localStorage.getItem("selectedSeats")); 37 | 38 | if (selectedSeats !== null && selectedSeats.length > 0) { 39 | seats.forEach((seat, index) => { 40 | if (selectedSeats.indexOf(index) > -1) { 41 | console.log(seat.classList.add("selected")); 42 | } 43 | }); 44 | } 45 | 46 | const selectedMovieIndex = localStorage.getItem("selectedMovieIndex"); 47 | 48 | if (selectedMovieIndex !== null) { 49 | movieSelect.selectedIndex = selectedMovieIndex; 50 | console.log(selectedMovieIndex) 51 | } 52 | } 53 | console.log(populateUI()) 54 | // Movie select event 55 | movieSelect.addEventListener("change", (e) => { 56 | ticketPrice = +e.target.value; 57 | setMovieData(e.target.selectedIndex, e.target.value); 58 | updateSelectedCount(); 59 | }); 60 | 61 | // Seat click event 62 | container.addEventListener("click", (e) => { 63 | if ( 64 | e.target.classList.contains("seat") && 65 | !e.target.classList.contains("sold") 66 | ) { 67 | e.target.classList.toggle("selected"); 68 | 69 | updateSelectedCount(); 70 | } 71 | }); 72 | 73 | // Initial count and total set 74 | updateSelectedCount(); 75 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css?family=Lato&display=swap"); 2 | 3 | * { 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | background-color: #242333; 9 | color: #fff; 10 | display: flex; 11 | flex-direction: column; 12 | align-items: center; 13 | justify-content: center; 14 | height: 100vh; 15 | font-family: "Lato", sans-serif; 16 | margin: 0; 17 | } 18 | 19 | .movie-container { 20 | margin: 20px 0; 21 | } 22 | 23 | .movie-container select { 24 | background-color: #fff; 25 | border: 0; 26 | border-radius: 5px; 27 | font-size: 16px; 28 | margin-left: 10px; 29 | padding: 5px 15px 5px 15px; 30 | -moz-appearance: none; 31 | -webkit-appearance: none; 32 | appearance: none; 33 | } 34 | 35 | .container { 36 | perspective: 1000px; 37 | margin-bottom: 30px; 38 | } 39 | 40 | .seat { 41 | background-color: #444451; 42 | height: 26px; 43 | width: 32px; 44 | margin: 3px; 45 | font-size: 50px; 46 | border-top-left-radius: 10px; 47 | border-top-right-radius: 10px; 48 | } 49 | 50 | .seat.selected { 51 | background-color: green; 52 | } 53 | 54 | .seat.sold { 55 | background-color: #fff; 56 | } 57 | 58 | .seat:nth-of-type(2) { 59 | margin-right: 18px; 60 | } 61 | 62 | .seat:nth-last-of-type(2) { 63 | margin-left: 18px; 64 | } 65 | 66 | .seat:not(.sold):hover { 67 | cursor: pointer; 68 | transform: scale(1.2); 69 | } 70 | 71 | .showcase .seat:not(.sold):hover { 72 | cursor: default; 73 | transform: scale(1); 74 | } 75 | 76 | .showcase { 77 | background: rgba(0, 0, 0, 0.1); 78 | padding: 5px 10px; 79 | border-radius: 5px; 80 | color: #777; 81 | list-style-type: none; 82 | display: flex; 83 | justify-content: space-between; 84 | } 85 | 86 | .showcase li { 87 | display: flex; 88 | align-items: center; 89 | justify-content: center; 90 | margin: 0 10px; 91 | } 92 | .showcase li small { 93 | margin-left: 2px; 94 | } 95 | 96 | .row { 97 | display: flex; 98 | } 99 | 100 | .screen { 101 | background-color: #fff; 102 | height: 120px; 103 | width: 100%; 104 | margin: 15px 0; 105 | transform: rotateX(-48deg); 106 | box-shadow: 0 3px 10px rgba(255, 255, 255, 0.7); 107 | } 108 | 109 | p.text{ 110 | margin: 5px 0; 111 | } 112 | 113 | p.text span{ 114 | color: rgb(158, 248, 158); 115 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie Seat Booking 9 | 10 | 11 |
12 | 13 | 19 |
20 | 21 | 35 |
36 |
37 | 38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | 101 |

102 | You have selected 0 seat for a price of RS.0 106 |

107 | 108 | 109 | 110 | --------------------------------------------------------------------------------