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 Contact from "#/pages/Contact/Contact.tsx";
|
||||||
|
import { sendToDiscord } from "#/server/contact.ts";
|
||||||
|
|
||||||
const ContactContainer = () => {
|
const ContactContainer = () => {
|
||||||
const handleSubmit = async (_prevState: unknown, data: FormData) => {
|
const handleSubmit = async (_prevState: unknown, data: FormData) => {
|
||||||
const name = data.get("name");
|
const payload = {
|
||||||
const email = data.get("email");
|
name: (data.get("name") as string) || "",
|
||||||
const subject = data.get("subject");
|
email: (data.get("email") as string) || "",
|
||||||
const message = data.get("message");
|
subject: (data.get("subject") as string) || "",
|
||||||
|
message: (data.get("message") as string) || "",
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return { success: true, message: "Message sent!" };
|
await sendToDiscord({ data: payload });
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Message sent successfully!",
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// TODO logger
|
// TODO logger
|
||||||
console.error("Error sending message:", error);
|
console.error("Error sending message:", error);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "Failed to send message. Please try again.",
|
message: "Failed to send message. Please try again.",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useActionState } from "react";
|
import { useActionState } from "react";
|
||||||
import { LuSend } from "react-icons/lu";
|
import { LuSend } from "react-icons/lu";
|
||||||
import Section from "#/components/Section.tsx";
|
import Section from "#/components/Section.tsx";
|
||||||
|
import { useToastStateChange } from "#/hooks/useToastStateChange.ts";
|
||||||
|
|
||||||
interface IFormField {
|
interface IFormField {
|
||||||
fieldName: string;
|
fieldName: string;
|
||||||
@@ -56,6 +57,7 @@ const FormField = ({
|
|||||||
|
|
||||||
const Contact = ({ handleSubmit }: IProps) => {
|
const Contact = ({ handleSubmit }: IProps) => {
|
||||||
const [state, formAction, isPending] = useActionState(handleSubmit, null);
|
const [state, formAction, isPending] = useActionState(handleSubmit, null);
|
||||||
|
useToastStateChange({ state });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="px-4 pb-8 place-self-center min-h-[calc(100vh-226px)]">
|
<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"}
|
{isPending ? "Sending..." : "Send"}
|
||||||
<LuSend className="w-5 h-5" />
|
<LuSend className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
{state && <p>{state.message}</p>}
|
{/*{state && <p>{state.message}</p>}*/}
|
||||||
</form>
|
</form>
|
||||||
</Section>
|
</Section>
|
||||||
</main>
|
</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