122 lines
3.4 KiB
JavaScript
122 lines
3.4 KiB
JavaScript
const form = document.getElementById("quote-form");
|
|
const userSelect = document.getElementById("user-select");
|
|
const quoteText = document.getElementById("quote-text");
|
|
const attachmentInput = document.getElementById("attachment");
|
|
const submitButton = document.getElementById("submit-btn");
|
|
const statusEl = document.getElementById("status");
|
|
const authText = document.getElementById("auth-text");
|
|
const loginLink = document.getElementById("login-link");
|
|
const logoutButton = document.getElementById("logout-btn");
|
|
|
|
function setFormLocked(locked) {
|
|
form.classList.toggle("locked", locked);
|
|
userSelect.disabled = locked;
|
|
quoteText.disabled = locked;
|
|
attachmentInput.disabled = locked;
|
|
submitButton.disabled = locked;
|
|
}
|
|
|
|
function setStatus(message, type = "") {
|
|
statusEl.textContent = message;
|
|
statusEl.className = `status ${type}`.trim();
|
|
}
|
|
|
|
async function loadUsers() {
|
|
const response = await fetch("/api/users");
|
|
const payload = await response.json();
|
|
|
|
userSelect.innerHTML = "";
|
|
const placeholder = document.createElement("option");
|
|
placeholder.value = "";
|
|
placeholder.textContent = "Select a speaker";
|
|
userSelect.appendChild(placeholder);
|
|
|
|
for (const user of payload.users) {
|
|
const option = document.createElement("option");
|
|
option.value = user.id;
|
|
option.textContent = user.displayName;
|
|
userSelect.appendChild(option);
|
|
}
|
|
}
|
|
|
|
async function loadSession() {
|
|
const response = await fetch("/api/session");
|
|
const payload = await response.json();
|
|
|
|
if (!payload.authenticated) {
|
|
authText.textContent = "Please log in with Discord to submit quotes.";
|
|
loginLink.hidden = false;
|
|
logoutButton.hidden = true;
|
|
setFormLocked(true);
|
|
return;
|
|
}
|
|
|
|
const userName = payload.user.globalName || payload.user.username;
|
|
logoutButton.hidden = false;
|
|
loginLink.hidden = true;
|
|
|
|
if (!payload.authorized) {
|
|
authText.textContent = `Logged in as ${userName}, but this account is not allowed to submit.`;
|
|
setFormLocked(true);
|
|
return;
|
|
}
|
|
|
|
authText.textContent = `Logged in as ${userName}. You can submit quotes.`;
|
|
setFormLocked(false);
|
|
}
|
|
|
|
logoutButton.addEventListener("click", async () => {
|
|
await fetch("/auth/logout", { method: "POST" });
|
|
window.location.reload();
|
|
});
|
|
|
|
form.addEventListener("submit", async (event) => {
|
|
event.preventDefault();
|
|
const userId = userSelect.value;
|
|
const quote = quoteText.value.trim();
|
|
const file = attachmentInput.files && attachmentInput.files[0] ? attachmentInput.files[0] : null;
|
|
|
|
if (!userId || !quote) {
|
|
setStatus("Please choose a speaker and enter a quote.", "error");
|
|
return;
|
|
}
|
|
|
|
submitButton.disabled = true;
|
|
setStatus("Sending quote...");
|
|
|
|
try {
|
|
const formData = new FormData();
|
|
formData.append("userId", userId);
|
|
formData.append("quoteText", quote);
|
|
if (file) {
|
|
formData.append("attachment", file);
|
|
}
|
|
|
|
const response = await fetch("/api/quotes", {
|
|
method: "POST",
|
|
body: formData,
|
|
});
|
|
|
|
const payload = await response.json();
|
|
if (!response.ok) {
|
|
throw new Error(payload.error || "Failed to send quote.");
|
|
}
|
|
|
|
quoteText.value = "";
|
|
attachmentInput.value = "";
|
|
setStatus("Quote sent to Discord.", "ok");
|
|
} catch (error) {
|
|
setStatus(error.message || "Something went wrong.", "error");
|
|
} finally {
|
|
submitButton.disabled = false;
|
|
}
|
|
});
|
|
|
|
setFormLocked(true);
|
|
|
|
Promise.all([loadSession(), loadUsers()]).catch((error) => {
|
|
console.error(error);
|
|
setStatus("Failed to initialize page.", "error");
|
|
});
|
|
|