mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2026-06-05 19:15:30 -04:00
refactor: migrate contact form to TanStack Form
- Replace manual state management with @tanstack/react-form - Add proper Field/FieldLabel components for accessibility - Simplify server action (remove useActionState signature) - Remove use-debounce dependency - Update PGP key links and minor styling tweaks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+20
-20
@@ -6,49 +6,49 @@ import { ContactSchema } from "@/lib/schemas/contact";
|
||||
import siteConfig from "@/lib/config/site";
|
||||
import { checkBotId } from "botid/server";
|
||||
|
||||
// Schema and type now imported from shared validation module
|
||||
|
||||
export type ContactState = {
|
||||
export type ContactResult = {
|
||||
success: boolean;
|
||||
message: string;
|
||||
errors?: Record<string, string[]>;
|
||||
};
|
||||
|
||||
export const send = async (state: ContactState, payload: FormData): Promise<ContactState> => {
|
||||
export const sendContactForm = async (formData: FormData): Promise<ContactResult> => {
|
||||
// TODO: remove after debugging why automated spam entries are causing 500 errors
|
||||
console.debug("[server/contact] received payload:", payload);
|
||||
console.debug("[server/contact] received payload:", formData);
|
||||
|
||||
// BotID server-side verification
|
||||
const verification = await checkBotId();
|
||||
if (verification.isBot) {
|
||||
console.warn("[server/contact] botid verification failed:", verification);
|
||||
throw new Error("Bot check failed");
|
||||
return {
|
||||
success: false,
|
||||
message: "Verification failed. Please try again.",
|
||||
};
|
||||
}
|
||||
|
||||
const parsed = ContactSchema.safeParse(Object.fromEntries(formData));
|
||||
|
||||
if (!parsed.success) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Please make sure all fields are filled in correctly.",
|
||||
errors: parsed.error.flatten().fieldErrors,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const data = ContactSchema.safeParse(Object.fromEntries(payload));
|
||||
|
||||
if (!data.success) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Please make sure all fields are filled in.",
|
||||
errors: data.error.flatten().fieldErrors,
|
||||
};
|
||||
}
|
||||
|
||||
if (env.RESEND_FROM_EMAIL === "onboarding@resend.dev") {
|
||||
// https://resend.com/docs/api-reference/emails/send-email
|
||||
console.warn("[server/contact] 'RESEND_FROM_EMAIL' is not set, falling back to onboarding@resend.dev.");
|
||||
}
|
||||
|
||||
// send email
|
||||
const resend = new Resend(env.RESEND_API_KEY);
|
||||
await resend.emails.send({
|
||||
from: `${data.data.name} <${env.RESEND_FROM_EMAIL || "onboarding@resend.dev"}>`,
|
||||
replyTo: `${data.data.name} <${data.data.email}>`,
|
||||
from: `${parsed.data.name} <${env.RESEND_FROM_EMAIL || "onboarding@resend.dev"}>`,
|
||||
replyTo: `${parsed.data.name} <${parsed.data.email}>`,
|
||||
to: [env.RESEND_TO_EMAIL],
|
||||
subject: `[${siteConfig.name}] Contact Form Submission`,
|
||||
text: data.data.message,
|
||||
text: parsed.data.message,
|
||||
});
|
||||
|
||||
return { success: true, message: "Thanks! You should hear from me soon." };
|
||||
|
||||
Reference in New Issue
Block a user