Personal Website for @jaspermayone.com jaspermayone.com
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 109 lines 3.4 kB view raw
1"use client"; 2import { emails } from "@/lib/defs"; 3import styles from "@/styles/Misc.module.css"; 4import { useState, type FormEvent } from "react"; 5import { Button } from "./ui/button"; 6import { Input } from "./ui/input"; 7 8// Emails from defs.ts plus any additional aliases not in the main list 9const predefinedEmails = [ 10 ...emails.map((e) => e.address), 11 "jasperphoenixmayone@gmail.com", 12 "jasper.mayone@jaspermayone.com", 13 "jasper.mayone.skiskate@gmail.com", 14]; 15 16export default function Email() { 17 const [email, setEmail] = useState(""); 18 const [submitted, setSubmitted] = useState(false); 19 const [error, setError] = useState<string | null>(null); 20 const [woahThere, setWoahThere] = useState<boolean>(false); 21 const [isLoading, setIsLoading] = useState<boolean>(false); 22 23 async function onSubmit(event: FormEvent<HTMLFormElement>) { 24 event.preventDefault(); 25 setIsLoading(true); 26 setError(null); 27 setWoahThere(false); 28 29 if (predefinedEmails.includes(email)) { 30 setWoahThere(true); 31 setIsLoading(false); 32 return; 33 } 34 35 fetch("/api/email/new", { 36 method: "POST", 37 body: JSON.stringify({ email }), 38 headers: { 39 "Content-Type": "application/json", 40 }, 41 }) 42 .then((res) => res.json()) 43 .then((data) => { 44 if (data.success) { 45 setSubmitted(true); 46 } else { 47 setError("Failed to submit. Please try again."); 48 } 49 }) 50 .catch(() => { 51 setError("An error occurred during submission."); 52 }) 53 .finally(() => { 54 setIsLoading(false); 55 }); 56 } 57 58 const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { 59 setEmail(e.target.value); 60 }; 61 62 return ( 63 <div className="mx-auto w-full max-w-6xl px-4"> 64 {/* h2 with custom .ul class */} 65 <h2 className={styles.lightUl}>Newsletter</h2> 66 <p className="mb-4 text-sm text-gray-700 dark:text-white/70"> 67 Subscribe to my newsletter to get <i>occasioal</i> updates on what 68 I&apos;m up to. 69 </p> 70 71 {!submitted ? ( 72 <form onSubmit={onSubmit} className="w-full"> 73 <div className="flex w-full flex-col gap-3 sm:flex-row"> 74 <Input 75 type="email" 76 placeholder="example@example.com" 77 className="flex-1 border-1 border-gray-300 text-sm outline-none focus:border-blue-400 focus:ring-blue-400" 78 value={email} 79 onChange={handleInputChange} 80 aria-label="email" 81 required 82 /> 83 <Button 84 type="submit" 85 className="bg-blue-400 text-sm whitespace-nowrap" 86 aria-label="submit" 87 disabled={isLoading} 88 data-umami-event="newsletter_submit" 89 data-umami-event-email={email} 90 > 91 {isLoading ? "Submitting..." : "Submit"} 92 </Button> 93 </div> 94 95 {woahThere && ( 96 <p className="mt-2 text-sm text-purple-500"> 97 Slow down cowboy! You&apos;re not Jasper! 98 </p> 99 )} 100 {error && <p className="mt-2 text-sm text-red-500">{error}</p>} 101 </form> 102 ) : ( 103 <p className="text-sm text-green-400"> 104 Submitted! Be sure to look out for emails in the future! 105 </p> 106 )} 107 </div> 108 ); 109}