summaryrefslogtreecommitdiff
path: root/static/app.js
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2026-05-06 12:21:26 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2026-05-06 12:21:26 -0700
commite708bec6cd76c2686de4158dde4d04f72a3c300d (patch)
tree04b0bc4738e090dd7834d47478c7e652da010f92 /static/app.js
init: lumiere film diary
Diffstat (limited to 'static/app.js')
-rw-r--r--static/app.js131
1 files changed, 131 insertions, 0 deletions
diff --git a/static/app.js b/static/app.js
new file mode 100644
index 0000000..01b1d79
--- /dev/null
+++ b/static/app.js
@@ -0,0 +1,131 @@
+const tmdbQuery = document.querySelector("#tmdb-query");
+const tmdbButton = document.querySelector("#tmdb-search");
+const tmdbResults = document.querySelector("#tmdb-results");
+
+const setValue = (selector, value) => {
+ const element = document.querySelector(selector);
+ if (element && value !== null && value !== undefined) {
+ element.value = value;
+ }
+};
+
+const setPoster = (url) => {
+ setValue("#poster_url", url || "");
+ const preview = document.querySelector("#poster-preview");
+ if (!preview) return;
+
+ if (url) {
+ preview.src = url;
+ preview.classList.add("is-visible");
+ } else {
+ preview.removeAttribute("src");
+ preview.classList.remove("is-visible");
+ }
+};
+
+const clearResults = () => {
+ if (tmdbResults) {
+ tmdbResults.replaceChildren();
+ }
+};
+
+const renderMessage = (message) => {
+ clearResults();
+ const node = document.createElement("p");
+ node.className = "tmdb-message";
+ node.textContent = message;
+ tmdbResults.appendChild(node);
+};
+
+const applyResult = (film) => {
+ setValue("#title", film.title || "");
+ setValue("#original_title", film.original_title || "");
+ setValue("#director", film.director || "");
+ setValue("#year", film.year || "");
+ setValue("#country", film.country || "");
+ setValue("#language", film.language || "");
+ setValue("#runtime", film.runtime || "");
+ setValue("#tmdb_id", film.tmdb_id || "");
+ setPoster(film.poster_url);
+ clearResults();
+};
+
+const renderResults = (films) => {
+ clearResults();
+
+ if (!films.length) {
+ renderMessage("No matches found.");
+ return;
+ }
+
+ films.forEach((film) => {
+ const button = document.createElement("button");
+ button.type = "button";
+ button.className = "tmdb-result";
+ button.addEventListener("click", () => applyResult(film));
+
+ if (film.poster_url) {
+ const image = document.createElement("img");
+ image.src = film.poster_url;
+ image.alt = "";
+ button.appendChild(image);
+ }
+
+ const text = document.createElement("span");
+ const title = document.createElement("strong");
+ title.textContent = film.year ? `${film.title} (${film.year})` : film.title;
+ text.appendChild(title);
+
+ if (film.director) {
+ const director = document.createElement("small");
+ director.textContent = film.director;
+ text.appendChild(director);
+ }
+
+ button.appendChild(text);
+ tmdbResults.appendChild(button);
+ });
+};
+
+const searchTmdb = async () => {
+ if (!tmdbQuery || !tmdbResults) return;
+
+ const query = tmdbQuery.value.trim();
+ if (query.length < 2) {
+ renderMessage("Enter at least two characters.");
+ return;
+ }
+
+ renderMessage("Searching...");
+
+ try {
+ const response = await fetch(`/tmdb/search?q=${encodeURIComponent(query)}`);
+ const data = await response.json();
+ if (!response.ok) {
+ renderMessage(data.error || "Search failed.");
+ return;
+ }
+ renderResults(data.results || []);
+ } catch (error) {
+ renderMessage("Search failed.");
+ }
+};
+
+if (tmdbButton && tmdbQuery) {
+ tmdbButton.addEventListener("click", searchTmdb);
+ tmdbQuery.addEventListener("keydown", (event) => {
+ if (event.key === "Enter") {
+ event.preventDefault();
+ searchTmdb();
+ }
+ });
+}
+
+document.querySelectorAll("form[data-confirm]").forEach((form) => {
+ form.addEventListener("submit", (event) => {
+ const message = form.dataset.confirm;
+ if (message && !window.confirm(message)) {
+ event.preventDefault();
+ }
+ });
+});