87 lines
3.2 KiB
TypeScript
87 lines
3.2 KiB
TypeScript
import { getQuestions, submitQuestion } from "~/lib/api";
|
|
import { frostedBox } from "~/components/frosted-box";
|
|
|
|
function escapeHtml(str: string): string {
|
|
const div = document.createElement("div");
|
|
div.textContent = str;
|
|
return div.innerHTML;
|
|
}
|
|
|
|
export async function qaPage(outlet: HTMLElement) {
|
|
outlet.innerHTML = `
|
|
<div class="flex flex-col items-center justify-start px-4">
|
|
${frostedBox(`
|
|
<form id="qa-form">
|
|
<fieldset class="border-2 border-white px-[calc(1.5ch-0.5px)] pb-[1ch] pt-[1ch]">
|
|
<legend class="-mx-[0.5ch] px-[0.5ch] text-white">Ask a Question</legend>
|
|
<textarea id="qa-input" maxlength="200" rows="3"
|
|
class="qa-textarea"
|
|
placeholder="Type your question..."></textarea>
|
|
<div class="flex justify-between mt-[1ch]">
|
|
<span id="char-count" style="color: var(--dark-gray);">0/200</span>
|
|
<button type="submit" class="qa-button">[SUBMIT]</button>
|
|
</div>
|
|
<p id="qa-status" class="mt-[0.5ch]" aria-live="polite"></p>
|
|
</fieldset>
|
|
</form>
|
|
<div id="qa-list" class="mt-[2ch]">Loading...</div>
|
|
`)}
|
|
</div>`;
|
|
|
|
const form = document.getElementById("qa-form") as HTMLFormElement;
|
|
const input = document.getElementById("qa-input") as HTMLTextAreaElement;
|
|
const charCount = document.getElementById("char-count")!;
|
|
const status = document.getElementById("qa-status")!;
|
|
const list = document.getElementById("qa-list")!;
|
|
|
|
input.addEventListener("input", () => {
|
|
charCount.textContent = `${input.value.length}/200`;
|
|
});
|
|
|
|
form.addEventListener("submit", (e) => {
|
|
e.preventDefault();
|
|
const question = input.value.trim();
|
|
if (!question) return;
|
|
|
|
status.textContent = "Submitting...";
|
|
status.style.color = "var(--light-gray)";
|
|
|
|
submitQuestion(question)
|
|
.then(() => {
|
|
input.value = "";
|
|
charCount.textContent = "0/200";
|
|
status.textContent = "Question submitted! It will appear here once answered.";
|
|
status.style.color = "var(--light-green)";
|
|
})
|
|
.catch((err: unknown) => {
|
|
status.textContent = err instanceof Error ? err.message : "Failed to submit question.";
|
|
status.style.color = "var(--light-red)";
|
|
});
|
|
});
|
|
|
|
try {
|
|
const questions = await getQuestions();
|
|
if (questions.length === 0) {
|
|
list.textContent = "No questions answered yet.";
|
|
list.style.color = "var(--dark-gray)";
|
|
} else {
|
|
list.innerHTML = questions
|
|
.map(
|
|
(q) => `
|
|
<fieldset class="border-2 border-white px-[calc(1.5ch-0.5px)] pb-[1ch] pt-0 mb-[2ch]">
|
|
<legend class="-mx-[0.5ch] px-[0.5ch]" style="color: var(--dark-gray);">#${String(q.id)}</legend>
|
|
<p style="color: var(--light-cyan);">${escapeHtml(q.question)}</p>
|
|
<p class="mt-[1ch]" style="color: var(--light-green);">${escapeHtml(q.answer)}</p>
|
|
<p class="mt-[0.5ch]" style="color: var(--dark-gray);">
|
|
Asked ${q.created_at} · Answered ${q.answered_at}
|
|
</p>
|
|
</fieldset>`,
|
|
)
|
|
.join("");
|
|
}
|
|
} catch {
|
|
list.textContent = "Failed to load questions.";
|
|
list.style.color = "var(--light-red)";
|
|
list.style.textAlign = "center";
|
|
}
|
|
}
|