feat: complete node task 2a

This commit is contained in:
Ayobami
2025-07-28 06:42:00 +01:00
parent fe95626d9f
commit bd70df60b9
17 changed files with 1968 additions and 170 deletions
+54 -66
View File
@@ -79,68 +79,6 @@ async function updateClocks() {
updateClocks();
setInterval(updateClocks, 1000);
// --- Airport Autocomplete ---
// const airportInput = document.querySelector('input[placeholder*="airport"]');
// let dropdownDiv;
// if (airportInput) {
// console.log("hi");
// dropdownDiv = document.createElement("div");
// dropdownDiv.className =
// "absolute bg-white border border-gray-300 rounded shadow z-10 w-full max-h-48 overflow-y-auto top-[calc(100%+10px)]";
// dropdownDiv.style.display = "none";
// airportInput.parentNode.appendChild(dropdownDiv);
// airportInput.addEventListener("input", async function () {
// const val = airportInput.value.trim();
// if (val.length < 3) {
// dropdownDiv.style.display = "none";
// return;
// }
// try {
// const res = await fetch(`/airports?search=${encodeURIComponent(val)}`);
// if (!res.ok) throw new Error("Failed to fetch airports");
// const airports = await res.json();
// if (!Array.isArray(airports) || airports.length === 0) {
// dropdownDiv.innerHTML =
// '<div class="p-2 text-gray-500">No results</div>';
// dropdownDiv.style.display = "block";
// return;
// }
// dropdownDiv.innerHTML = airports
// .map(
// (a, i) =>
// `<div class="p-2 hover:bg-sky-100 cursor-pointer" data-index="${i}">${a.name}</div>`
// )
// .join("");
// dropdownDiv.style.display = "block";
// Array.from(dropdownDiv.children).forEach((child, i) => {
// child.addEventListener("click", () => {
// airportInput.value = child.textContent;
// dropdownDiv.style.display = "none";
// selectedAirport = airports[i];
// console.log("hey");
// airportInput.textContent = `hold`;
// if (selectedAirport) {
// console.log(selectedAirport);
// airportInput.value = `${selectedAirport.name} (${selectedAirport.code})`;
// showMap(
// Number(selectedAirport.latitude_deg),
// Number(selectedAirport.longitude_deg)
// );
// }
// });
// });
// } catch (err) {
// dropdownDiv.innerHTML =
// '<div class="p-2 text-red-500">Error loading airports</div>';
// dropdownDiv.style.display = "block";
// }
// });
// // Hide dropdown on blur
// airportInput.addEventListener("blur", () =>
// setTimeout(() => (dropdownDiv.style.display = "none"), 200)
// );
// }
// --- Airport Autocomplete ---
const airportInput = document.querySelector('input[placeholder*="airport"]');
let dropdownDiv;
@@ -163,10 +101,6 @@ if (airportInput) {
selectedAirport = currentAirports[index]; // Use latest fetched data
airportInput.value = `${selectedAirport.name} (${selectedAirport.code})`; // Set once
// showMap(
// Number(selectedAirport.latitude_deg),
// Number(selectedAirport.longitude_deg)
// );
onAirportSelected(selectedAirport);
dropdownDiv.style.display = "none";
});
@@ -307,6 +241,11 @@ function logWidgetClick(widgetName) {
widget_name: widgetName,
browser_type: navigator.userAgent,
}),
}).then(async (res) => {
if (res.status === 429) {
const data = await res.json();
if (data.redirect) window.location.href = data.redirect;
}
});
}
@@ -394,6 +333,55 @@ if (coinInput && coinBtn && coinResult) {
});
}
// --- Upload Widget ---
const uploadInput = document.querySelector(
'input[type="file"][id="upload-input"]'
);
const uploadBtn = document.getElementById("upload-btn");
const uploadPreview = document.getElementById("upload-preview");
const uploadError = document.getElementById("upload-error");
async function fetchLatestUpload() {
try {
const res = await fetch("/upload/latest");
const data = await res.json();
if (data.url && uploadPreview) {
uploadPreview.src = data.url;
uploadPreview.style.display = "";
} else if (uploadPreview) {
uploadPreview.style.display = "none";
}
} catch {}
}
if (uploadBtn && uploadInput) {
uploadBtn.addEventListener("click", async function () {
if (!uploadInput.files || !uploadInput.files[0]) {
if (uploadError) uploadError.textContent = "Please select an image.";
return;
}
const formData = new FormData();
formData.append("image", uploadInput.files[0]);
try {
const res = await fetch("/upload", { method: "POST", body: formData });
const data = await res.json();
if (data.url) {
if (uploadPreview) {
uploadPreview.src = data.url;
uploadPreview.style.display = "";
}
if (uploadError) uploadError.textContent = "";
} else {
if (uploadError)
uploadError.textContent = data.error || "Upload failed.";
}
} catch (err) {
if (uploadError) uploadError.textContent = "Upload failed.";
}
});
}
fetchLatestUpload();
// Attach click listeners to widgets
function attachAnalyticListeners() {
const widgets = [