Spaces:
No application file
No application file
File size: 1,761 Bytes
0d237e6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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 | export {};
interface SubmitDownloadResponse {
job?: { id: string };
error?: string;
}
const form = document.getElementById("submitForm") as HTMLFormElement | null;
const titleInput = document.getElementById("titleInput") as HTMLInputElement | null;
const urlInput = document.getElementById("urlInput") as HTMLInputElement | null;
const errorEl = document.getElementById("formError") as HTMLElement | null;
function showError(message: string): void {
if (!errorEl) return;
errorEl.textContent = message;
errorEl.hidden = false;
}
function clearError(): void {
if (!errorEl) return;
errorEl.hidden = true;
errorEl.textContent = "";
}
form?.addEventListener("submit", async (e: Event) => {
e.preventDefault();
clearError();
const title = titleInput?.value.trim() || "";
const url = urlInput?.value.trim() || "";
if (!title || !url) {
showError("Both a title and a source link are needed.");
return;
}
const submitBtn = form.querySelector<HTMLButtonElement>("button[type=submit]");
if (submitBtn) submitBtn.disabled = true;
try {
const res = await fetch("/api/downloads", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title, url }),
});
const data = (await res.json()) as SubmitDownloadResponse;
if (!res.ok) {
showError(data.error || "The booth couldn't take that link.");
return;
}
form.reset();
// job-feed.ts listens on /api/events and will render the new job as soon
// as the server emits it — no need to duplicate that rendering here.
} catch {
showError("Couldn't reach the booth. Check your connection and try again.");
} finally {
if (submitBtn) submitBtn.disabled = false;
}
});
|