Files
portfolio/src/components/ContactForm.astro
Nathan Cummins 7c8ab1c988
Some checks failed
Build and Deploy to Web Server / deploy (push) Failing after 11m57s
Better handle contact form JS
2025-08-29 12:52:22 +09:30

106 lines
2.8 KiB
Plaintext

---
import { Icon } from "astro-icon/components";
const ID = `contact-form-${Math.random().toString(36)}`;
---
<form
class="mx-auto mt-8 max-w-xl space-y-6 rounded bg-white p-8 shadow-lg dark:bg-gray-900"
id={ID}
>
<div>
<label for="name" class="block font-bold">Name</label>
<input
type="text"
id="name"
name="name"
required
class="mt-2 block w-full rounded p-2 shadow dark:bg-gray-600"
/>
</div>
<div>
<label for="email" class="block font-bold">Your email</label>
<input
type="email"
id="email"
name="email"
required
class="mt-2 block w-full rounded p-2 shadow dark:bg-gray-600"
/>
</div>
<div>
<label for="subject" class="block font-bold">Subject</label>
<input
type="text"
id="subject"
name="subject"
class="mt-2 block w-full rounded p-2 shadow dark:bg-gray-600"
/>
</div>
<div>
<label for="message" class="block font-bold">Message</label>
<textarea
id="message"
name="message"
rows="4"
class="mt-2 block w-full rounded p-2 shadow dark:bg-gray-600"></textarea>
</div>
<button
id="submit"
type="submit"
class="bg-primary text-md font-header hover:text-primary repeat hover:ring-primary mx-auto inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow transition hover:bg-white hover:ring-2"
><Icon
name="mdi:loading"
id="loading-icon"
class="mr-4 hidden animate-spin"
/><span id="response-message" class="inline">Send message</span></button
>
</form>
<script define:vars={{ ID }}>
function init() {
const form = document.getElementById(ID);
const responseMsg = form.querySelector("#response-message");
const button = form.querySelector("#submit");
const loadingIcon = form.querySelector("#loading-icon");
form.addEventListener("submit", async function (event) {
event.preventDefault();
loadingIcon.classList.replace("hidden", "inline");
responseMsg.textContent = "Sending...";
button.disabled = true;
try {
const formData = new FormData(form);
const response = await fetch("/api/email/contact/", {
method: "POST",
body: formData
});
const data = await response.json();
if (response.ok) {
responseMsg.textContent = data.message;
form.reset();
} else {
responseMsg.textContent = data.message;
}
} catch (err) {
responseMsg.textContent =
"An error occurred. Please refresh the page and try again.";
}
loadingIcon.classList.replace("inline", "hidden");
setTimeout(() => {
responseMsg.textContent = "Send message";
button.disabled = false;
}, 10000);
});
}
init();
document.addEventListener("astro:after-swap", init);
</script>