svrjs-nextjs-website/components/shared/Newsletter.tsx

147 lines
4.6 KiB
TypeScript
Raw Normal View History

2024-06-15 17:30:51 +02:00
"use client";
2024-08-24 06:28:25 +02:00
import { useRef, useState } from "react";
2024-06-15 18:41:36 +02:00
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import Image from "next/image";
import { Happy_Monkey } from "next/font/google";
2024-08-24 06:28:25 +02:00
import { Mail } from "lucide-react";
2024-08-26 13:11:47 +02:00
import HCaptcha from "@hcaptcha/react-hcaptcha";
2024-06-15 18:41:36 +02:00
const happyMonkey = Happy_Monkey({
2024-08-24 06:28:25 +02:00
preload: true,
weight: "400",
subsets: ["latin"],
2024-06-15 18:41:36 +02:00
});
2024-06-15 17:30:51 +02:00
const Newsletter = () => {
2024-08-24 06:28:25 +02:00
const [submission, setSubmission] = useState<
"idle" | "loading" | "success" | "error"
>("idle");
const [input, setInput] = useState<string>("");
2024-08-26 13:11:47 +02:00
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
const [showCaptcha, setShowCaptcha] = useState<boolean>(false);
const [isSubmitting, setIsSubmitting] = useState<boolean>(false); // Added this line
2024-08-24 06:28:25 +02:00
const buttonRef = useRef<HTMLButtonElement>(null);
2024-08-26 13:11:47 +02:00
const hcaptchaRef = useRef<HCaptcha>(null);
2024-06-15 17:30:51 +02:00
2024-08-26 13:11:47 +02:00
const handleCaptcha = async (token: string) => {
setCaptchaToken(token);
setShowCaptcha(false);
await handleSubmit(token);
};
2024-06-15 18:41:36 +02:00
2024-08-26 13:11:47 +02:00
const handleSubmit = async (token: string | null) => {
if (!input || !token || isSubmitting) return;
2024-08-24 06:28:25 +02:00
2024-08-26 13:11:47 +02:00
setIsSubmitting(true);
2024-08-24 06:28:25 +02:00
setSubmission("loading");
try {
const response = await fetch("/api/subscribe", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
2024-08-26 13:11:47 +02:00
body: JSON.stringify({ email: input, captchaToken: token }),
2024-08-24 06:28:25 +02:00
});
if (response.ok) {
setSubmission("success");
2024-08-26 13:11:47 +02:00
setInput("");
2024-08-24 06:28:25 +02:00
} else {
setSubmission("error");
}
} catch (error) {
console.error("Error subscribing:", error);
setSubmission("error");
2024-08-26 13:11:47 +02:00
} finally {
setIsSubmitting(false);
2024-08-24 06:28:25 +02:00
}
};
2024-08-26 13:11:47 +02:00
const handleSubscribeClick = () => {
if (!input) return;
setShowCaptcha(true);
};
2024-08-24 06:28:25 +02:00
return (
<section id="newsletter">
<hr className="w-11/12 mx-auto" />
<div className="container py-24 md:py-32">
<h3 className="text-center text-4xl md:text-5xl md:pb-2 text-black font-bold dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
Join The Newsletter!
</h3>
<p className="text-lg text-muted-foreground text-center mt-4 md:mt-2 mb-8">
2024-08-26 13:11:47 +02:00
Subscribe to our newsletter for updates. We promise no spam emails
2024-08-24 06:28:25 +02:00
will be sent
</p>
<form
className="relative flex flex-col w-full md:flex-row md:w-6/12 lg:w-4/12 mx-auto gap-4 md:gap-2"
aria-label="Email Information"
2024-08-26 13:11:47 +02:00
onSubmit={(e) => e.preventDefault()}
2024-08-24 06:28:25 +02:00
>
2024-08-26 13:23:41 +02:00
<div className="group flex items-center gap-x-4 pl-4 pr-1 rounded-[9px] bg-accent/80 hover:bg-accent shadow-outline-gray hover:shadow-transparent focus-within:bg-accent focus-within:!shadow-outline-gray-focus transition-all duration-300">
<Mail className="hidden sm:inline w-6 h-6 text-[#4B4C52] group-focus-within:text-secondary-foreground group-hover:text-secondary-foreground transition-colors duration-300" />
2024-08-24 06:28:25 +02:00
<Input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Email address"
required
type="email"
2024-08-26 13:24:27 +02:00
className="flex-1 text-secondary-foreground text-sm sm:text-base outline-none placeholder-[#4B4C52] group-focus-within:placeholder-muted bg-transparent placeholder:transition-colors placeholder:duration-300 border-none"
2024-08-24 06:28:25 +02:00
/>
</div>
2024-08-26 13:11:47 +02:00
<Button
ref={buttonRef}
onClick={handleSubscribeClick}
disabled={submission === "loading" || !input || isSubmitting}
>
2024-08-24 06:28:25 +02:00
Subscribe
</Button>
2024-08-26 13:11:47 +02:00
2024-08-24 06:28:25 +02:00
<div className="pointer-events-none dark:invert -scale-x-100 absolute -bottom-14 right-1/2 md:right-14 inline-flex justify-center items-center gap-1">
<Image
src="/curly-arrow.png"
alt="see here"
width={35}
height={35}
/>
2024-08-26 13:11:47 +02:00
2024-08-24 06:28:25 +02:00
<span
className={`mt-10 font-bold text-black -scale-x-100 text-[15px] ${happyMonkey.className}`}
>
{submission === "idle" && "Subscribe Now"}
{submission === "loading" && (
<p className="text-sm text-center">Subscribing...</p>
)}
{submission === "success" && (
<p className="dark:invert text-sm text-center text-green-500">
🎉 Subscribed successfully...
</p>
)}
{submission === "error" && (
<p className="dark:invert text-sm text-center text-red-500">
😥 Something went wrong...
</p>
)}
</span>
</div>
</form>
2024-08-26 13:11:47 +02:00
{showCaptcha && (
<div className="flex-center relative">
2024-08-26 13:11:47 +02:00
<HCaptcha
sitekey={process.env.NEXT_PUBLIC_HCAPTCHA_SITE_KEY!}
onVerify={handleCaptcha}
ref={hcaptchaRef}
/>
</div>
)}
2024-08-24 06:28:25 +02:00
</div>
<hr className="w-11/12 mx-auto" />
</section>
);
2024-06-15 17:30:51 +02:00
};
export default Newsletter;