Skip to content

Commit

Permalink
Test simpler form component and api route for mailchimp
Browse files Browse the repository at this point in the history
  • Loading branch information
gabros20 committed Jan 29, 2025
1 parent 34fd375 commit 51f5ab3
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 109 deletions.
7 changes: 7 additions & 0 deletions src/app/api/newsletter/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ async function subscribeToMailchimp(email) {
};
}

// Detailed logging for unexpected errors
console.error("Unexpected Mailchimp error:", {
message: error.message,
stack: error.stack,
response: error.response,
});

throw error; // Let the main handler catch other errors
}
}
Expand Down
54 changes: 54 additions & 0 deletions src/app/api/subscribe/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { NextResponse } from "next/server";

export async function POST(req) {
try {
const { email } = await req.json();

if (!email || !email.includes("@")) {
return NextResponse.json({ error: "Invalid email address" }, { status: 400 });
}

const MAILCHIMP_API_KEY = process.env.MAILCHIMP_API_KEY;
const MAILCHIMP_LIST_ID = process.env.MAILCHIMP_LIST_ID;
const MAILCHIMP_SERVER_PREFIX = process.env.MAILCHIMP_SERVER_PREFIX;

if (!MAILCHIMP_API_KEY || !MAILCHIMP_LIST_ID || !MAILCHIMP_SERVER_PREFIX) {
return NextResponse.json({ error: "Missing Mailchimp configuration" }, { status: 500 });
}

const url = `https://${MAILCHIMP_SERVER_PREFIX}.api.mailchimp.com/3.0/lists/${MAILCHIMP_LIST_ID}/members`;

const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Basic ${Buffer.from(`anystring:${MAILCHIMP_API_KEY}`).toString("base64")}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
email_address: email,
status: "subscribed",
}),
signal: AbortSignal.timeout(5000),
});

if (response.status === 400) {
const data = await response.json();
if (data.title === "Member Exists") {
return NextResponse.json({ error: "Already subscribed" }, { status: 400 });
}
}

const data = await response.json();

if (!response.ok) {
return NextResponse.json({ error: data.detail || "Failed to subscribe" }, { status: response.status });
}

return NextResponse.json({ success: true });
} catch (error) {
if (error.name === "TimeoutError") {
return NextResponse.json({ error: "Request timed out" }, { status: 408 });
}
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
}
210 changes: 101 additions & 109 deletions src/components/Footer/Footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,117 +8,109 @@ import Link from "@/macros/Link/Link";
import Icon from "@/macros/Icons/Icon";
import ArrowLongSVG from "@/macros/SVGs/ArrowLongSVG";
import { isInternalLink } from "@/utils/isInternalLink";
import Newsletter from "@/components/Newsletter/Newsletter";
// import Newsletter from "@/components/Newsletter/Newsletter";
import NewsletterSimple from "@/components/NewsletterSimple/NewsletterSimple";

