Skip to content

Commit

Permalink
added newsletter
Browse files Browse the repository at this point in the history
  • Loading branch information
ArturBuja committed Sep 27, 2023
1 parent eca1d8b commit 94501aa
Show file tree
Hide file tree
Showing 9 changed files with 600 additions and 3 deletions.
394 changes: 394 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"@auth/prisma-adapter": "^1.0.2",
"@emailjs/browser": "^3.11.0",
"@mailchimp/mailchimp_marketing": "^3.0.80",
"@prisma/client": "^5.2.0",
"@types/node": "20.5.9",
"@types/react": "18.2.21",
Expand All @@ -29,6 +30,7 @@
"typescript": "5.2.2"
},
"devDependencies": {
"@types/mailchimp__mailchimp_marketing": "^3.0.13",
"encoding": "^0.1.13",
"prisma": "^5.2.0"
}
Expand Down
66 changes: 66 additions & 0 deletions src/app/api/subscribe/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import mailchimp from '@mailchimp/mailchimp_marketing';

import { NextResponse } from 'next/server';

mailchimp.setConfig({
apiKey: process.env.MAILCHIMP_API_KEY,
server: process.env.MAILCHIMP_API_SERVER,
});

const API_KEY = process.env.MAILCHIMP_API_KEY;
const API_SERVER = process.env.MAILCHIMP_API_SERVER;
const AUDIENCE_ID = process.env.MAILCHIMP_AUDIENCE_ID;
export const POST = async (req: Request, res: Response) => {
const body = await req.json();
const { email } = body;

if (!email || !email.length) {
return new NextResponse(
JSON.stringify({ message: 'Adres emial nie może być pusty' }),
{
status: 400,
}
);
}

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

const data = {
email_address: email,
status: 'subscribed',
};

const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `api_key ${API_KEY}`,
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, options);
const responseData = await response.json();

if (responseData.status >= 400) {
return new NextResponse(
JSON.stringify({
message:
responseData.detail ??
`Wystąpił bład podczas dodawania emaila do list. Napisz do mnie na [email protected], a dodam Cię do listy. `,
}),
{
status: responseData.status,
}
);
}
return new NextResponse(JSON.stringify({ message: responseData.detail }), {
status: 201,
});
} catch (error) {
console.log(error);
return new NextResponse(JSON.stringify({ message: 'Coś poszło nie tak' }), {
status: 500,
});
}
};
7 changes: 4 additions & 3 deletions src/app/contact/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import emailjs from '@emailjs/browser';
import styles from './contactPage.module.css';
//hooks
import useInput from '@/hooks/useInput';
//utils
import { isEmailOrEmpty } from '@/utils/helpers';

const isNotEmptyMessage = (value: string) => value.trim().length >= 10;
const isNotEmptyName = (value: string) => value.trim().length >= 2;
const isEmailOrEmpty = (value: string) =>
/^([A-Za-z0-9_\-.])+@([A-Za-z0-9_\-.])+\.([A-Za-z]{2,4})$/.test(value);

const Contact = () => {
const form = useRef<HTMLFormElement | null>(null);
const [emailIsSending, setEmailIsSending] = useState(false);
Expand Down Expand Up @@ -123,7 +124,7 @@ const Contact = () => {
onBlur={emailBlurHandler}
value={email}
className={styles.input}
type='text'
type='email'
placeholder={'Wpisz swój email'}
/>

Expand Down
67 changes: 67 additions & 0 deletions src/app/subscribe/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client';
import React, { useState } from 'react';

//utils
import { isEmailOrEmpty } from '@/utils/helpers';
//styles
import styles from './subscribePage.module.css';

const SubscribePage = () => {
const [email, setEmail] = useState('');
const [message, setMessage] = useState('');
const [loading, setLoading] = useState(false);

const subscribe = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!isEmailOrEmpty(email)) {
return setMessage('Wpisz poprawny adres email');
}
setLoading(true);
const res = await fetch('/api/subscribe', {
body: JSON.stringify({
email,
}),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
});
const data = await res.json();

const { message } = data;
if (message) {
setMessage(message);
setLoading(false);
return;
}

setEmail('');
setMessage('Sukces! 🎉 Twoj adres mailowy został zapisany do newslettera.');
setLoading(false);
};

return (
<form onSubmit={subscribe} className={styles.form}>
<input
id='email-input'
name='email'
placeholder={'Wpisz swój email'}
value={email}
className={styles.input}
onChange={e => setEmail(e.target.value)}
required
type='email'
/>
<div className={styles.message}>
{message
? message
: ` Zapisz się do newslettera! Wysyłam tylko powiadomienie o nowych wpisach, bez spamu. Możesz zrezygnować w dowolnym momencie. W przypadku zapisania się, a nie otrzymywania wiadomości mailowej, czasem wiadomości wpadają do folderu SPAM.`}
</div>
<button className={styles.button} disabled={loading} type='submit'>
{'Subskrybuj'}
</button>
</form>
);
};

export default SubscribePage;
58 changes: 58 additions & 0 deletions src/app/subscribe/subscribePage.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
.form {
background-color: var(--softBg);
padding: 3rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 1.25rem;
width: 50%;
margin: 0 auto;
}
.input {
border: none;
width: max-content;
border-radius: 0.625rem;
padding: 0.625rem;
outline: none;
text-align: center;
}
.message {
text-align: center;
font-size: 1.125rem;
color: var(--textColor);
font-weight: 500;
margin-bottom: 1.25rem;
width: 60%;
}
.button {
padding: 0.625rem 1.25rem;
border: none;
background-color: #1a8917;
color: #fff;
cursor: pointer;
border-radius: 20px;
align-self: flex-end;
}
.button:disabled {
opacity: 0.5;
cursor: not-allowed;
}

@media screen and (max-width: 1280px) {
.form {
width: 80%;
}
}

@media screen and (max-width: 640px) {
.form {
width: 100%;
}
}

@media screen and (max-width: 480px) {
.message {
width: 100%;
}
}
3 changes: 3 additions & 0 deletions src/components/footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const Footer = () => {
programowanie, relacje z podróży, kulinarne eksploracje oraz ogólny
styl życia.
</p>
<Link href='/subscribe' className={styles.newsletter}>
{`Zapisz się do newslettera ;)`}
</Link>
<div className={styles.icons}>
<Socials />
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/components/footer/footer.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
.desc {
font-weight: 300;
}
.newsletter {
font-weight: 300;
text-decoration: underline !important;
}
.icons {
margin-top: 0.625rem;
display: flex;
Expand Down
2 changes: 2 additions & 0 deletions src/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ export const slugify = (str: string) =>
})
.replace(/[\s_-]+/g, '-')
.replace(/^-+|-+$/g, '');
export const isEmailOrEmpty = (value: string) =>
/^([A-Za-z0-9_\-.])+@([A-Za-z0-9_\-.])+\.([A-Za-z]{2,4})$/.test(value);

0 comments on commit 94501aa

Please sign in to comment.