mirror of
https://github.com/TheRealOwenRees/chess-scribe-website.git
synced 2026-07-23 01:46:57 +00:00
discord server component and toast on state change
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import { useEffect } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
interface IProps {
|
||||
state: {
|
||||
success: boolean;
|
||||
message: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export const useToastStateChange = ({ state }: IProps) => {
|
||||
useEffect(() => {
|
||||
if (!state) return;
|
||||
|
||||
if (state.success) {
|
||||
toast.success(state.message);
|
||||
} else {
|
||||
toast.error(state.message);
|
||||
}
|
||||
}, [state]);
|
||||
};
|
||||
@@ -1,17 +1,26 @@
|
||||
import Contact from "#/pages/Contact/Contact.tsx";
|
||||
import { sendToDiscord } from "#/server/contact.ts";
|
||||
|
||||
const ContactContainer = () => {
|
||||
const handleSubmit = async (_prevState: unknown, data: FormData) => {
|
||||
const name = data.get("name");
|
||||
const email = data.get("email");
|
||||
const subject = data.get("subject");
|
||||
const message = data.get("message");
|
||||
const payload = {
|
||||
name: (data.get("name") as string) || "",
|
||||
email: (data.get("email") as string) || "",
|
||||
subject: (data.get("subject") as string) || "",
|
||||
message: (data.get("message") as string) || "",
|
||||
};
|
||||
|
||||
try {
|
||||
return { success: true, message: "Message sent!" };
|
||||
await sendToDiscord({ data: payload });
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Message sent successfully!",
|
||||
};
|
||||
} catch (error) {
|
||||
// TODO logger
|
||||
console.error("Error sending message:", error);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: "Failed to send message. Please try again.",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useActionState } from "react";
|
||||
import { LuSend } from "react-icons/lu";
|
||||
import Section from "#/components/Section.tsx";
|
||||
import { useToastStateChange } from "#/hooks/useToastStateChange.ts";
|
||||
|
||||
interface IFormField {
|
||||
fieldName: string;
|
||||
@@ -56,6 +57,7 @@ const FormField = ({
|
||||
|
||||
const Contact = ({ handleSubmit }: IProps) => {
|
||||
const [state, formAction, isPending] = useActionState(handleSubmit, null);
|
||||
useToastStateChange({ state });
|
||||
|
||||
return (
|
||||
<main className="px-4 pb-8 place-self-center min-h-[calc(100vh-226px)]">
|
||||
@@ -103,7 +105,7 @@ const Contact = ({ handleSubmit }: IProps) => {
|
||||
{isPending ? "Sending..." : "Send"}
|
||||
<LuSend className="w-5 h-5" />
|
||||
</button>
|
||||
{state && <p>{state.message}</p>}
|
||||
{/*{state && <p>{state.message}</p>}*/}
|
||||
</form>
|
||||
</Section>
|
||||
</main>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { createServerFn } from "@tanstack/react-start";
|
||||
import { env } from "#/env.ts";
|
||||
|
||||
export const sendToDiscord = createServerFn({ method: "POST" })
|
||||
.inputValidator(
|
||||
(data: { name: string; email: string; subject: string; message: string }) =>
|
||||
data,
|
||||
)
|
||||
.handler(async ({ data }) => {
|
||||
const response = await fetch(env.DISCORD_CONTACT_WEBHOOK, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
embeds: [
|
||||
{
|
||||
title: "Contact Form Submission",
|
||||
fields: [
|
||||
{ name: "Name", value: data.name.trim() || "Not provided" },
|
||||
{ name: "Email", value: data.email.trim() || "Not provided" },
|
||||
{ name: "Subject", value: data.subject.trim() || "No Subject" },
|
||||
{
|
||||
name: "Message",
|
||||
value: data.message.trim() || "Empty message",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Discord API rejected the request");
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
});
|
||||
Reference in New Issue
Block a user