const Footer = () => {
const columns = footerData();
const copywriteYear = new Date().getFullYear();
return (
<footer
id={"footer"}
className={`bg-black w-full rounded-tl-3xl rounded-tr-3xl py-5 text-white z-30 relative`}
>
<div className={`px-4`}>
<div
className={`h-[225px] md:h-[400px] block w-full rounded-2xl bg-white overflow-hidden z-0 relative`}
>
<VideoPlayer src={"/videos/footer.mp4"} />
</div>
</div>
<div className={`px-4 mb-8`}>
<Container
size={`lg`}
className={`pt-20 pb-6 px-8 lg:pt-[10.25rem] lg:px-[6.25rem] lg:pb-20 rounded-2xl z-10 relative frosted-container -mt-10 lg:-mt-[100px]`}
>
<div className="relative z-10 lg:flex">
<div className="pb-12 lg:pb-0 w-full lg:1/2">
<Heading size="lg" className={`mb-12`}>
Build whatever with Celestia underneath
</Heading>
<Newsletter />
</div>
<div
className={`flex flex-wrap lg:flex-nowrap w-full lg:1/2 lg:gap-6 lg:justify-end ml-auto mr-0`}
>
{columns.map((column, index) => {
return (
<ul
key={index}
className={`block ${
index === columns.length - 1
? "w-full flex flex-row justify-center lg:justify-end gap-4 order-last lg:order-none lg:flex-col lg:w-auto"
: "w-1/2 lg:w-1/5"
} ${index === columns.length - 1 ? "" : "mb-10 lg:mb-0"}`}
>
{column.links.map((link, linkIndex) => {
const isInternal = isInternalLink(link.url);
return (
<li key={`col-${index}-link-${linkIndex}`}>
<Link
href={link.url}
target={isInternal ? "_self" : "_blank"}
rel={isInternal ? "" : "noopener noreferrer"}
className={`flex items-center group mb-4`}
>
{link.icon ? (
<Icon
Icon={<link.icon dark />}
hover
HoverIcon={<link.icon dark className="opacity-50" />}
size="sm"
border={false}
transparentBg
direction="up"
/>
) : (
<>
<Body className={`mr-1`} size={"md"}>
{link.title}
</Body>
<Icon
className={"flex-grow-0 flex-shrink-0"}
border={false}
transparentBg
size={"xs"}
Icon={<div className={"block h-4 w-4"}></div>}
hover
HoverIcon={<ArrowLongSVG />}
direction={isInternal ? "down-right" : "up-right"}
/>
</>
)}
</Link>
</li>
);
})}
</ul>
);
})}
</div>
</div>
</Container>
</div>
<Container
size="lg"
className={`lg:flex lg:justify-between px-4 lg:mb-3`}
>
<div className="text-center lg:text-left w-full mb-2 ">
<Link href={"/privacy"} className={`inline-block mr-2`}>
<Body size="sm">Privacy Policy</Body>
</Link>
·
<Link href={"/tos"} className={`inline-block ml-2`}>
<Body size="sm">Terms of Service</Body>
</Link>
</div>
<div className={`w-full`}>
<Body size="sm" className={`text-center lg:text-right`}>
© {copywriteYear} Celestia Labs
</Body>
</div>
</Container>
</footer>
);
const columns = footerData();
const copywriteYear = new Date().getFullYear();
return (
<footer id={"footer"} className={`bg-black w-full rounded-tl-3xl rounded-tr-3xl py-5 text-white z-30 relative`}>
<div className={`px-4`}>
<div className={`h-[225px] md:h-[400px] block w-full rounded-2xl bg-white overflow-hidden z-0 relative`}>
<VideoPlayer src={"/videos/footer.mp4"} />
</div>
</div>
<div className={`px-4 mb-8`}>
<Container
size={`lg`}
className={`pt-20 pb-6 px-8 lg:pt-[10.25rem] lg:px-[6.25rem] lg:pb-20 rounded-2xl z-10 relative frosted-container -mt-10 lg:-mt-[100px]`}
>
<div className='relative z-10 lg:flex'>
<div className='w-full pb-12 lg:pb-0 lg:1/2'>
<Heading size='lg' className={`mb-12`}>
Build whatever with Celestia underneath
</Heading>
{/* <Newsletter /> */}
<NewsletterSimple />
</div>
<div className={`flex flex-wrap lg:flex-nowrap w-full lg:1/2 lg:gap-6 lg:justify-end ml-auto mr-0`}>
{columns.map((column, index) => {
return (
<ul
key={index}
className={`block ${
index === columns.length - 1
? "w-full flex flex-row justify-center lg:justify-end gap-4 order-last lg:order-none lg:flex-col lg:w-auto"
: "w-1/2 lg:w-1/5"
} ${index === columns.length - 1 ? "" : "mb-10 lg:mb-0"}`}
>
{column.links.map((link, linkIndex) => {
const isInternal = isInternalLink(link.url);
return (
<li key={`col-${index}-link-${linkIndex}`}>
<Link
href={link.url}
target={isInternal ? "_self" : "_blank"}
rel={isInternal ? "" : "noopener noreferrer"}
className={`flex items-center group mb-4`}
>
{link.icon ? (
<Icon
Icon={<link.icon dark />}
hover
HoverIcon={<link.icon dark className='opacity-50' />}
size='sm'
border={false}
transparentBg
direction='up'
/>
) : (
<>
<Body className={`mr-1`} size={"md"}>
{link.title}
</Body>
<Icon
className={"flex-grow-0 flex-shrink-0"}
border={false}
transparentBg
size={"xs"}
Icon={<div className={"block h-4 w-4"}></div>}
hover
HoverIcon={<ArrowLongSVG />}
direction={isInternal ? "down-right" : "up-right"}
/>
</>
)}
</Link>
</li>
);
})}
</ul>
);
})}
</div>
</div>
</Container>
</div>
<Container size='lg' className={`lg:flex lg:justify-between px-4 lg:mb-3`}>
<div className='w-full mb-2 text-center lg:text-left '>
<Link href={"/privacy"} className={`inline-block mr-2`}>
<Body size='sm'>Privacy Policy</Body>
</Link>
·
<Link href={"/tos"} className={`inline-block ml-2`}>
<Body size='sm'>Terms of Service</Body>
</Link>
</div>
<div className={`w-full`}>
<Body size='sm' className={`text-center lg:text-right`}>
© {copywriteYear} Celestia Labs
</Body>
</div>
</Container>
</footer>
);
};

export default Footer;
Loading

0 comments on commit 51f5ab3

Please sign in to comment.