|
|
@ -14,7 +14,7 @@ const handleClick = () => {
|
|||
}
|
||||
})
|
||||
}
|
||||
const ScrollHint = () => (
|
||||
const ScrollHint = ({...props}) => (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'block',
|
||||
|
|
@ -33,6 +33,7 @@ const ScrollHint = () => (
|
|||
'&:active': { transform: ' translateY(6px) rotate(45deg)' }
|
||||
}}
|
||||
onClick={handleClick}
|
||||
{...props}
|
||||
></Box>
|
||||
)
|
||||
|
||||
|
|
|
|||
80
components/winter/breakdown-box.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import {
|
||||
Box,
|
||||
Card,
|
||||
Flex,
|
||||
Container,
|
||||
Heading,
|
||||
Text,
|
||||
Badge,
|
||||
Link
|
||||
} from 'theme-ui'
|
||||
import { Zoom } from 'react-reveal'
|
||||
import Icon from '@hackclub/icons'
|
||||
|
||||
function BreakdownBox({ subtitle, icon, text, description, delay, href, color, bg }) {
|
||||
return (
|
||||
<Zoom delay={delay}>
|
||||
<Card
|
||||
sx={{
|
||||
color: 'white',
|
||||
background: 'rgba(225,225,225,0.2)',
|
||||
height: '100%',
|
||||
cursor: `${href ? 'pointer' : 'default'}`,
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
// justifyContent: 'flex-end'
|
||||
}}
|
||||
variant="interactive"
|
||||
as={href ? 'a' : 'div'}
|
||||
href={href}
|
||||
>
|
||||
{subtitle ? (
|
||||
<Text
|
||||
as="h1"
|
||||
sx={{
|
||||
fontSize: [2, 3, 4]
|
||||
}}
|
||||
>
|
||||
{subtitle}
|
||||
</Text>
|
||||
) : (
|
||||
<Box
|
||||
as="span"
|
||||
sx={{
|
||||
width: 'fit-content',
|
||||
bg: bg || 'white',
|
||||
borderRadius: 18,
|
||||
lineHeight: 0,
|
||||
p: 2,
|
||||
mb: 1,
|
||||
display: 'inline-block',
|
||||
transform: ['scale(0.75)', 'none'],
|
||||
transformOrigin: 'bottom left',
|
||||
boxShadow:
|
||||
'inset 2px 2px 6px rgba(255,255,255,0.2), inset -2px -2px 6px rgba(0,0,0,0.1), 0 1px 4px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.1)'
|
||||
}}
|
||||
>
|
||||
<Icon glyph={icon} size={48} color={color || 'white'} />
|
||||
</Box>
|
||||
)}
|
||||
<Heading
|
||||
sx={{
|
||||
fontSize: [3, 4, 5]
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Heading>
|
||||
<Text
|
||||
as="p"
|
||||
sx={{
|
||||
fontSize: [2, 3]
|
||||
}}
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
</Card>
|
||||
</Zoom>
|
||||
)
|
||||
}
|
||||
|
||||
export default BreakdownBox
|
||||
106
components/winter/breakdown.js
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Container,
|
||||
Heading,
|
||||
Grid,
|
||||
Text,
|
||||
Badge,
|
||||
Link
|
||||
} from 'theme-ui'
|
||||
import { Fade, Slide } from 'react-reveal'
|
||||
import BreakdownBox from './breakdown-box'
|
||||
|
||||
function Breakdown() {
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
pt: 3,
|
||||
pb: 5,
|
||||
background: 'linear-gradient(180deg, #579AC9 0%, #338EDA 100%)'
|
||||
}}
|
||||
>
|
||||
<Container>
|
||||
<Slide>
|
||||
<Heading
|
||||
variant="headline"
|
||||
sx={{
|
||||
textShadow: '0px 0px 21px #E1F1FF',
|
||||
color: 'white',
|
||||
fontStyle: 'italic'
|
||||
}}
|
||||
>
|
||||
<Fade>
|
||||
Dear high school hacker, we have a challenge for you:
|
||||
</Fade>
|
||||
</Heading>
|
||||
<Heading
|
||||
variant="headline"
|
||||
sx={{
|
||||
textShadow: '0px 0px 21px #E1F1FF',
|
||||
color: 'white',
|
||||
fontSize: [4, 5, 6],
|
||||
pb: 4,
|
||||
mt: 0
|
||||
}}
|
||||
>
|
||||
<Fade>
|
||||
What will you make this winter?
|
||||
</Fade>
|
||||
</Heading>
|
||||
</Slide>
|
||||
<Fade>
|
||||
<Heading
|
||||
variant="headline"
|
||||
sx={{
|
||||
// textShadow: '0px 0px 21px #E1F1FF',
|
||||
color: '#338eda',
|
||||
background: 'white',
|
||||
px: 3,
|
||||
py: 2,
|
||||
borderRadius: '10px',
|
||||
width: 'fit-content'
|
||||
}}
|
||||
>
|
||||
Join Hack Clubbers in a winter of making with
|
||||
</Heading>
|
||||
</Fade>
|
||||
|
||||
<Grid gap={[2, 2, 3]} columns={[1, 1, 3, 3]} py={3}>
|
||||
<BreakdownBox
|
||||
icon="friend"
|
||||
color="#5bc0de"
|
||||
text="Friends"
|
||||
description="Find support from our community of 20k+ teenagers in the Hack Club Slack."
|
||||
delay="300"
|
||||
href="/slack"
|
||||
/>
|
||||
<BreakdownBox
|
||||
icon="event-code"
|
||||
color="#5bc0de"
|
||||
text="Daily progress"
|
||||
description={
|
||||
<>
|
||||
From <strong>Feb 15-25</strong>, work on your project, share
|
||||
short photo/video updates each day.
|
||||
</>
|
||||
}
|
||||
delay="100"
|
||||
href="https://scrapbook.hackclub.com/r/10daysinpublic"
|
||||
/>
|
||||
<BreakdownBox
|
||||
icon="settings"
|
||||
color="#5bc0de"
|
||||
text="Free hardware"
|
||||
description="We'll pay for up to $250 of your hardware to build your project."
|
||||
delay="200"
|
||||
/>
|
||||
</Grid>
|
||||
</Container>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Breakdown
|
||||
162
components/winter/form.js
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
import { Box, Input, Label, Button, Select, Text, Grid } from 'theme-ui'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import theme from '@hackclub/theme'
|
||||
import Icon from '../icon'
|
||||
import { keyframes } from '@emotion/react'
|
||||
import debounce from 'lodash/debounce'
|
||||
|
||||
const hideAnimation = keyframes({
|
||||
from: { display: 'flex' },
|
||||
to: { display: 'none', opacity: 0, padding: 0, position: 'absolute' }
|
||||
})
|
||||
|
||||
const spinAnimation = keyframes({
|
||||
from: { transform: 'rotate(0deg)' },
|
||||
to: { transform: 'rotate(360deg)' }
|
||||
})
|
||||
|
||||
function Base({ children, action, target, method, onSubmit, id }) {
|
||||
return (
|
||||
<Box
|
||||
as="form"
|
||||
sx={{ display: 'grid', gridTemplateColumns: '1fr' }}
|
||||
id={id}
|
||||
action={action}
|
||||
target={target}
|
||||
method={method}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
function Field({
|
||||
placeholder,
|
||||
label,
|
||||
name,
|
||||
type,
|
||||
value,
|
||||
onChange,
|
||||
required = true,
|
||||
loading = false
|
||||
}) {
|
||||
return (
|
||||
<Box sx={{ my: 2 }}>
|
||||
<Label htmlFor={name} sx={{ color: 'muted', fontSize: 18 }}>
|
||||
{label}
|
||||
</Label>
|
||||
<Box sx={{ position: 'relative' }}>
|
||||
{loading && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 10,
|
||||
right: 10,
|
||||
width: 20,
|
||||
height: 20,
|
||||
border: '1px solid white',
|
||||
borderRightStyle: 'none',
|
||||
animation: `${spinAnimation} 1s linear infinite`,
|
||||
borderRadius: '50%'
|
||||
}}
|
||||
></Box>
|
||||
)}
|
||||
<Input
|
||||
id={name}
|
||||
placeholder={placeholder}
|
||||
name={name}
|
||||
type={type}
|
||||
sx={{
|
||||
bg: 'light'
|
||||
}}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
required={required}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Signup() {
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
|
||||
const [eventName, setEventName] = useState('')
|
||||
const [userEmail, setUserEmail] = useState('')
|
||||
|
||||
const handleSubmit = async e => {
|
||||
e.preventDefault()
|
||||
|
||||
await fetch('/api/bank/demo', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
eventName,
|
||||
userEmail
|
||||
})
|
||||
})
|
||||
|
||||
setSubmitted(true)
|
||||
|
||||
// clear form
|
||||
setEventName('')
|
||||
setUserEmail('')
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Base
|
||||
id="form"
|
||||
method="POST"
|
||||
action="/api/bank/demo"
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<Field
|
||||
label="Name"
|
||||
name="eventName"
|
||||
placeholder="Fiona's Hardware Fund"
|
||||
value={eventName}
|
||||
onChange={e => setEventName(e.target.value)}
|
||||
/>
|
||||
<Field
|
||||
label="Email address"
|
||||
name="userEmail"
|
||||
placeholder="fiona@hackclub.com"
|
||||
type="email"
|
||||
value={userEmail}
|
||||
onChange={e => setUserEmail(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
sx={{
|
||||
backgroundImage: theme.util.gx('green', 'blue'),
|
||||
mt: [2, 3],
|
||||
py: 2
|
||||
}}
|
||||
type="submit"
|
||||
>
|
||||
Create new account
|
||||
</Button>
|
||||
</Base>
|
||||
{submitted && (
|
||||
<Box
|
||||
sx={{
|
||||
mt: 2,
|
||||
px: 2,
|
||||
py: 2,
|
||||
borderRadius: 'default',
|
||||
color: 'white',
|
||||
bg: 'green',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'start',
|
||||
animation: `${hideAnimation} 0s ease-in 15s`,
|
||||
animationFillMode: 'forwards'
|
||||
}}
|
||||
>
|
||||
<Icon glyph="send" size={24} />
|
||||
<Text>Submitted! Check your email for a sign in link.</Text>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
246
components/winter/info.js
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
import {
|
||||
Card,
|
||||
Grid,
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Heading,
|
||||
Text,
|
||||
Flex,
|
||||
Avatar
|
||||
} from 'theme-ui'
|
||||
import Icon from '../icon'
|
||||
import Tilt from '../tilt'
|
||||
import { Zoom } from 'react-reveal'
|
||||
|
||||
export default function InfoGrid() {
|
||||
return (
|
||||
<Container py={4}>
|
||||
<Grid
|
||||
sx={{
|
||||
gridTemplateColumns: ['1fr', '1fr', '1fr 1fr', '1fr 1fr 1fr'],
|
||||
gap: 3,
|
||||
h: 'fit-content'
|
||||
}}
|
||||
>
|
||||
<Zoom>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: ['100%']
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
variant="translucent"
|
||||
sx={{ borderRadius: 'default', px: 4, py: [2, 3, 5] }}
|
||||
>
|
||||
{/* <Icon glyph="sam" size={64} color="#5BC0DE" /> */}
|
||||
<Text variant="lead" as="p">
|
||||
A deeper look at
|
||||
</Text>
|
||||
<Heading as="h2" variant="title">
|
||||
Free hardware for your project
|
||||
</Heading>
|
||||
<br />
|
||||
<Button
|
||||
as="a"
|
||||
href="https://github.com/hackclub/wom"
|
||||
variant="ctaLg"
|
||||
sx={{ mt: 4 }}
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
</Card>
|
||||
</Box>
|
||||
</Zoom>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%'
|
||||
}}
|
||||
>
|
||||
<Zoom delay={200}>
|
||||
<Card
|
||||
variant="translucent"
|
||||
sx={{
|
||||
borderRadius: 'default',
|
||||
px: 4,
|
||||
py: 3,
|
||||
mb: 3
|
||||
}}
|
||||
>
|
||||
<Heading variant="headline">To qualify:</Heading>
|
||||
{/* <BulletItem iconGlyph="checkmark" iconColor="#5BC0DE">
|
||||
Up to $250 grant per person
|
||||
</BulletItem> */}
|
||||
<BulletItem iconGlyph="checkmark" iconColor="#5BC0DE">
|
||||
Be a high schoolers (& younger)
|
||||
</BulletItem>
|
||||
{/* <BulletItem iconGlyph="checkmark" iconColor="#5BC0DE">
|
||||
Share a plan for what you want to build and how much you need (up to $250)
|
||||
</BulletItem> */}
|
||||
<Text sx={{ color: 'muted' }}>
|
||||
If you qualify, share your idea! We're giving out as many grants
|
||||
as possible!
|
||||
</Text>
|
||||
</Card>
|
||||
</Zoom>
|
||||
<Zoom delay={400}>
|
||||
<Card
|
||||
variant="translucent"
|
||||
sx={{
|
||||
borderRadius: 'default',
|
||||
px: 4,
|
||||
py: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: 'fit-content'
|
||||
}}
|
||||
>
|
||||
<Heading variant="headline">
|
||||
Once you have a project idea,
|
||||
</Heading>
|
||||
<Text as="p">
|
||||
figure out the hardware you need and where you can buy it. Share
|
||||
that with us and we'll give you a grant of up to $250.
|
||||
</Text>
|
||||
<Text as="p" mt={3}>
|
||||
It could be your first ever electronics project or your tenth,
|
||||
we want to support you in building whatever you want.
|
||||
</Text>
|
||||
{/* <Text>
|
||||
(& see what other Hack Clubbers, like{' '}
|
||||
<UserMention user="bellesea" />, are building)
|
||||
todo: link a random pr from the repo that is tagged with "accepted"
|
||||
</Text> */}
|
||||
{/* <Button
|
||||
as="a"
|
||||
href="https://github.com/hackclub/wom"
|
||||
variant="outline"
|
||||
sx={{
|
||||
color: 'text',
|
||||
mt: 3
|
||||
}}
|
||||
>
|
||||
See projects ➚
|
||||
</Button> */}
|
||||
</Card>
|
||||
</Zoom>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%'
|
||||
}}
|
||||
>
|
||||
<Zoom delay={600}>
|
||||
<Card
|
||||
variant="translucent"
|
||||
sx={{
|
||||
borderRadius: 'default',
|
||||
px: 4,
|
||||
py: 3,
|
||||
mb: 3,
|
||||
}}
|
||||
>
|
||||
<Heading variant="headline">
|
||||
Receive and spend the grant through Hack Club Bank.
|
||||
</Heading>
|
||||
<BulletItem iconGlyph="bank-account" iconColor="#5BC0DE">
|
||||
Full history and balance stuff on powerful web dashbaord
|
||||
</BulletItem>
|
||||
<BulletItem iconGlyph="card" iconColor="#5BC0DE">
|
||||
Issue yourself a debit card to spend the funds
|
||||
</BulletItem>
|
||||
<BulletItem iconGlyph="explore" iconColor="#5BC0DE">
|
||||
Use transparency mode to spend it in public
|
||||
</BulletItem>
|
||||
</Card>
|
||||
</Zoom>
|
||||
<Zoom delay={800}>
|
||||
<Tilt>
|
||||
<Card
|
||||
as="div"
|
||||
sx={{
|
||||
backgroundColor: 'transparent',
|
||||
backgroundImage:
|
||||
'url("https://cloud-ehtgzdn7u-hack-club-bot.vercel.app/0card.png")',
|
||||
height: ['300px', '500px', '100%', '230px'],
|
||||
backgroundSize: '100%',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
boxShadow: '0 8px 32px rgba(255, 255, 255, 0.0625)',
|
||||
display: ['block', 'block', 'none', 'block']
|
||||
}}
|
||||
/>
|
||||
</Tilt>
|
||||
</Zoom>
|
||||
</Box>
|
||||
<Tilt>
|
||||
<Card
|
||||
as="div"
|
||||
sx={{
|
||||
backgroundColor: 'transparent',
|
||||
backgroundImage:
|
||||
'url("https://cloud-ehtgzdn7u-hack-club-bot.vercel.app/0card.png")',
|
||||
height: ['300px', '500px', '100%', '230px'],
|
||||
backgroundSize: '100%',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
boxShadow: '0 8px 32px rgba(255, 255, 255, 0.0625)',
|
||||
display: ['none', 'none', 'block', 'none']
|
||||
}}
|
||||
/>
|
||||
</Tilt>
|
||||
</Grid>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
function BulletItem({ children, iconGlyph, iconColor, iconSize }) {
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'flex-start',
|
||||
alignItems: 'center',
|
||||
my: 2
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
glyph={iconGlyph}
|
||||
size={iconSize || 36}
|
||||
color={iconColor || 'text'}
|
||||
sx={{
|
||||
flexShrink: '0'
|
||||
}}
|
||||
/>
|
||||
<Text sx={{ ml: 1 }}>{children}</Text>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
function UserMention({ user }) {
|
||||
return (
|
||||
<Box
|
||||
as="span"
|
||||
sx={{
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Text as="a" href={`https://github.com/${user}`}>
|
||||
@{user}
|
||||
</Text>
|
||||
<Avatar
|
||||
src={`https://github.com/${user}.png`}
|
||||
height="24px"
|
||||
width="24px"
|
||||
sx={{ backgroundColor: 'white', ml: 2 }}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
124
components/winter/landing.js
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
import { Box, Heading, Button, Text, Container } from 'theme-ui'
|
||||
// import { gsap } from 'gsap'
|
||||
import { useEffect } from 'react'
|
||||
// import ScrollTrigger from 'gsap/dist/ScrollTrigger'
|
||||
/** @jsxImportSource theme-ui */
|
||||
import Snowfall from 'react-snowfall'
|
||||
import { Fade } from 'react-reveal'
|
||||
import Rsvp from './rsvp'
|
||||
import ScrollHint from '../scroll-hint'
|
||||
import useSWR from 'swr'
|
||||
import fetcher from '../../lib/fetcher'
|
||||
|
||||
export default function Landing({ rsvpCount }) {
|
||||
// useEffect(() => {
|
||||
// if (typeof window !== 'undefined') {
|
||||
// gsap.registerPlugin(ScrollTrigger)
|
||||
// gsap.to('.box', {
|
||||
// scrollTrigger: {
|
||||
// trigger: '.box',
|
||||
// start: 'top center',
|
||||
// end: 'top 100%',
|
||||
// scrub: true,
|
||||
// markers: true,
|
||||
// }, // start the animation when ".box" enters the viewport (once)
|
||||
// x: 600,
|
||||
// ease: 'none',
|
||||
// duration: 5
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
|
||||
return (
|
||||
<Box sx={{ position: 'relative' }}>
|
||||
{/* <img
|
||||
src="https://cloud-mvlym308h-hack-club-bot.vercel.app/0cloud_2.png"
|
||||
width="200px"
|
||||
height="auto"
|
||||
class="box"
|
||||
sx={{ zIndex: 3, position: 'absolute', top: '10%', left: '60%' }}
|
||||
/>
|
||||
<img
|
||||
src="https://cloud-mvlym308h-hack-club-bot.vercel.app/1cloud_1.png"
|
||||
width="200px"
|
||||
height="auto"
|
||||
class="box"
|
||||
sx={{ zIndex: 3, position: 'absolute', top: '20%', left: '80%' }}
|
||||
/>
|
||||
<img
|
||||
src="https://cloud-mvlym308h-hack-club-bot.vercel.app/1cloud_1.png"
|
||||
width="200px"
|
||||
height="auto"
|
||||
class="box"
|
||||
sx={{ zIndex: 3, position: 'absolute', top: '40%', left: '40%' }}
|
||||
/> */}
|
||||
<Box
|
||||
sx={{
|
||||
background:
|
||||
'url(https://cloud-6h53svh6x-hack-club-bot.vercel.app/0group_5.png), linear-gradient(0deg, #3561A4 0%, #338EDA 100%)',
|
||||
backgroundPosition: 'bottom center',
|
||||
backgroundSize: ['200%', '150%', '100%'],
|
||||
backgroundRepeat: 'no-repeat',
|
||||
width: '100vw',
|
||||
height: '85vh',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
zIndex: 2
|
||||
}}
|
||||
>
|
||||
<Snowfall />
|
||||
<Box>
|
||||
<Box
|
||||
sx={{
|
||||
backdropFilter: 'blur(1.5px)',
|
||||
maxWidth: 'container'
|
||||
}}
|
||||
>
|
||||
<Fade left cascade>
|
||||
<Heading
|
||||
variant="eyebrow"
|
||||
sx={{
|
||||
color: 'sunken'
|
||||
// fontSize: ['18px', '20px', '24px']
|
||||
}}
|
||||
>
|
||||
{rsvpCount} more RSVPs till the start of a hacker's
|
||||
</Heading>
|
||||
</Fade>
|
||||
<Fade left cascade>
|
||||
<Heading
|
||||
as="h1"
|
||||
variant="ultratitle"
|
||||
sx={{
|
||||
color: 'white',
|
||||
textShadow: '0 0 16px rgba(0, 0, 0, 0.2)'
|
||||
}}
|
||||
>
|
||||
Winter Hardware <br />
|
||||
Wonderland
|
||||
</Heading>
|
||||
</Fade>
|
||||
{/* <Container variant="copy">
|
||||
<Text
|
||||
variant="subtitle"
|
||||
as="p"
|
||||
sx={{
|
||||
color: 'white',
|
||||
textShadow: '2px 2px 10px rgba(0, 0, 0, 1)',
|
||||
pt: 2
|
||||
}}
|
||||
>
|
||||
Get up to $250 in grant money build a hardware project this
|
||||
winter alongside hundreds of other hackers.
|
||||
</Text>
|
||||
</Container> */}
|
||||
<Rsvp />
|
||||
</Box>
|
||||
{/* <ScrollHint sx={{mt: 3}} /> */}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
308
components/winter/projects.js
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
import React, { useState } from 'react'
|
||||
import styled from '@emotion/styled'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Flex,
|
||||
Heading,
|
||||
Card,
|
||||
Grid,
|
||||
Link as A,
|
||||
Text,
|
||||
Avatar,
|
||||
Image
|
||||
} from 'theme-ui'
|
||||
import Photo from '../../components/photo'
|
||||
import NextImage from 'next/image'
|
||||
import Marquee from 'react-marquee-slider'
|
||||
import Photo1 from '../../public/winter/1.jpeg'
|
||||
import Photo2 from '../../public/winter/2.png'
|
||||
import Photo3 from '../../public/winter/3.jpeg'
|
||||
import Photo4 from '../../public/winter/4.jpeg'
|
||||
import Photo5 from '../../public/winter/5.jpeg'
|
||||
import Photo6 from '../../public/winter/6.jpeg'
|
||||
import Photo7 from '../../public/winter/7.jpeg'
|
||||
import Photo8 from '../../public/winter/8.jpeg'
|
||||
import Photo9 from '../../public/winter/9.jpeg'
|
||||
import Photo10 from '../../public/winter/10.jpeg'
|
||||
import Photo12 from '../../public/winter/12.jpeg'
|
||||
import Photo13 from '../../public/winter/13.jpeg'
|
||||
import Photo14 from '../../public/winter/14.jpeg'
|
||||
import Photo15 from '../../public/winter/15.jpeg'
|
||||
import Photo16 from '../../public/winter/16.jpeg'
|
||||
import Photo17 from '../../public/winter/17.jpeg'
|
||||
import Photo18 from '../../public/winter/18.jpeg'
|
||||
import Photo19 from '../../public/winter/19.jpeg'
|
||||
import Photo20 from '../../public/winter/20.jpeg'
|
||||
import Photo21 from '../../public/winter/21.jpeg'
|
||||
import Photo22 from '../../public/winter/22.jpeg'
|
||||
import Photo23 from '../../public/winter/23.jpeg'
|
||||
import Photo24 from '../../public/winter/24.jpeg'
|
||||
import Photo25 from '../../public/winter/25.jpeg'
|
||||
import Photo26 from '../../public/winter/26.jpeg'
|
||||
import Photo27 from '../../public/winter/27.jpeg'
|
||||
import Photo28 from '../../public/winter/28.jpeg'
|
||||
import Photo29 from '../../public/winter/29.jpeg'
|
||||
import Photo30 from '../../public/winter/30.jpeg'
|
||||
import Photo31 from '../../public/winter/31.png'
|
||||
|
||||
/** @jsxImportSource theme-ui */
|
||||
|
||||
const Header = styled(Box)`
|
||||
background: url('/pattern.svg');
|
||||
`
|
||||
|
||||
const Sheet = styled(Card)`
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
color: white;
|
||||
`
|
||||
Sheet.defaultProps = {
|
||||
sx: {
|
||||
bg: 'rgba(255, 255, 255, 0.875)',
|
||||
p: [3, 4],
|
||||
color: 'black',
|
||||
width: 1,
|
||||
mb: 4
|
||||
}
|
||||
}
|
||||
|
||||
Sheet.defaultProps = {
|
||||
sx: {
|
||||
maxWidth: '52rem',
|
||||
fontSize: 3,
|
||||
p: [4, 5],
|
||||
color: 'white'
|
||||
}
|
||||
}
|
||||
const PhotoRow = ({ photos }) => (
|
||||
<Box sx={{ height: '200px', overflow: 'hidden' }}>
|
||||
<Box sx={{ display: ['block', 'block', 'block', 'block', 'none'] }}>
|
||||
<Marquee velocity={12}>
|
||||
{photos.map((photo, index) => (
|
||||
<NextImage
|
||||
placeholder="blur"
|
||||
src={photo}
|
||||
objectFit="cover"
|
||||
className="next-image"
|
||||
height="200px"
|
||||
width="300px"
|
||||
alt="Hack Club students"
|
||||
key={'image-' + index}
|
||||
/>
|
||||
))}
|
||||
</Marquee>
|
||||
</Box>
|
||||
<Box sx={{ display: ['none', 'none', 'none', 'none', 'block'] }}>
|
||||
<Marquee velocity={12}>
|
||||
{photos.map((photo, index) => (
|
||||
<NextImage
|
||||
placeholder="blur"
|
||||
src={photo}
|
||||
objectFit="cover"
|
||||
className="next-image"
|
||||
height="200px"
|
||||
width="600px"
|
||||
key={'image-' + index}
|
||||
alt="Hack Club students"
|
||||
/>
|
||||
))}
|
||||
</Marquee>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
|
||||
const Cards = ({ avatar, username, description, image }) => {
|
||||
return (
|
||||
<Card
|
||||
className="post"
|
||||
sx={{ p: [3, 3], width: '100%', background: 'rgba(225,225,225,0.9)' }}
|
||||
>
|
||||
<Flex
|
||||
as="a"
|
||||
href={username != 'cjmika110'? `https://scrapbook.hackclub.com/${username}`: 'https://scrapbook.hackclub.com' }
|
||||
sx={{
|
||||
color: 'inherit',
|
||||
textDecoration: 'none',
|
||||
alignItems: 'center',
|
||||
mb: 2
|
||||
}}
|
||||
>
|
||||
<Avatar loading="lazy" src={avatar} alt="" mr={2} />
|
||||
<Box>
|
||||
<Text variant="subheadline" my={0} fontSize={[1, 1]}>
|
||||
@{username}
|
||||
</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Text
|
||||
as="p"
|
||||
sx={{
|
||||
fontSize: 1,
|
||||
textAlign: 'left',
|
||||
mb: 2,
|
||||
a: {
|
||||
color: 'primary',
|
||||
wordBreak: 'break-all',
|
||||
wordWrap: 'break-word'
|
||||
},
|
||||
'> div': { width: 18, height: 18 }
|
||||
}}
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '200px',
|
||||
overflow: 'hidden',
|
||||
backgroundImage: `url('${image}')`,
|
||||
backgroundSize: '100%',
|
||||
backgroundPosition: 'bottom center',
|
||||
backgroundRepeat: 'no-repeat'
|
||||
}}
|
||||
>
|
||||
{/* <img src={image} sx={{ width: '100%' }} /> */}
|
||||
</Box>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Projects() {
|
||||
const [count, setCount] = useState(0)
|
||||
|
||||
let list = [
|
||||
'mechanical keyboard',
|
||||
'3D printer',
|
||||
'drone',
|
||||
'CNC machine',
|
||||
'pixel art display',
|
||||
'camera'
|
||||
]
|
||||
|
||||
if (count == list.length - 1) {
|
||||
setCount(0)
|
||||
}
|
||||
|
||||
let project_idea = list[count]
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Header sx={{ position: 'relative' }}>
|
||||
<Box
|
||||
sx={{
|
||||
background: 'rgba(0,0,0, 0.8)',
|
||||
zIndex: 1,
|
||||
position: 'relative',
|
||||
color: 'white!important',
|
||||
height: ['auto', '800px', '800px']
|
||||
}}
|
||||
pt={[5, 5, '50px']}
|
||||
pb={[5, 0, 0]}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
maxWidth: '64rem',
|
||||
mx: 'auto',
|
||||
zIndex: 1,
|
||||
position: 'relative'
|
||||
}}
|
||||
align="center"
|
||||
py={2}
|
||||
px={[1, 3]}
|
||||
>
|
||||
<Container sx={{ maxWidth: '48rem' }}>
|
||||
<Heading
|
||||
variant="title"
|
||||
sx={{
|
||||
textShadow: '0px 0px 21px #E1F1FF',
|
||||
color: 'white',
|
||||
fontSize: [4, 5, 6]
|
||||
}}
|
||||
>
|
||||
You could be building a{' '}
|
||||
<Text
|
||||
sx={{
|
||||
backgroundColor: '#406BAB',
|
||||
py: 2,
|
||||
px: 3,
|
||||
borderRadius: 10,
|
||||
position: 'relative',
|
||||
lineHeight: '1.5'
|
||||
}}
|
||||
onClick={() => setCount(count + 1)}
|
||||
>
|
||||
<Box
|
||||
as="span"
|
||||
sx={{ whiteSpace: 'nowrap', cursor: 'pointer' }}
|
||||
>
|
||||
{project_idea}
|
||||
</Box>
|
||||
<Image
|
||||
src="https://cloud-ohzuz4m3t-hack-club-bot.vercel.app/0click_me.svg"
|
||||
alt="click me"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: -3,
|
||||
right: -4
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
</Heading>
|
||||
<Grid columns={[1, 3, 3]} mt={4} mx={['5vw', 'auto', 'auto']}>
|
||||
<Cards
|
||||
avatar="https://scrapbook.hackclub.com/_next/image?url=https://avatars.slack-edge.com/2022-12-04/4449277732855_bc5a70015c4b2146cdec_192.jpg&w=640&q=75"
|
||||
username="sampoder"
|
||||
description="today i presented.. the *CLIMATATOR*! it’s a 4D interactive media experience / climate change simulator that showcases the effects of climate change to a younger audience..."
|
||||
image="https://cloud-lwd22jmab-hack-club-bot.vercel.app/420210303_154846.jpg"
|
||||
/>
|
||||
<Cards
|
||||
avatar="https://scrapbook.hackclub.com/_next/image?url=https://avatars.slack-edge.com/2022-07-26/3865494839057_a471d7e9c871ca9121ea_192.png&w=640&q=75"
|
||||
username="maggie"
|
||||
description="working on something…"
|
||||
image="https://image.mux.com/50200NTyKdeFIayts00oUjauhMTTfQiOPgVn9Xm00mE1aS8/thumbnail.jpg?width=512&fit_mode=pad&time=0"
|
||||
/>
|
||||
<Cards
|
||||
avatar="https://www.gravatar.com/avatar/04484b2178b8fd17c5a529c54614e14c?d=identicon&r=pg"
|
||||
username="cjmika110"
|
||||
description="Tired of QWERTY keyboards? Is typing too intuitive for you? Karl the Keyboard is a portable, squishable, fun, easy- to-use binary keyboard! Instead of pressing keys, you move a joystick up and down to represent ones..."
|
||||
image="https://assemble-images.hackclub.com/a34cbf72-7023-424a-8239-abf4146529e8-Untitled%20drawing%20(1).png"
|
||||
/>
|
||||
</Grid>
|
||||
<Button
|
||||
as="a"
|
||||
variant="cta"
|
||||
href="https://scrapbook.hackclub.com/"
|
||||
sx={{
|
||||
background:
|
||||
'linear-gradient(32deg, rgba(51, 142, 218, 0.9) 0%, rgba(51, 214, 166, 0.9) 100%)',
|
||||
mt: 2
|
||||
}}
|
||||
>
|
||||
Keep exploring →
|
||||
</Button>
|
||||
</Container>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
zIndex: 0,
|
||||
width: '100%',
|
||||
display: ['none', 'block', 'block']
|
||||
}}
|
||||
>
|
||||
<PhotoRow photos={[Photo1, Photo2, Photo3, Photo4, Photo5]} />
|
||||
<PhotoRow photos={[Photo6, Photo7, Photo8, Photo9, Photo10]} />
|
||||
<PhotoRow photos={[Photo21, Photo12, Photo13, Photo14, Photo15]} />
|
||||
<PhotoRow photos={[Photo16, Photo17, Photo18, Photo19, Photo20]} />
|
||||
</Box>
|
||||
</Header>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
100
components/winter/recap.js
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import { Box, Button, Container, Heading, Grid, Card, Text } from 'theme-ui'
|
||||
import { Slide, Zoom } from 'react-reveal'
|
||||
import BreakdownBox from './breakdown-box'
|
||||
import Signup from './form'
|
||||
|
||||
function Recap() {
|
||||
return (
|
||||
<>
|
||||
<Container sx={{ py: 5 }}>
|
||||
<Slide>
|
||||
<Heading
|
||||
variant="headline"
|
||||
sx={{
|
||||
textShadow: '0px 0px 21px #E1F1FF',
|
||||
color: 'white',
|
||||
fontSize: [3, 4, 5],
|
||||
pb: 4,
|
||||
maxWidth: '90%'
|
||||
}}
|
||||
>
|
||||
Make your ideas real this winter, with electronics and Hack Club
|
||||
friends.{' '}
|
||||
</Heading>
|
||||
</Slide>
|
||||
<Grid gap={[2, 2, 3]} columns={[1, 1, 3, 3]} pb={4}>
|
||||
<BreakdownBox
|
||||
icon="event-code"
|
||||
text="10 days"
|
||||
description="of building with other teenagers around the world"
|
||||
delay="100"
|
||||
bg="blue"
|
||||
/>
|
||||
<BreakdownBox
|
||||
icon="payment-transfer"
|
||||
text="$250"
|
||||
description="grants instantly transferred through Hack Club Bank"
|
||||
delay="200"
|
||||
bg="blue"
|
||||
/>
|
||||
<Zoom delay="300">
|
||||
<Card
|
||||
variant="translucent"
|
||||
sx={{
|
||||
borderRadius: 'default',
|
||||
px: 3,
|
||||
pb: 4,
|
||||
pt: 2,
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
variant="subtitle"
|
||||
sx={{
|
||||
fontWeight: 'bold',
|
||||
color: 'blue',
|
||||
textShadow: '0px 0px 21px #ffffff'
|
||||
}}
|
||||
>
|
||||
Open a Demo Account
|
||||
</Text>
|
||||
<Text variant="caption">
|
||||
While you wait for your hardware, explore and get familiar with
|
||||
Hack Club Bank with limited access to features until you get
|
||||
fully activated.
|
||||
</Text>
|
||||
<Signup />
|
||||
</Card>
|
||||
</Zoom>
|
||||
{/* <Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'left'
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="outlineLg"
|
||||
sx={{
|
||||
color: 'white',
|
||||
mt: 3
|
||||
}}
|
||||
as="a"
|
||||
href="https://github.com/hackclub/wom"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
</Box> */}
|
||||
</Grid>
|
||||
<Button variant="ctaLg" as="a" href="#apply" style={{ zIndex: '100', textAlign: 'center' }}>
|
||||
RSVP
|
||||
</Button>
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Recap
|
||||
137
components/winter/rsvp.js
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import Icon from '@hackclub/icons'
|
||||
import { useRef, useState } from 'react'
|
||||
import {
|
||||
Box,
|
||||
Label,
|
||||
Input,
|
||||
Button,
|
||||
Text,
|
||||
Alert,
|
||||
Card,
|
||||
Heading,
|
||||
Grid
|
||||
} from 'theme-ui'
|
||||
|
||||
const Loading = () => (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
border: '2px solid #f3f3f3',
|
||||
borderTop: '2px solid #ec3750',
|
||||
borderRadius: '50%',
|
||||
width: '10px',
|
||||
height: '10px',
|
||||
animation: 'spin 2s linear infinite',
|
||||
'@keyframes spin': {
|
||||
'0%': { transform: 'rotate(0deg)' },
|
||||
'100%': { transform: 'rotate(360deg)' }
|
||||
}
|
||||
}}
|
||||
></Box>
|
||||
)
|
||||
|
||||
const Rsvp = () => {
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
const formRef = useRef(null)
|
||||
|
||||
const handleSubmit = async e => {
|
||||
e.preventDefault()
|
||||
setSubmitting(true)
|
||||
|
||||
await fetch('/api/winter-rsvp', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
Name: e.target.name.value,
|
||||
Email: e.target.email.value
|
||||
})
|
||||
})
|
||||
|
||||
formRef.current.reset()
|
||||
setSubmitting(false)
|
||||
|
||||
setSubmitted(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
maxWidth: 'narrowPlus',
|
||||
mx: 'auto',
|
||||
mt: [3, 4],
|
||||
background: 'rgb(255,255,255, 0.45)',
|
||||
backdropFilter: 'blur(8px)'
|
||||
}}
|
||||
>
|
||||
<Heading as="h2" variant="subheadline" sx={{ mb: 1 }}>
|
||||
Get up to $250 to build a hardware project this winter.
|
||||
</Heading>
|
||||
<Text sx={{ color: 'muted' }}>
|
||||
RSVP to get notified when applications open.
|
||||
</Text>
|
||||
<Grid
|
||||
as="form"
|
||||
ref={formRef}
|
||||
onSubmit={handleSubmit}
|
||||
gap={[2, 3]}
|
||||
sx={{
|
||||
mt: [null, 3],
|
||||
gridTemplateColumns: [null, '1fr 1fr auto'],
|
||||
textAlign: 'left',
|
||||
alignItems: 'end',
|
||||
input: { bg: 'sunken' }
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<Label htmlFor="location">Name</Label>
|
||||
<Input
|
||||
autofillBackgroundColor="highlight"
|
||||
type="text"
|
||||
name="name"
|
||||
id="name"
|
||||
placeholder="Fiona Hackworth"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
autofillBackgroundColor="highlight"
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
placeholder="fiona@hackclub.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button type="submit" sx={{ mt: [2, 0] }}>
|
||||
{submitting ? (
|
||||
<>
|
||||
<Loading />
|
||||
RSVP
|
||||
</>
|
||||
) : (
|
||||
'RSVP'
|
||||
)}
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
{submitted && (
|
||||
<Alert variant="primary" sx={{ bg: 'green', mt: [2, 3] }}>
|
||||
<Icon glyph="send" />
|
||||
<Text sx={{ ml: 2 }}>Signed up!</Text>
|
||||
</Alert>
|
||||
)}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default Rsvp
|
||||
128
components/winter/timeline.js
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
import { Box, Flex, Container, Text, Badge, Link } from 'theme-ui'
|
||||
import { Slide } from 'react-reveal'
|
||||
import Icon from '../icon'
|
||||
|
||||
function TimelineStep({ children }) {
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
marginX: 4,
|
||||
paddingY: 4,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
'&:before': {
|
||||
content: '""',
|
||||
background: 'snow',
|
||||
height: ['420px', '320px', '320px'],
|
||||
width: '4px',
|
||||
marginLeft: 36,
|
||||
position: 'absolute',
|
||||
zIndex: 0
|
||||
},
|
||||
'&:first-of-type:before': {
|
||||
top: [0, null, 'auto'],
|
||||
width: [0, null, 0],
|
||||
left: [0, null, 0]
|
||||
},
|
||||
'&:last-of-type:before': {
|
||||
bottom: [0, null, 'auto'],
|
||||
left: [0, null, 0],
|
||||
width: [0, null, 0]
|
||||
}
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
function Circle({ children }) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
p: 14,
|
||||
background: 'red',
|
||||
|
||||
color: 'white',
|
||||
backgroundImage:
|
||||
'radial-gradient(ellipse farthest-corner at top left, #5bc0de, #338eda)',
|
||||
borderRadius: '100%',
|
||||
display: 'inline-block',
|
||||
lineHeight: 0,
|
||||
position: 'relative',
|
||||
zIndex: 999
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
function Step({ icon, name, duration, href }) {
|
||||
return (
|
||||
<TimelineStep sx={{ pb: 1 }}>
|
||||
<Slide left>
|
||||
<Circle>
|
||||
{href ? (
|
||||
<Link href={href} sx={{ cursor: 'pointer', zIndex: 999 }}>
|
||||
<Icon glyph={icon} size={48} color="white" />
|
||||
</Link>
|
||||
) : (
|
||||
<Icon glyph={icon} size={48} />
|
||||
)}
|
||||
</Circle>
|
||||
<Container
|
||||
sx={{
|
||||
mt: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'left',
|
||||
flexDirection: 'column',
|
||||
textAlign: 'left'
|
||||
}}
|
||||
>
|
||||
<Badge
|
||||
variant="pill"
|
||||
sx={{
|
||||
bg: 'smoke',
|
||||
color: 'darker',
|
||||
fontWeight: 'normal',
|
||||
textTransform: 'uppercase',
|
||||
width: 'fit-content',
|
||||
fontSize: 18,
|
||||
px: 3
|
||||
}}
|
||||
>
|
||||
{duration}
|
||||
</Badge>
|
||||
<Text
|
||||
sx={{ color: 'white', fontSize: 24, maxWidth: [300, null, 550] }}
|
||||
>
|
||||
{name}
|
||||
</Text>
|
||||
</Container>
|
||||
</Slide>
|
||||
</TimelineStep>
|
||||
)
|
||||
}
|
||||
|
||||
export default function RealTimeline() {
|
||||
return (
|
||||
<Flex sx={{ flexDirection: 'column', justifyContent: 'center', pb: 4 }}>
|
||||
<Step
|
||||
icon="post"
|
||||
name="Instructions sent out on how to submit your hardware plan to qualify for the grant."
|
||||
duration="When we reach 500 RSVPs"
|
||||
/>
|
||||
<Step
|
||||
icon="send"
|
||||
name="Deadline for sharing your hardware plan. Make sure to order your hardware by this time!"
|
||||
duration="January 15"
|
||||
/>
|
||||
<Step
|
||||
icon="slack"
|
||||
name="Start of a 10 days building in public challenge where you share daily updates on your hardware project"
|
||||
duration="February 15"
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
|
@ -74,6 +74,11 @@ const nextConfig = {
|
|||
destination: '/bank/first/',
|
||||
permanent: false
|
||||
},
|
||||
{
|
||||
source: '/wom/',
|
||||
destination: '/winter/',
|
||||
permanent: false
|
||||
},
|
||||
{ source: '/workshops/slack/', destination: '/slack/', permanent: true },
|
||||
{ source: '/community/', destination: '/slack/', permanent: true },
|
||||
{ source: '/hack_camp/', destination: '/camp/', permanent: true },
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
"axios": "^1.2.0",
|
||||
"country-list-js": "^3.1.7",
|
||||
"globby": "^11.0.4",
|
||||
"gsap": "^3.11.3",
|
||||
"jquery": "^3.6.1",
|
||||
"lodash": "^4.17.21",
|
||||
"next": "^12.3.1",
|
||||
|
|
|
|||
35
pages/api/winter-rsvp.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import AirtablePlus from 'airtable-plus'
|
||||
|
||||
const airtable = new AirtablePlus({
|
||||
baseID: 'app1o9tRo6XulLnsr',
|
||||
apiKey: process.env.AIRTABLE_API_KEY,
|
||||
tableName: 'rsvp'
|
||||
})
|
||||
|
||||
export default async function handler(req, res) {
|
||||
if (req.method === 'POST') {
|
||||
const rsvp = await airtable.create({
|
||||
Name: req.body.Name,
|
||||
Email: req.body.Email,
|
||||
IP: req.headers['x-forwarded-for'] || req.socket.remoteAddress
|
||||
})
|
||||
const url = process.env.WOM_SLACK_WEBHOOK_URL
|
||||
const body = JSON.stringify({
|
||||
rsvp
|
||||
})
|
||||
fetch(url, {
|
||||
body,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(res => res.status(200).json({ success: true }))
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
res.json({ status: 'Something went wrong', error })
|
||||
})
|
||||
} else {
|
||||
res.status(405).json({ status: 'error', error: 'Must send POST request' })
|
||||
}
|
||||
}
|
||||
|
|
@ -126,10 +126,10 @@ const Page = () => (
|
|||
priority
|
||||
/>
|
||||
<Announcement
|
||||
copy="Epoch: celebrate the New Year with Hack Club."
|
||||
caption="Join 150+ hackers in Delhi for a magical high-school hackathon!"
|
||||
href="https://epoch.hackclub.com"
|
||||
iconLeft="explore"
|
||||
copy="Join the community for a winter of hardware hacking."
|
||||
caption="Get a grant of up to $250 to build an electronics project."
|
||||
href="/winter"
|
||||
iconLeft="idea"
|
||||
color="primary"
|
||||
/>
|
||||
|
||||
|
|
@ -464,10 +464,10 @@ const Page = () => (
|
|||
name="Tools to hack on"
|
||||
desc={
|
||||
<>
|
||||
We build tools, such as{" "}
|
||||
<a href="https://sprig.hackclub.com">Sprig</a>, that your members can
|
||||
use to make projects with in meetings! Built more of them with us in our
|
||||
{" "}<Link href="/slack">Slack community</Link>.
|
||||
We build tools, such as{' '}
|
||||
<a href="https://sprig.hackclub.com">Sprig</a>, that your
|
||||
members can use to make projects with in meetings! Built more of
|
||||
them with us in our <Link href="/slack">Slack community</Link>.
|
||||
</>
|
||||
}
|
||||
></Feature>
|
||||
|
|
|
|||
115
pages/winter.js
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import Head from 'next/head'
|
||||
import Meta from '@hackclub/meta'
|
||||
import Nav from '../components/nav'
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
Heading,
|
||||
Button,
|
||||
Text,
|
||||
Image,
|
||||
Input,
|
||||
Label,
|
||||
Link,
|
||||
Flex
|
||||
} from 'theme-ui'
|
||||
import Snowfall from 'react-snowfall'
|
||||
import Footer from '../components/footer'
|
||||
import FadeIn from '../components/fade-in'
|
||||
import { useState } from 'react'
|
||||
import ForceTheme from '../components/force-theme'
|
||||
import RealTimeline from '../components/winter/timeline'
|
||||
import InfoGrid from '../components/winter/info'
|
||||
import Breakdown from '../components/winter/breakdown'
|
||||
import Projects from '../components/winter/projects'
|
||||
import Landing from '../components/winter/landing'
|
||||
import Recap from '../components/winter/recap'
|
||||
import { Zoom } from 'react-reveal'
|
||||
import useSWR from 'swr'
|
||||
import fetcher from '../lib/fetcher'
|
||||
|
||||
export function Winter() {
|
||||
const { data: rsvps } = useSWR(
|
||||
'http://airbridge.hackclub.com/v0.1/Winter%20Hardware%20Wonderland/rsvp',
|
||||
fetcher,
|
||||
{ refreshInterval: 1000 }
|
||||
)
|
||||
return (
|
||||
<>
|
||||
<Box as="main" sx={{ bg: 'blue' }}>
|
||||
<Meta
|
||||
as={Head}
|
||||
title="Winter Hardware Wonderland"
|
||||
description="Join the Hack Club community for a winter of hardware hacking, and get a $250 grant to build your project."
|
||||
image="/winter/og-image.png" // TODO: add og image
|
||||
/>
|
||||
<Nav light />
|
||||
<Snowfall />
|
||||
<ForceTheme theme="light" />
|
||||
<Landing rsvpCount={500 - rsvps?.length} />
|
||||
<Breakdown />
|
||||
<Projects />
|
||||
<InfoGrid />
|
||||
<Container>
|
||||
<Zoom>
|
||||
<Heading
|
||||
variant="headline"
|
||||
sx={{
|
||||
textShadow: '0px 0px 21px #E1F1FF',
|
||||
color: 'white',
|
||||
fontSize: [3, 4, 5],
|
||||
pb: 4,
|
||||
maxWidth: '90%'
|
||||
}}
|
||||
>
|
||||
You've RSVPed, what's next?
|
||||
</Heading>
|
||||
</Zoom>
|
||||
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: ['column', null, 'row'],
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{ display: 'flex', flexDirection: ['row', null, 'column'] }}
|
||||
>
|
||||
<Zoom>
|
||||
<Heading
|
||||
variant="title"
|
||||
sx={{
|
||||
color: 'white',
|
||||
textTransform: 'uppercase',
|
||||
transform: ['none', null, 'rotate(-90deg)'],
|
||||
textShadow: '0px 0px 21px #E1F1FF'
|
||||
}}
|
||||
>
|
||||
Timeline
|
||||
</Heading>
|
||||
<Image
|
||||
src="https://cloud-lbajgdi3a-hack-club-bot.vercel.app/0fox_1.png"
|
||||
alt="Illustrated orange fox sleeping in a curled position"
|
||||
sx={{
|
||||
width: ['100px', null, '80%'],
|
||||
pt: [null, null, 6],
|
||||
ml: [2, null, null]
|
||||
}}
|
||||
/>
|
||||
</Zoom>
|
||||
</Box>
|
||||
<RealTimeline />
|
||||
</Flex>
|
||||
</Container>
|
||||
{/* Timeline */}
|
||||
|
||||
<Recap />
|
||||
{/* <Signup /> */}
|
||||
<Footer />
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Winter
|
||||
BIN
public/winter/1.jpeg
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
public/winter/10.jpeg
Normal file
|
After Width: | Height: | Size: 352 KiB |
BIN
public/winter/11.gif
Normal file
|
After Width: | Height: | Size: 17 MiB |
BIN
public/winter/12.jpeg
Normal file
|
After Width: | Height: | Size: 576 KiB |
BIN
public/winter/13.jpeg
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
public/winter/14.jpeg
Normal file
|
After Width: | Height: | Size: 416 KiB |
BIN
public/winter/15.jpeg
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/winter/16.jpeg
Normal file
|
After Width: | Height: | Size: 536 KiB |
BIN
public/winter/17.jpeg
Normal file
|
After Width: | Height: | Size: 597 KiB |
BIN
public/winter/18.jpeg
Normal file
|
After Width: | Height: | Size: 517 KiB |
BIN
public/winter/19.jpeg
Normal file
|
After Width: | Height: | Size: 538 KiB |
BIN
public/winter/2.png
Normal file
|
After Width: | Height: | Size: 10 MiB |
BIN
public/winter/20.jpeg
Normal file
|
After Width: | Height: | Size: 330 KiB |
BIN
public/winter/21.jpeg
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
public/winter/22.jpeg
Normal file
|
After Width: | Height: | Size: 301 KiB |
BIN
public/winter/23.jpeg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
public/winter/24.jpeg
Normal file
|
After Width: | Height: | Size: 937 KiB |
BIN
public/winter/25.jpeg
Normal file
|
After Width: | Height: | Size: 802 KiB |
BIN
public/winter/26.jpeg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/winter/27.jpeg
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
public/winter/28.jpeg
Normal file
|
After Width: | Height: | Size: 978 KiB |
BIN
public/winter/29.jpeg
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
public/winter/3.jpeg
Normal file
|
After Width: | Height: | Size: 671 KiB |
BIN
public/winter/30.jpeg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
public/winter/31.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
public/winter/4.jpeg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
public/winter/5.jpeg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
public/winter/6.jpeg
Normal file
|
After Width: | Height: | Size: 997 KiB |
BIN
public/winter/7.jpeg
Normal file
|
After Width: | Height: | Size: 349 KiB |
BIN
public/winter/8.jpeg
Normal file
|
After Width: | Height: | Size: 544 KiB |
BIN
public/winter/9.jpeg
Normal file
|
After Width: | Height: | Size: 613 KiB |
|
|
@ -2537,6 +2537,11 @@ grapheme-splitter@^1.0.4:
|
|||
resolved "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz"
|
||||
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
|
||||
|
||||
gsap@^3.11.3:
|
||||
version "3.11.3"
|
||||
resolved "https://registry.yarnpkg.com/gsap/-/gsap-3.11.3.tgz#ca5be827f56fe8d5720e08343390f74fb89a05f3"
|
||||
integrity sha512-xc/iIJy+LWiMbRa4IdMtdnnKa/7PXEK6NNzV71gdOYUVeTZN7UWnLU0fB7Hi1iwiz4ZZoYkBZPPYGg+2+zzFHA==
|
||||
|
||||
har-schema@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz"
|
||||
|
|
|
|||