Skip to content

Commit

Permalink
Merge pull request #1 from NUWildHacks/dev
Browse files Browse the repository at this point in the history
Implement POST API for Mailing List Subscription
  • Loading branch information
dilanx authored Sep 20, 2023
2 parents 773f1c6 + 70870cb commit b38781d
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 9 deletions.
75 changes: 75 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@fortawesome/free-brands-svg-icons": "^6.3.0",
"@fortawesome/free-solid-svg-icons": "^6.3.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"framer-motion": "^10.16.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-is": "^18.2.0",
Expand Down
2 changes: 2 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import About from './About';
import Faq from './Faq';
import Footer from './Footer';
import styled from 'styled-components';
import MailingList from './components/MailingList';

const Container = styled.div`
max-width: 1000px;
Expand All @@ -19,6 +20,7 @@ function App() {
<About />
<Faq />
<Footer />
<MailingList />
</Container>
);
}
Expand Down
21 changes: 14 additions & 7 deletions src/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,22 @@ const Email = styled.p`
}
`;

const BottomPadding = styled.div`
height: 64px;
`;

function Footer() {
return (
<Section>
<Email>
<a href="mailto:wildhacks@northwestern.edu">
wildhacks@northwestern.edu
</a>
</Email>
</Section>
<>
<Section>
<Email>
<a href="mailto:wildhacks@northwestern.edu">
wildhacks@northwestern.edu
</a>
</Email>
</Section>
<BottomPadding />
</>
);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Heading.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ const Button = styled.a`
function Heading() {
return (
<Container>
<Time>April 15-16 2023 in Evanston, IL</Time>
<Title>WILDHACKS 2023</Title>
<Time>Coming April 2024 in Evanston, IL</Time>
<Title>WILDHACKS 2024</Title>
<ButtonContainer>
<Button href="https://dashboard.wildhacks.net">
<p>DASHBOARD</p>
Expand Down
210 changes: 210 additions & 0 deletions src/components/MailingList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { useEffect, useState, useRef } from 'react';
import styled from 'styled-components';
import { mobile } from '../styles';

const Container = styled.div`
position: fixed;
bottom: 16px;
left: 50%;
transform: translateX(-50%);
max-width: 1200px;
width: 100vw;
padding: 0 16px;
box-sizing: border-box;
transition: transform 2s ease-in-out;
${({ success }) => {
if (success === 'hidden')
return `transform: translateX(-50%) translateY(100%);`;
}};
`;

const Form = styled.form`
background-color: #382e7d;
padding: 8px;
border-radius: 6px;
box-shadow: 0 0 16px #382e7d;
display: flex;
gap: 32px;
justify-content: center;
align-items: center;
.hide {
display: ${({ success }) => {
if (success === 'true') return `none`;
}};
${({ success }) => {
if (success === 'hidden') return `visibility: hidden`;
}};
}
.success {
display: ${({ success }) => {
if ((success !== 'true') & (success !== 'hidden')) return `none`;
}};
${({ success }) => {
if (success === 'hidden')
return `
opacity: 0;
`;
}};
}
${mobile} {
flex-direction: column;
gap: 8px;
}
`;

const Text = styled.p`
margin: 0;
font-size: 14px;
text-align: center;
`;

const InputContainer = styled.div`
display: flex;
align-items: center;
gap: 8px;
`;

const Input = styled.input`
background-color: #01002e;
border: 1px solid #646464;
color: #ffffff;
border-radius: 8px;
padding: 4px 8px;
outline: none;
width: ${(props) => props.w}px;
&:hover {
border-color: #a0a0a0;
}
&:focus {
border-color: #559fd5;
}
`;

const Button = styled.button`
background-color: #a599ff;
color: #ffffff;
border: 1px solid #8b74bd;
padding: 4px 16px;
border-radius: 6px;
transition: opacity 150ms;
&:hover {
opacity: 0.8;
cursor: pointer;
}
&:active {
opacity: 0.7;
}
`;

export default function MailingList() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');
const [success, setSuccess] = useState('');

const api = 'https://api.dilanxd.com/wildhacks/subscribe';
const form = useRef();
const messages = {
true: 'You have been successfully added to our mailing list',
false: 'Subscription failed: Please enter valid inputs',
error: 'Subscription error: Please try again',
};

const subscriberData = {
firstName: firstName,
lastName: lastName,
email: email,
};

const subscribe = (e) => {
e.preventDefault();

const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(subscriberData),
};

fetch(api, requestOptions)
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then((data) => {
console.log(data);
setSuccess(data.success);
})
.catch((error) => {
console.log(error);
setSuccess('error');
});
};

useEffect(() => {
console.log('useEffect triggered. Success:', success);
let timeout;

if (success.toString() === 'true') {
timeout = setTimeout(() => {
setSuccess('hidden');
}, 2_000);
}
return () => {
clearTimeout(timeout);
};
}, [success]);

return (
<Container success={success.toString()}>
<Form ref={form} onSubmit={subscribe} success={success.toString()}>
<Text className="hide">
{success === 'false' || success === 'error'
? messages[success.toString()]
: 'Interested? Join our mailing list!'}
</Text>
<p className="success">{messages.true}</p>
<InputContainer className="hide">
<Input
autoComplete="off"
placeholder="First Name"
w={80}
onChange={(e) => setFirstName(e.target.value)}
value={firstName}
required
/>
<Input
autoComplete="off"
placeholder="Last Name"
w={80}
onChange={(e) => setLastName(e.target.value)}
value={lastName}
required
/>
<Input
autoComplete="off"
placeholder="Email"
w={160}
onChange={(e) => setEmail(e.target.value)}
value={email}
required
/>
</InputContainer>
<Button className="hide" type="submit" value="Send">
Join
</Button>
</Form>
</Container>
);
}

0 comments on commit b38781d

Please sign in to comment.