Files
highland_games_website/app/components/ContactForm.tsx
T
2026-06-22 23:03:02 +02:00

142 lines
4.2 KiB
TypeScript

"use client";
import { useActionState } from "react";
import { useFormStatus } from "react-dom";
import { sendContact, type ContactState } from "@/app/actions/contact";
const initialState: ContactState = { status: "idle", message: "" };
function SubmitButton() {
const { pending } = useFormStatus();
return (
<button
type="submit"
disabled={pending}
className="px-8 py-3 bg-accent text-background font-display tracking-widest text-sm hover:bg-foreground hover:scale-[1.03] transition duration-200 disabled:opacity-60 disabled:cursor-not-allowed disabled:hover:scale-100"
>
{pending ? "SENDING…" : "SEND MESSAGE"}
</button>
);
}
const inputBase =
"w-full bg-surface border px-4 py-3 text-sm text-foreground placeholder:text-foreground-muted focus:outline-none transition-colors";
export function ContactForm() {
const [state, formAction] = useActionState(sendContact, initialState);
if (state.status === "success") {
return (
<div className="border border-accent/40 bg-surface p-8 text-center">
<p className="font-display text-xs tracking-[0.3em] text-accent mb-3">
MESSAGE SENT
</p>
<p className="text-foreground-muted leading-relaxed">{state.message}</p>
</div>
);
}
const err = state.fieldErrors ?? {};
return (
<form action={formAction} className="space-y-5">
<input
type="text"
name="website"
tabIndex={-1}
autoComplete="off"
className="hidden"
aria-hidden
/>
<div className="grid sm:grid-cols-2 gap-5">
<div>
<label
htmlFor="contact-name"
className="block font-display text-xs tracking-[0.3em] text-foreground-muted mb-2"
>
NAME
</label>
<input
id="contact-name"
name="name"
type="text"
required
placeholder="Your name"
className={`${inputBase} ${err.name ? "border-red-400" : "border-border focus:border-accent"}`}
/>
{err.name && (
<p className="text-xs text-red-400 mt-1.5">{err.name}</p>
)}
</div>
<div>
<label
htmlFor="contact-email"
className="block font-display text-xs tracking-[0.3em] text-foreground-muted mb-2"
>
EMAIL
</label>
<input
id="contact-email"
name="email"
type="email"
required
placeholder="you@example.com"
className={`${inputBase} ${err.email ? "border-red-400" : "border-border focus:border-accent"}`}
/>
{err.email && (
<p className="text-xs text-red-400 mt-1.5">{err.email}</p>
)}
</div>
</div>
<div>
<label
htmlFor="contact-subject"
className="block font-display text-xs tracking-[0.3em] text-foreground-muted mb-2"
>
SUBJECT
</label>
<input
id="contact-subject"
name="subject"
type="text"
required
placeholder="What is this about?"
className={`${inputBase} ${err.subject ? "border-red-400" : "border-border focus:border-accent"}`}
/>
{err.subject && (
<p className="text-xs text-red-400 mt-1.5">{err.subject}</p>
)}
</div>
<div>
<label
htmlFor="contact-message"
className="block font-display text-xs tracking-[0.3em] text-foreground-muted mb-2"
>
MESSAGE
</label>
<textarea
id="contact-message"
name="message"
rows={6}
required
placeholder="Your message…"
className={`${inputBase} resize-y ${err.message ? "border-red-400" : "border-border focus:border-accent"}`}
/>
{err.message && (
<p className="text-xs text-red-400 mt-1.5">{err.message}</p>
)}
</div>
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 pt-2">
<SubmitButton />
{state.status === "error" && !Object.keys(err).length && (
<p className="text-sm text-red-400">{state.message}</p>
)}
</div>
</form>
);
}