(Feat) Init WebSite
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
"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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user