From 2b54da80b1c70847dd46e325ae924fe35124835a Mon Sep 17 00:00:00 2001 From: Manuel Thalmann Date: Fri, 1 Mar 2024 19:48:46 +0100 Subject: [PATCH] Create a draft search app --- Tasks/Task 01/movieSearch/index.html | 34 ++++++++ Tasks/Task 01/movieSearch/main.js | 116 +++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 Tasks/Task 01/movieSearch/index.html create mode 100644 Tasks/Task 01/movieSearch/main.js diff --git a/Tasks/Task 01/movieSearch/index.html b/Tasks/Task 01/movieSearch/index.html new file mode 100644 index 0000000..9199687 --- /dev/null +++ b/Tasks/Task 01/movieSearch/index.html @@ -0,0 +1,34 @@ + + + + Movie Search + + + +
+

Movie Search

+
+
+ + +
+
+ + + + + + + + + + + + +
#PosterNameRatingDescription
+
+ + + + + \ No newline at end of file diff --git a/Tasks/Task 01/movieSearch/main.js b/Tasks/Task 01/movieSearch/main.js new file mode 100644 index 0000000..511f1a7 --- /dev/null +++ b/Tasks/Task 01/movieSearch/main.js @@ -0,0 +1,116 @@ +const maxRating = 10; + +window.addEventListener( + "load", + (e) => { + let config; + /** + * @type {HTMLTableElement} + */ + let table = document.querySelector("table#output"); + let form = document.getElementById("movieSearch"); + let textInput = form.querySelector("input"); + table.hidden = true; + + form.addEventListener( + "submit", + async (e) => { + e.preventDefault(); + table.hidden = true; + config ??= await queryTMDb("configuration"); + + while (table.tBodies.length > 0) { + table.removeChild(table.tBodies[0]); + } + + let result = await queryTMDb( + "search/movie", + { + include_adult: true, + language: "en-US", + query: textInput.value + }); + + let tBody = table.createTBody(); + tBody.classList.add("align-middle"); + + for (let i = 0; i < result.results.length; i++) { + let movie = result.results[i]; + let row = tBody.insertRow(); + let title = document.createElement("a"); + let poster = document.createElement("img"); + + title.href = `${new URL(`${movie.id}`, "https://themoviedb.org/movie/")}`; + title.classList.add("link-body-emphasis"); + title.target = "_blank"; + title.innerText = movie.title; + + poster.src = new URL( + `./${movie.poster_path}`, + new URL( + `${config.images.poster_sizes[0]}/`, + config.images.secure_base_url).toString()).toString(); + + row.insertCell().innerText = `#${i + 1}`; + row.insertCell().appendChild(poster); + row.insertCell().appendChild(title); + row.insertCell().appendChild(createRating(movie.vote_average)); + row.insertCell().innerText = movie.overview; + } + + table.hidden = false; + console.log(config); + console.log(result); + }); + }); + +/** + * Queries an endpoint of the TMDb API. + * + * @param {string} endpoint + * @param {Record} params + * The parameters to send to the API. + */ +async function queryTMDb(endpoint, params) { + let url = new URL(endpoint, "https://api.themoviedb.org/3/"); + + for (let param in params) { + url.searchParams.append(param, `${params[param]}`); + } + + return ( + await fetch( + `${url}`, + { + headers: { + Accept: "application/json" + } + })).json(); +} + +function createRating(rating) { + let progressBar = document.createElement("div"); + let indicator = progressBar.appendChild(document.createElement("div")); + let rounded = Math.round(rating * 10) / 10; + + progressBar.style.minWidth = "10rem"; + progressBar.classList.add("progress"); + + for ( + let attribute of + [ + ["role", "progressbar"], + ["aria-label", "Rating"], + ["aria-valuenow", `${rating}`], + ["aria-valuemin", `${0}`], + ["aria-valuemax", `${maxRating}`] + ]) + { + progressBar.setAttribute(attribute[0], attribute[1]); + } + + indicator.classList.add("progress-bar", "text-bg-warning", "overflow-visible"); + indicator.style.width = `${rating * 10}%`; + indicator.textContent = `${rounded}/${maxRating}`; + return progressBar; +} \ No newline at end of file