187 lines
5.3 KiB
TypeScript
187 lines
5.3 KiB
TypeScript
import { Handlers, PageProps } from "$fresh/server.ts";
|
|
import { Head } from "$fresh/runtime.ts";
|
|
|
|
interface FormState {
|
|
name?: string;
|
|
email?: string;
|
|
message?: string;
|
|
errors?: {
|
|
name?: string;
|
|
email?: string;
|
|
message?: string;
|
|
};
|
|
submitted?: boolean;
|
|
failed?: boolean;
|
|
}
|
|
|
|
export const handler: Handlers = {
|
|
GET(_, ctx) {
|
|
return ctx.render({});
|
|
},
|
|
async POST(req, ctx) {
|
|
const formData = await req.formData();
|
|
const state: FormState = {
|
|
name: formData.get("name")?.toString(),
|
|
email: formData.get("email")?.toString(),
|
|
message: formData.get("message")?.toString(),
|
|
};
|
|
|
|
// Validation logic
|
|
const errors: FormState["errors"] = {};
|
|
|
|
if (!state.name || state.name.trim() === "") {
|
|
errors.name = "Name is required";
|
|
}
|
|
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
if (!state.email) {
|
|
errors.email = "Email is required";
|
|
} else if (!emailRegex.test(state.email)) {
|
|
errors.email = "Invalid email format";
|
|
}
|
|
|
|
if (!state.message || state.message.trim() === "") {
|
|
errors.message = "Message is required";
|
|
}
|
|
|
|
// If there are errors, return the form with error messages
|
|
if (Object.keys(errors).length > 0) {
|
|
return ctx.render({
|
|
...state,
|
|
errors,
|
|
});
|
|
}
|
|
|
|
const res = await fetch(`${Deno.env.get("EMAIL_FORM")}`, {
|
|
method: "POST",
|
|
body: formData,
|
|
});
|
|
console.log(res);
|
|
|
|
if (!res.ok || res.status !== 200) {
|
|
return ctx.render({
|
|
...state,
|
|
failed: true,
|
|
});
|
|
}
|
|
|
|
return ctx.render({
|
|
...state,
|
|
submitted: true,
|
|
});
|
|
},
|
|
};
|
|
|
|
export default function Contact({ data }: PageProps<FormState>) {
|
|
return (
|
|
<div class="bg-[#313244] min-h-screen">
|
|
<div class="px-4 py-8 mx-auto p-6 flex flex-col bg-[#313244] min-h-screen w-full md:max-w-md">
|
|
<Head>
|
|
<title>Contact</title>
|
|
</Head>
|
|
<h1 class="text-3xl text-white font-bold uppercase text-center">
|
|
Contact
|
|
</h1>
|
|
{data?.submitted && (
|
|
<div
|
|
class="bg-[#a6e3a1] text-[#313244] px-4 py-3 rounded relative"
|
|
role="alert"
|
|
>
|
|
Your message has been sent successfully!
|
|
</div>
|
|
)}
|
|
{data?.failed && (
|
|
<div
|
|
class="bg-[#f38ba8] text-[#313245] px-4 py-3 rounded relative"
|
|
role="alert"
|
|
>
|
|
There has been a error in sending your message. Please try again
|
|
later.
|
|
</div>
|
|
)}
|
|
<form method="POST" class="space-y-4">
|
|
<div>
|
|
<label
|
|
htmlFor="name"
|
|
class="block text-[#cdd6f4] text-sm font-bold mb-2"
|
|
>
|
|
Name
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="name"
|
|
name="name"
|
|
required
|
|
placeholder="Your Name"
|
|
value={data?.name || ""}
|
|
class={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
${data?.errors?.name ? "border-[#f38ba8]" : "border-[#313244]"}`}
|
|
/>
|
|
{data?.errors?.name && (
|
|
<p class="text-[#f38ba8] text-xs italic mt-1">
|
|
{data.errors.name}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div>
|
|
<label
|
|
htmlFor="email"
|
|
class="block text-[#cdd6f4] text-sm font-bold mb-2"
|
|
>
|
|
Email
|
|
</label>
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
name="email"
|
|
required
|
|
placeholder="your@email.com"
|
|
value={data?.email || ""}
|
|
class={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
${data?.errors?.email ? "border-[#f38ba8]" : "border-[#313244]"}`}
|
|
/>
|
|
{data?.errors?.email && (
|
|
<p class="text-red-500 text-xs italic mt-1">
|
|
{data.errors.email}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div>
|
|
<label
|
|
htmlFor="message"
|
|
class="block text-[#cdd6f4] text-sm font-bold mb-2"
|
|
>
|
|
Message
|
|
</label>
|
|
<textarea
|
|
id="message"
|
|
name="message"
|
|
required
|
|
placeholder="Write your message here..."
|
|
rows={4}
|
|
class={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
${data?.errors?.message ? "border-red-500" : "border-gray-300"}`}
|
|
>
|
|
{data?.message || ""}
|
|
</textarea>
|
|
{data?.errors?.message && (
|
|
<p class="text-[#f38ba8] text-xs italic mt-1">
|
|
{data.errors.message}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<input type="hidden" name="_gotcha" style="display:none !important" />
|
|
<div>
|
|
<button
|
|
type="submit"
|
|
class="w-full bg-[#89b4fa] text-[#313244] py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
>
|
|
Send Message
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|