From 9aaf4523102a9d831e037d38543b8e92b998040d Mon Sep 17 00:00:00 2001 From: Dorian Niemiec Date: Thu, 7 Nov 2024 21:54:34 +0100 Subject: [PATCH] feat: add the contact form --- .env.example | 13 ++- app/(root)/contact/layout.jsx | 37 +++++++ app/(root)/contact/page.jsx | 138 ++++++++++++++++++++++++ app/api/contact/route.js | 195 ++++++++++++++++++++++++++++++++++ constants/index.jsx | 34 +++++- package-lock.json | 55 +++++++++- package.json | 5 +- 7 files changed, 473 insertions(+), 4 deletions(-) create mode 100644 app/(root)/contact/layout.jsx create mode 100644 app/(root)/contact/page.jsx create mode 100644 app/api/contact/route.js diff --git a/.env.example b/.env.example index 09e74cc..8b01447 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,12 @@ -NEXT_PUBLIC_WEBSITE_URL= \ No newline at end of file +NEXT_PUBLIC_WEBSITE_URL= + +EMAIL_SERVER= +EMAIL_PORT= +EMAIL_SECURE= +EMAIL_USER= +EMAIL_PASS= +EMAIL_CONTACT_ADDRESS= +EMAIL_CONTACT_DEST= + +NEXT_PUBLIC_HCAPTCHA_SITE_KEY= +HCAPTCHA_SECRET= \ No newline at end of file diff --git a/app/(root)/contact/layout.jsx b/app/(root)/contact/layout.jsx new file mode 100644 index 0000000..dd0c6b7 --- /dev/null +++ b/app/(root)/contact/layout.jsx @@ -0,0 +1,37 @@ +export const metadata = { + title: "Contact Us - MERNMail", + description: + "Have questions about MERNMail? Need technical support? Visit our Contact Us page to find various ways to get in touch with our team, including email, and our official support channel.", + openGraph: { + title: "Contact Us - MERNMail", + description: + "Have questions about MERNMail? Need technical support? Visit our Contact Us page to find various ways to get in touch with our team, including email, and our official support channel.", + url: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/contact`, + type: "website", + images: [ + { + url: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/metadata/mernmail-cover.png`, + width: 2560, + height: 1440, + alt: "Contact Us - MERNMail" + } + ] + }, + twitter: { + card: "summary_large_image", + site: "@MERNMail", + title: "Contact Us - MERNMail", + description: + "Have questions about MERNMail? Need technical support? Visit our Contact Us page to find various ways to get in touch with our team, including email, and our official support channel.", + images: [ + `${process.env.NEXT_PUBLIC_WEBSITE_URL}/metadata/mernmail-cover.png` + ], + creator: "@MERNMail" + } +}; + +const ContactLayout = ({ children }) => { + return <>{children}; +}; + +export default ContactLayout; diff --git a/app/(root)/contact/page.jsx b/app/(root)/contact/page.jsx new file mode 100644 index 0000000..9dfd5b1 --- /dev/null +++ b/app/(root)/contact/page.jsx @@ -0,0 +1,138 @@ +"use client"; + +import HCaptcha from "@hcaptcha/react-hcaptcha"; +import { Send } from "lucide-react"; +import { useRef, useState } from "react"; +import { emails } from "@/constants"; +import { isEmail } from "validator"; +import SocialIcons from "@/components/SocialIcons"; + +function Contact() { + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + const [message, setMessage] = useState(""); + const [status, setStatus] = useState(""); + const [hCaptchaToken, setHCaptchaToken] = useState(null); + const captchaRef = useRef(); + + return ( +
+

+ Contact us +

+
+
{ + e.preventDefault(); + try { + const res = await fetch("/api/contact", { + method: "POST", + body: JSON.stringify({ + captchaToken: hCaptchaToken, + name: name, + email: email, + message: message + }), + headers: { + "Content-Type": "application/json", + Accept: "application/json" + } + }); + + if (res.status == 200) { + setStatus("Your message has been sent."); + } else { + setStatus("Uh oh! Something went wrong."); + } + } catch (error) { + console.error(error); + setStatus("Uh oh! Something went wrong."); + } + setHCaptchaToken(null); + captchaRef.current.resetCaptcha(); + setName(""); + setEmail(""); + setMessage(""); + }} + > + + { + setName(e.target.value); + }} + value={name} + id="contact-name" + className="block mb-4 bg-accent text-accent-foreground w-full rounded-md px-2 py-1 focus:outline focus:outline-2 focus:outline-primary" + /> + + { + setEmail(e.target.value); + }} + value={email} + id="contact-email" + className="block mb-4 bg-accent text-accent-foreground w-full rounded-md px-2 py-1 focus:outline focus:outline-2 focus:outline-primary" + /> + +