Skip to content

Commit

Permalink
Add internal newsletter
Browse files Browse the repository at this point in the history
  • Loading branch information
nuno-aac committed Nov 30, 2023
1 parent 5dde5f6 commit a362436
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 1 deletion.
5 changes: 5 additions & 0 deletions _data/seo/newsletter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
title: Starknet Newsletter ✨🗞️
subtitle: Stay up to date with the latest news and updates from the Starknet ecosystem.
description: Sign up to receive the latest news and updates from the Starknet ecosystem.
We'll send you emails with the latest news, updates, and resources
from the Starknet ecosystem.
2 changes: 2 additions & 0 deletions public/robots.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ Disallow: /fr/*
Disallow: /ja/*
Disallow: /ko/*
Disallow: /pt/*
Disallow: /*/subscribe-newsletter
Disallow: /subscribe-newsletter
25 changes: 25 additions & 0 deletions workspaces/cms-config/src/collections/seo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,31 @@ export const SEOCollectionConfig = {
crowdin: true,
},
],
}, {
label: "Starknet newsletter",
name: "newsletter",
file: `_data/seo/newsletter.yml`,
crowdin: true,
fields: [
{
label: "Title",
name: "title",
widget: "string",
crowdin: true,
},
{
label: "Sub Title",
name: "subtitle",
widget: "string",
crowdin: true,
},
{
label: "Description",
name: "description",
widget: "string",
crowdin: true,
}
],
},
],
} satisfies CmsCollection;
5 changes: 5 additions & 0 deletions workspaces/cms-data/src/seo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export interface SEOTexts {
subtitle: string;
description: string;
};
newsletter: {
title: string;
subtitle: string;
description: string;
};
search: {
search: string;
cancel: string;
Expand Down
4 changes: 3 additions & 1 deletion workspaces/cms-scripts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const createSharedData = async () => {
"jobs",
"search",
"language",
"newsletter"
];

for (const locale of locales) {
Expand Down Expand Up @@ -160,6 +161,7 @@ const simpleFiles = [
await getSimpleFiles("seo", "footer", true),
await getSimpleFiles("seo", "home", true),
await getSimpleFiles("seo", "language", true),
await getSimpleFiles("seo", "newsletter", true),
await getSimpleFiles("seo", "search", true),
];

Expand Down Expand Up @@ -278,4 +280,4 @@ const redirects = await yaml("_data/settings/redirects.yml");
await write(`workspaces/website/redirects.json`, redirects);
await createRoadmapDetails()
await createAnnouncementDetails()
await createSharedData()
await createSharedData()
145 changes: 145 additions & 0 deletions workspaces/website/src/pages/subscribe-newsletter/NewsletterPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@

/**
* Module dependencies.
*/

import {
Box,
Button,
FormControl,
FormLabel,
Input,
useToast
} from "@chakra-ui/react";

import { PageLayout } from "@ui/Layout/PageLayout";
import { SEOTexts } from "@starknet-io/cms-data/src/seo";
import { Text } from '@ui/Typography/Text';
import { Turnstile, TurnstileInstance } from "@marsidev/react-turnstile";
import { useRef, useState } from "react";
import axios from "axios";
import qs from "qs";

/**
* `Props` type.
*/

export interface Props {
readonly env: {
readonly CLOUDFLARE_RECAPTCHA_KEY: string;
};
readonly seo: SEOTexts['newsletter'];
}

/**
* Export `NewsletterPage` component.
*/

export function NewsletterPage({ env, seo }: Props): JSX.Element | null {
const toast = useToast();
const [formState, setFormState] = useState<'submitting' | 'success' | null>(null);
const captchaRef = useRef<TurnstileInstance | undefined>(null);

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setFormState('submitting');

try {
const token = captchaRef.current?.getResponse();

await axios.post(`/api/newsletter-subscribe?${qs.stringify({
email: (event.target as any)[0].value,
token,
})}`)

captchaRef.current?.reset();
setFormState('success');
} catch (error: any) {
setFormState(null);
captchaRef.current?.reset();

const toastErrorConfig = {
duration: 1500,
isClosable: true,
status: 'error' as 'error',
};

if(error.response.data?.title === 'Invalid Captcha') {
toast({
description: 'We\'re having trouble verifying you\'re a human. Please try again.',
...toastErrorConfig
});

return;
}

if(error.response.data?.title === 'Member Exists') {
toast({
description: 'You are already subscribed to the newsletter.',
...toastErrorConfig
});

return;
}

toast({
description: 'There was an issue subscribing you to the newsletter.',
...toastErrorConfig
});
}
}

return (
<PageLayout
sectionHeaderTitle={seo.title}
sectionHeaderDescription={seo.subtitle}
main={
<Box maxW={500}>
{formState !== 'success' ? (
<form onSubmit={handleSubmit}>
<FormControl isRequired paddingBottom={'20px'}>
<FormLabel fontWeight={'700'}>
Email
</FormLabel>

<Input
type={'email'}
name={'email'}
id={'email'}
placeholder={'Please enter your email'}
/>
</FormControl>

<Turnstile
options={{
size: 'invisible'
}}
ref={captchaRef}
siteKey={env.CLOUDFLARE_RECAPTCHA_KEY}
/>

<Button
fontSize={'14px'}
isLoading={formState === 'submitting'}
padding={'6px 16px'}
type={'submit'}
variant={'solid'}
>
Submit
</Button>
</form>
) : (
<div style={{ textAlign: 'center' }}>
<Text
variant={'cardBody'}
color={'heading-navy-fg'}
>
Thank you and may the STARK be with you ✨🗞️
</Text>
</div>
)}
</Box>
}
/>
)
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Module dependencies
*/

import { PageContextServer } from "src/renderer/types";
import { Props } from "src/pages/subscribe-newsletter/NewsletterPage";
import { getDefaultPageContext } from "src/renderer/helpers";

/**
* Export `onBeforeRender` function.
*/

export async function onBeforeRender(pageContext: PageContextServer) {
const defaultPageContext = await getDefaultPageContext(pageContext);
const { locale } = defaultPageContext;
console.log(defaultPageContext.seo)

const pageProps: Props = {
seo: defaultPageContext.seo.newsletter,
env: {
CLOUDFLARE_RECAPTCHA_KEY: import.meta.env.VITE_CLOUDFLARE_RECAPTCHA_KEY
},
params: {
locale,
},
};

return {
pageContext: {
...defaultPageContext,
pageProps,
},
};
}
20 changes: 20 additions & 0 deletions workspaces/website/src/pages/subscribe-newsletter/index.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Module dependencies.
*/

import { DocumentProps } from "src/renderer/types";

/**
* Export `Page` component
*/

export { NewsletterPage as Page } from "src/pages/subscribe-newsletter/NewsletterPage";

/**
* Export `documentProps`.
*/

export const documentProps = {
title: "Starknet Newsletter",
description: "Subscribe to the Starknet newsletter to stay up to date with the latest news and developments from the Starknet team."
} satisfies DocumentProps

0 comments on commit a362436

Please sign in to comment.