Merge branch 'main' into onboard_gallery
32
.github/workflows/caniuse-update.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
name: Update Browserslist database
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 2 1,15 * *'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-browserslist-database:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config --global user.email "action@github.com"
|
||||
git config --global user.name "GitHub Action"
|
||||
- name: Update Browserslist database and create PR if applies
|
||||
uses: c2corg/browserslist-update-action@v2
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: browserslist-update
|
||||
base_branch: main
|
||||
commit_message: 'build: update Browserslist db'
|
||||
title: 'build: update Browserslist db'
|
||||
body: Auto-generated by [browserslist-update-action](https://github.com/c2corg/browserslist-update-action/). Caniuse database has been updated. Review changes, merge this PR, and be merry.
|
||||
7
.prettierrc
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"arrowParens": "avoid",
|
||||
"printWidth": 80,
|
||||
"semi": false
|
||||
}
|
||||
|
|
@ -3,7 +3,8 @@ import Icon from '@hackclub/icons'
|
|||
import { useState } from 'react'
|
||||
|
||||
export default function Bio({ popup = true, spanTwo = false, ...props }) {
|
||||
let { img, name, teamRole, pronouns, text, subrole, href, video } = props
|
||||
let { img, name, teamRole, pronouns, text, subrole, email, href, video } =
|
||||
props
|
||||
const [expand, setExpand] = useState(false)
|
||||
return (
|
||||
<>
|
||||
|
|
@ -94,6 +95,13 @@ export default function Bio({ popup = true, spanTwo = false, ...props }) {
|
|||
)}
|
||||
</Text>
|
||||
</Flex>
|
||||
{!popup && email && (
|
||||
<Text color="muted" as={'a'} href={`mailto:${email}@hackclub.com`}>
|
||||
{email}@hackclub.com
|
||||
<br />
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{!popup && (
|
||||
<>
|
||||
<Text mt={2} mb={0} color="black">
|
||||
|
|
|
|||
37
components/fiscal-sponsorship/apply/checkbox.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import Icon from '../../icon'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Checkbox({ name, defaultChecked = false, size = 38 }) {
|
||||
const [checked, setChecked] = useState(defaultChecked)
|
||||
const toggle = () => setChecked(!checked)
|
||||
const router = useRouter()
|
||||
|
||||
/* Fill in the field with the value from sessionStorage.
|
||||
For other input elements, the value is set in the Field component,
|
||||
but these checkboxes hold their state in useState rather than in the DOM. */
|
||||
useEffect(() => {
|
||||
const value = router.query[name] || sessionStorage.getItem('bank-signup-' + name)
|
||||
if (value) {
|
||||
const input = document.getElementById(name)
|
||||
input && setChecked(!!value)
|
||||
}
|
||||
}, [router.query, name])
|
||||
|
||||
return (
|
||||
<>
|
||||
<input aria-hidden="true" type="hidden" value={checked} name={name} />
|
||||
<Icon
|
||||
glyph={checked ? 'checkmark' : 'checkbox'}
|
||||
size={size}
|
||||
id={name}
|
||||
name={name}
|
||||
aria-checked={checked}
|
||||
role="checkbox"
|
||||
tabindex="0"
|
||||
onClick={() => toggle()}
|
||||
onKeyDown={e => e.key === 'Enter' && toggle()}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
import { Input, Select, Textarea } from 'theme-ui'
|
||||
// import Checkbox from './checkbox'
|
||||
import Checkbox from './checkbox'
|
||||
import Field from './field'
|
||||
// This is using country-list instead of country-list-js as it has a smaller bundle size
|
||||
import { getNames } from 'country-list'
|
||||
|
|
@ -54,10 +54,10 @@ export default function OrganizationInfoForm({ requiredFields }) {
|
|||
))}
|
||||
</Select>
|
||||
</Field>
|
||||
{/* <Field
|
||||
<Field
|
||||
name="transparent"
|
||||
label="Transparency mode"
|
||||
col={false}
|
||||
col={true}
|
||||
description={`
|
||||
Transparent accounts’ balances and donations are public.
|
||||
You choose who has access to personal details.
|
||||
|
|
@ -67,7 +67,7 @@ export default function OrganizationInfoForm({ requiredFields }) {
|
|||
requiredFields={requiredFields}
|
||||
>
|
||||
<Checkbox defaultChecked={true} name="transparent" />
|
||||
</Field> */}
|
||||
</Field>
|
||||
<Field
|
||||
name="eventDescription"
|
||||
label={`Tell us about your ${org.toLowerCase()}`}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ export default function PersonalInfoForm({ requiredFields }) {
|
|||
<div />
|
||||
<Field
|
||||
label="Your Hack Club Slack username"
|
||||
description="For teenagers only!"
|
||||
name="slackUsername"
|
||||
requiredFields={requiredFields}
|
||||
>
|
||||
|
|
@ -111,7 +112,7 @@ export default function PersonalInfoForm({ requiredFields }) {
|
|||
name="userPhone"
|
||||
id="userPhone"
|
||||
type="tel"
|
||||
placeholder="1-855-625-HACK"
|
||||
placeholder="+1 (844) 237 2290"
|
||||
/>
|
||||
</Field>
|
||||
<Field
|
||||
|
|
|
|||
36
components/fiscal-sponsorship/contact.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import Icon from '../icon'
|
||||
import { Flex, Link, Text } from 'theme-ui'
|
||||
|
||||
const phoneNumber = '+1 (844) 237-2290'
|
||||
const phoneNumberUri = '+1-844-237-2290'
|
||||
const email = 'hcb@hackclub.com'
|
||||
|
||||
export default function ContactBanner({ sx }) {
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
bg: 'sunken',
|
||||
color: 'slate',
|
||||
alignItems: 'center',
|
||||
p: 3,
|
||||
gap: [3, 2],
|
||||
...sx
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
glyph="message"
|
||||
sx={{ color: 'inherit', flexShrink: 0, my: -1 }}
|
||||
aria-hidden
|
||||
/>
|
||||
<Text
|
||||
sx={{
|
||||
textWrap: 'balance',
|
||||
a: { color: 'inherit', mx: '0.125em', whiteSpace: 'nowrap' }
|
||||
}}
|
||||
>
|
||||
Questions? Email <Link href={`mailto:${email}`}>{email}</Link>{' '}
|
||||
or call <Link href={`tel:${phoneNumberUri}`}>{phoneNumber}</Link>
|
||||
</Text>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import styled from '@emotion/styled'
|
||||
import { css, keyframes } from '@emotion/react'
|
||||
import { Box, Container, Flex, Link, Text } from 'theme-ui'
|
||||
import { Box, Container, Flex, Link } from 'theme-ui'
|
||||
import theme from '../lib/theme'
|
||||
import Icon from './icon'
|
||||
import Flag from './flag'
|
||||
|
|
@ -68,7 +68,7 @@ const hoverColor = name =>
|
|||
slate: 'black',
|
||||
black: 'slate',
|
||||
primary: 'error'
|
||||
}[name] || 'black')
|
||||
})[name] || 'black'
|
||||
|
||||
const slide = keyframes({
|
||||
from: { transform: 'translateY(-25%)', opacity: 0 },
|
||||
|
|
@ -198,13 +198,13 @@ function Header({ unfixed, color, bgColor, dark, fixed, ...props }) {
|
|||
const baseColor = dark
|
||||
? color || 'white'
|
||||
: color === 'white' && scrolled
|
||||
? 'black'
|
||||
: color
|
||||
? 'black'
|
||||
: color
|
||||
const toggleColor = dark
|
||||
? color || 'snow'
|
||||
: toggled || (color === 'white' && scrolled)
|
||||
? 'slate'
|
||||
: color
|
||||
? 'slate'
|
||||
: color
|
||||
|
||||
return (
|
||||
<Root
|
||||
|
|
|
|||
41
components/onboard/youtube-video.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { useMemo } from "react"
|
||||
|
||||
const YoutubeVideo = ({
|
||||
'youtube-id': youtubeID = 'dQw4w9WgXcQ',
|
||||
list,
|
||||
title = "YouTube video player",
|
||||
width,
|
||||
height,
|
||||
}) => {
|
||||
const src = useMemo(() => {
|
||||
const url = new URL(`https://www.youtube.com/embed/${youtubeID}`)
|
||||
if (list) {
|
||||
url.searchParams.set('list', list)
|
||||
}
|
||||
return url
|
||||
}, [youtubeID, list])
|
||||
|
||||
const allowlist = [
|
||||
'accelerometer',
|
||||
'autoplay',
|
||||
'clipboard-write',
|
||||
'encrypted-media',
|
||||
'gyroscope',
|
||||
'picture-in-picture',
|
||||
'web-share',
|
||||
'fullscreen'
|
||||
].join('; ')
|
||||
|
||||
return (
|
||||
<iframe
|
||||
src={src}
|
||||
title={title}
|
||||
{...{ width, height }}
|
||||
frameborder="0"
|
||||
allow={allowlist}
|
||||
allowfullscreen>
|
||||
</iframe>
|
||||
)
|
||||
}
|
||||
|
||||
export default YoutubeVideo
|
||||
73
components/slack/arrows.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import { VisibilityContext } from 'react-horizontal-scrolling-menu'
|
||||
import { useContext } from 'react'
|
||||
import Icon from '@hackclub/icons'
|
||||
import { Box, Link } from 'theme-ui'
|
||||
|
||||
function Arrow({ direction, disabled, onClick }) {
|
||||
return (
|
||||
<Link
|
||||
onClick={onClick}
|
||||
sx={{
|
||||
borderRadius: 100,
|
||||
boxShadow: 'none',
|
||||
backgroundColor: 'black',
|
||||
padding: '8px',
|
||||
cursor: 'pointer',
|
||||
placeItems: 'center',
|
||||
display: 'flex',
|
||||
mr: 2,
|
||||
opacity: disabled ? '0.5' : '1',
|
||||
pointerEvents: disabled ? 'none' : 'auto',
|
||||
transition: 'opacity 0.3s ease'
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
glyph={direction === 'left' ? 'view-back' : 'view-forward'}
|
||||
size={32}
|
||||
color="white"
|
||||
/>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export function LeftArrow() {
|
||||
const { scrollPrev } =
|
||||
useContext(VisibilityContext)
|
||||
|
||||
const visibility = useContext(VisibilityContext)
|
||||
const isVisible = visibility.useIsVisible("first", false);
|
||||
|
||||
return (
|
||||
<Arrow direction="left" disabled={isVisible} onClick={() => scrollPrev()} />
|
||||
)
|
||||
}
|
||||
|
||||
export function RightArrow() {
|
||||
const { scrollNext } =
|
||||
useContext(VisibilityContext)
|
||||
|
||||
const visibility = useContext(VisibilityContext)
|
||||
const isVisible = visibility.useIsVisible("last", false);
|
||||
|
||||
return (
|
||||
<Arrow direction="right" disabled={isVisible} onClick={() => scrollNext()} />
|
||||
)
|
||||
}
|
||||
|
||||
export default function Arrows() {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
marginBottom: 32,
|
||||
position: 'relative',
|
||||
// this is v janky please ignore, thank you.
|
||||
ml: ['1rem', '1rem', '1rem', 'calc(50vw - 36.5rem)']
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<LeftArrow /> <RightArrow />
|
||||
</div>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
218
components/slack/channels.js
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
import { Badge, Box, Card, Flex, Grid, Heading, Image, Text } from 'theme-ui'
|
||||
import Icon from '@hackclub/icons'
|
||||
import NextLink from 'next/link'
|
||||
import useSWR from 'swr'
|
||||
import fetcher from '../../lib/fetcher'
|
||||
import SlackEvents from './slack-events'
|
||||
|
||||
const withCommas = x => x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
|
||||
export default function Channels() {
|
||||
const { data: millionCount } = useSWR(
|
||||
'https://jia.haas.hackclub.com/api/currentNumber',
|
||||
fetcher,
|
||||
{ refreshInterval: 10_000 }
|
||||
)
|
||||
return (
|
||||
<Grid
|
||||
columns={[2, 9, 15]}
|
||||
gap={3}
|
||||
sx={{
|
||||
py: [3, 4],
|
||||
h3: { my: 0 },
|
||||
'> div': {
|
||||
px: [2, 3],
|
||||
py: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
gridColumn: ['span 1', 'span 3']
|
||||
},
|
||||
a: {
|
||||
position: 'relative',
|
||||
':hover,:focus': {
|
||||
svg: {
|
||||
transform: 'translateX(28px) translateY(-28px)',
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
svg: {
|
||||
position: 'absolute',
|
||||
top: 2,
|
||||
right: 2,
|
||||
fill: 'white',
|
||||
transition: 'transform 0.25s ease-in-out, opacity 0.25s ease-in-out'
|
||||
},
|
||||
h3: {
|
||||
variant: 'text.headline',
|
||||
color: 'white',
|
||||
lineHeight: 'title',
|
||||
m: 0,
|
||||
'+ p': {
|
||||
mt: 2,
|
||||
color: 'white',
|
||||
opacity: 0.75,
|
||||
fontSize: 2,
|
||||
lineHeight: 'caption'
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
as="aside"
|
||||
sx={{
|
||||
gridRow: [null, 'span 2'],
|
||||
gridColumn: ['span 2', 'span 3'],
|
||||
maxHeight: '100%',
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
>
|
||||
<Heading
|
||||
as="h2"
|
||||
variant="subheadline"
|
||||
sx={{
|
||||
mt: 0,
|
||||
mb: 0,
|
||||
color: 'red',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 'headline'
|
||||
}}
|
||||
>
|
||||
Live from our Slack <br />
|
||||
</Heading>
|
||||
<Text
|
||||
as="p"
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontSize: 1,
|
||||
fontWeight: 300,
|
||||
fontStyle: 'italic',
|
||||
mb: '16px'
|
||||
}}
|
||||
>
|
||||
Waiting for more messages...
|
||||
</Text>
|
||||
<SlackEvents />
|
||||
</Box>
|
||||
<NextLink href="/ship" passHref>
|
||||
<Card
|
||||
as="a"
|
||||
variant="interactive"
|
||||
sx={{
|
||||
gridColumn: ['span 2', 'span 5'],
|
||||
bg: 'blue',
|
||||
backgroundImage: t => t.util.gx('cyan', 'blue')
|
||||
}}
|
||||
>
|
||||
<Icon glyph="external" size={24} />
|
||||
<Heading as="h3" variant="headline">
|
||||
#ship
|
||||
</Heading>
|
||||
<Text as="p">Launch your latest projects & get feedback</Text>
|
||||
</Card>
|
||||
</NextLink>
|
||||
<Card
|
||||
as="a"
|
||||
href="https://scrapbook.hackclub.com/"
|
||||
variant="interactive"
|
||||
sx={{
|
||||
gridColumn: ['span 2', 'span 5'],
|
||||
bg: 'dark',
|
||||
backgroundImage: t => t.util.gx('yellow', 'orange')
|
||||
}}
|
||||
>
|
||||
<Icon glyph="external" size={24} />
|
||||
<Heading as="h3" variant="headline">
|
||||
#scrapbook
|
||||
</Heading>
|
||||
<Text as="p">A daily diary of project updates</Text>
|
||||
</Card>
|
||||
<Card
|
||||
bg="red"
|
||||
sx={{
|
||||
gridColumn: ['span 2 !important', 'span 2 !important'],
|
||||
gridRow: ['span 1 !important', 'span 3 !important'],
|
||||
writingMode: ['lr-tb', 'tb-rl']
|
||||
}}
|
||||
>
|
||||
<Heading as="h3">#counttoamillion</Heading>
|
||||
<Text as="p" sx={{ display: 'flex', alignItems: 'baseline' }}>
|
||||
We’re at{' '}
|
||||
<Badge
|
||||
variant="outline"
|
||||
as="span"
|
||||
sx={{ ml: [2, 0], mt: [0, 2], px: [2, 0], py: [0, 2] }}
|
||||
>
|
||||
{millionCount ? withCommas(millionCount.number) : '???'}
|
||||
</Badge>
|
||||
!
|
||||
</Text>
|
||||
</Card>
|
||||
<Card backgroundColor="green">
|
||||
<h3 sx={{ color: 'black' }}>#gamedev</h3>
|
||||
</Card>
|
||||
<Card
|
||||
sx={{
|
||||
backgroundImage:
|
||||
'url(https://cloud-n6i5i4zb9-hack-club-bot.vercel.app/12020-07-25_fqxym71bmqjr1d35btawn5q6ph1zt0mk.png)',
|
||||
backgroundColor: '#FEC62E',
|
||||
backgroundPosition: 'center center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundSize: '100% auto',
|
||||
gridColumn: ['span 2', 'span 3 !important', 'span 4 !important'],
|
||||
h3: { opacity: 0 }
|
||||
}}
|
||||
>
|
||||
<h3>#design</h3>
|
||||
</Card>
|
||||
<Card
|
||||
bg="dark"
|
||||
sx={{ h3: { color: 'green', textShadow: '0 0 4px currentColor' } }}
|
||||
>
|
||||
<h3>#code</h3>
|
||||
</Card>
|
||||
<Card
|
||||
sx={{
|
||||
bg: 'dark',
|
||||
backgroundImage:
|
||||
'url(https://cloud-jnfb0t781-hack-club-bot.vercel.app/02020-07-25_r6thfxwv1u0c71uw0qk94juv6fxxjygf.png)',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
textShadow: 'text',
|
||||
gridColumn: ['span 2 !important', 'span 4 !important']
|
||||
}}
|
||||
>
|
||||
<h3>#photography</h3>
|
||||
</Card>
|
||||
<Card bg="purple">
|
||||
<Flex>
|
||||
<Text as="h3" sx={{ placeSelf: 'center' }}>
|
||||
#music
|
||||
</Text>
|
||||
<Image
|
||||
src="https://cloud-jd45ga0mv-hack-club-bot.vercel.app/0music.svg"
|
||||
alt="Music notes"
|
||||
sx={{ height: '50px', width: '50px', ml: 2 }}
|
||||
/>
|
||||
</Flex>
|
||||
</Card>
|
||||
<Card bg="orange">
|
||||
<Flex>
|
||||
<Text as="h3" sx={{ placeSelf: 'center' }}>
|
||||
#lounge
|
||||
</Text>
|
||||
</Flex>
|
||||
</Card>
|
||||
<Card
|
||||
bg="red"
|
||||
sx={{
|
||||
backgroundImage: ({ colors }) =>
|
||||
`linear-gradient(-184deg, ${colors.red} 0%, ${colors.red} 16.6666%, ${colors.orange} 16.6666%, ${colors.orange} 33.333%, ${colors.yellow} 33.333%, ${colors.yellow} 50%, ${colors.green} 50%, ${colors.green} 66.6666%, ${colors.blue} 66.6666%, ${colors.blue} 83.3333%, ${colors.purple} 83.3333%, ${colors.purple} 100%)`
|
||||
}}
|
||||
>
|
||||
<h3>#lgbtq</h3>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Box, Heading, Grid } from 'theme-ui'
|
||||
import { Box, Grid, Heading } from 'theme-ui'
|
||||
import SlideUp from '../slide-up'
|
||||
import JoinForm from './join-form'
|
||||
import usePrefersMotion from '../../lib/use-prefers-motion'
|
||||
|
|
@ -118,7 +118,7 @@ const Slack = () => {
|
|||
/>
|
||||
</Box>
|
||||
<Cover />
|
||||
<Content />
|
||||
<Content nameInputRef />
|
||||
</Box>
|
||||
)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,4 @@
|
|||
import {
|
||||
Box,
|
||||
Card,
|
||||
Grid,
|
||||
Input,
|
||||
Label,
|
||||
Link,
|
||||
Select,
|
||||
Text,
|
||||
Textarea
|
||||
} from 'theme-ui'
|
||||
import { Box, Card, Grid, Input, Label, Link, Select, Text, Textarea } from 'theme-ui'
|
||||
import { useRouter } from 'next/router'
|
||||
import useForm from '../../lib/use-form'
|
||||
import Submit from '../submit'
|
||||
|
|
@ -16,21 +6,21 @@ import { getCookie, hasCookie } from 'cookies-next'
|
|||
|
||||
const JoinForm = ({ sx = {} }) => {
|
||||
const router = useRouter()
|
||||
const useWaitlist = process.env.NEXT_PUBLIC_OPEN !== 'true'
|
||||
|
||||
const { status, formProps, useField } = useForm('/api/join/', null, {
|
||||
clearOnSubmit: 60000,
|
||||
method: 'POST',
|
||||
initData: hasCookie('continent')
|
||||
? {
|
||||
continent: getCookie('continent'),
|
||||
reason: router.query.reason,
|
||||
event: router.query.event
|
||||
}
|
||||
continent: getCookie('continent'),
|
||||
reason: router.query.reason,
|
||||
event: router.query.event
|
||||
}
|
||||
: { reason: router.query.reason, event: router.query.event }
|
||||
})
|
||||
|
||||
const eventReferrer = useField('event').value
|
||||
const isAdult = useField('educationLevel').value === 'tertiary'
|
||||
const useWaitlist = process.env.NEXT_PUBLIC_OPEN !== 'true'
|
||||
|
||||
return (
|
||||
<Card sx={{ maxWidth: 'narrow', mx: 'auto', label: { mb: 3 }, ...sx }}>
|
||||
|
|
@ -58,16 +48,17 @@ const JoinForm = ({ sx = {} }) => {
|
|||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
<Grid columns={[1, 2]} gap={1} sx={{ columnGap: 2 }}>
|
||||
<Grid columns={[1, 3]} gap={1} sx={{ columnGap: 2 }}>
|
||||
<Label>
|
||||
Full name
|
||||
<Input
|
||||
{...useField('name')}
|
||||
placeholder="Fiona Hackworth"
|
||||
required
|
||||
id="joiner_full_name"
|
||||
/>
|
||||
</Label>
|
||||
<Label>
|
||||
<Label sx={{ width: '100%' }}>
|
||||
Email address
|
||||
<Input
|
||||
{...useField('email')}
|
||||
|
|
@ -76,39 +67,17 @@ const JoinForm = ({ sx = {} }) => {
|
|||
/>
|
||||
</Label>
|
||||
<Label>
|
||||
Your home continent
|
||||
Education level
|
||||
<Select
|
||||
{...useField('continent')}
|
||||
{...useField('year')}
|
||||
required
|
||||
sx={{ color: useField('continent').value === '' ? 'muted' : '' }}
|
||||
>
|
||||
<option value="" selected disabled hidden>
|
||||
Select a continent...
|
||||
</option>
|
||||
<option>Africa</option>
|
||||
<option>Asia</option>
|
||||
<option>Europe</option>
|
||||
<option>North America</option>
|
||||
<option value="Australia">Oceania / Australia</option>
|
||||
<option>South America</option>
|
||||
</Select>
|
||||
</Label>
|
||||
<Label>
|
||||
Current education level
|
||||
<Select
|
||||
{...useField('educationLevel')}
|
||||
required
|
||||
sx={{
|
||||
color: useField('educationLevel').value === '' ? 'muted' : ''
|
||||
}}
|
||||
>
|
||||
<option value="" selected disabled hidden>
|
||||
Select a level...
|
||||
</option>
|
||||
<option value="middle">
|
||||
Middle School (approx. 11 to 14)
|
||||
</option>
|
||||
<option value="high">High School (approx. 14 to 18)</option>
|
||||
<option value="middle">Middle School</option>
|
||||
<option value="high">High School</option>
|
||||
<option value="tertiary">Tertiary Education (18+)</option>
|
||||
</Select>
|
||||
</Label>
|
||||
|
|
@ -121,8 +90,7 @@ const JoinForm = ({ sx = {} }) => {
|
|||
required
|
||||
/>
|
||||
</Label>
|
||||
|
||||
{isAdult && (
|
||||
{/*{isAdult && (
|
||||
<Text
|
||||
variant="caption"
|
||||
color="secondary"
|
||||
|
|
@ -136,44 +104,68 @@ const JoinForm = ({ sx = {} }) => {
|
|||
a email at{' '}
|
||||
<Link href="mailto:team@hackclub.com">team@hackclub.com</Link>.
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{!isAdult && (
|
||||
<Box>
|
||||
<Submit
|
||||
status={status}
|
||||
mt={'0px!important'}
|
||||
labels={{
|
||||
default: useWaitlist ? 'Join Waitlist' : 'Get Invite',
|
||||
error: 'Something went wrong',
|
||||
success: useWaitlist
|
||||
? "We'll be in touch soon!"
|
||||
: 'Check your email for invite!'
|
||||
)}*/}
|
||||
<Box>
|
||||
<Submit
|
||||
status={status}
|
||||
mt={'0px!important'}
|
||||
labels={{
|
||||
default: useWaitlist ? 'Join Waitlist' : 'Get Invite',
|
||||
error: 'Something went wrong',
|
||||
success: useWaitlist
|
||||
? "You're on the Waitlist!"
|
||||
: 'Check your email for invite!'
|
||||
}}
|
||||
disabled={status === 'loading' || status === 'success'}
|
||||
/>
|
||||
{status === 'success' && !useWaitlist && (
|
||||
<Text
|
||||
variant="caption"
|
||||
color="secondary"
|
||||
as="div"
|
||||
sx={{
|
||||
maxWidth: '600px',
|
||||
textAlign: 'center',
|
||||
mt: 3
|
||||
}}
|
||||
disabled={status === 'loading' || status === 'success'}
|
||||
/>
|
||||
{status === 'success' && (
|
||||
<Text
|
||||
variant="caption"
|
||||
color="secondary"
|
||||
as="div"
|
||||
sx={{
|
||||
maxWidth: '600px',
|
||||
textAlign: 'center',
|
||||
mt: 3
|
||||
}}
|
||||
>
|
||||
Search for "Slack" in your mailbox! Not there?{' '}
|
||||
<Link href="mailto:slack@hackclub.com" sx={{ ml: 1 }}>
|
||||
Send us an email
|
||||
</Link>
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
>
|
||||
Search for "Slack" in your mailbox! Not there?{' '}
|
||||
<Link href="mailto:slack@hackclub.com" sx={{ ml: 1 }}>
|
||||
Send us an email
|
||||
</Link>
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
</form>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
function AdultChecker() {
|
||||
return (
|
||||
<Label>
|
||||
Birthday
|
||||
<Select
|
||||
required
|
||||
onChange={handleYearChange}
|
||||
sx={{ color: useField('continent').value === '' ? 'muted' : '' }}
|
||||
>
|
||||
<option value="" selected disabled hidden>
|
||||
Year
|
||||
</option>
|
||||
<option value="middle" disabled hidden>
|
||||
Hi, I'm hidden!
|
||||
</option>
|
||||
{years
|
||||
.map(year => (
|
||||
<option key={year} value={year}>
|
||||
{year}
|
||||
</option>
|
||||
))
|
||||
.reverse()}
|
||||
</Select>
|
||||
</Label>
|
||||
)
|
||||
}
|
||||
|
||||
export default JoinForm
|
||||
|
|
|
|||
62
components/slack/join.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { Box, Image, Link, Text } from 'theme-ui'
|
||||
import Icon from '@hackclub/icons'
|
||||
|
||||
export default function Join() {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: '#F9FAFC',
|
||||
mt: '2rem',
|
||||
borderRadius: 12,
|
||||
overflowX: 'hidden',
|
||||
height: ['', '30rem'],
|
||||
paddingTop: ['2rem', 0],
|
||||
display: ['grid', 'grid', 'flex']
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: ['100%', '100%', '50%'],
|
||||
paddingX: '32px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Text
|
||||
as="h1"
|
||||
variant="title"
|
||||
sx={{ mb: 3, fontSize: ['36px', '48px', '56px'] }}
|
||||
>
|
||||
Discover the Hack Club Slack
|
||||
</Text>
|
||||
<Link
|
||||
href="#"
|
||||
sx={{
|
||||
mb: 3,
|
||||
cursor: 'pointer',
|
||||
textDecoration: 'none',
|
||||
fontSize: '24px',
|
||||
fontWeight: 500,
|
||||
placeItems: 'center',
|
||||
display: 'flex'
|
||||
}}
|
||||
>
|
||||
I'm ready to join <Icon glyph="view-forward" size={24} />
|
||||
</Link>
|
||||
</Box>
|
||||
</Box>
|
||||
<Image
|
||||
src="https://cloud-j0p07nviw-hack-club-bot.vercel.app/0image.png"
|
||||
sx={{
|
||||
width: ['100%', '100%', '50%'],
|
||||
height: ['100%', '100%', '30rem'],
|
||||
objectFit: 'cover',
|
||||
position: 'relative',
|
||||
top: 0
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
32
components/slack/preventScroll.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
const preventDefault = ev => {
|
||||
if (ev.preventDefault) {
|
||||
ev.preventDefault()
|
||||
}
|
||||
ev.returnValue = false
|
||||
}
|
||||
|
||||
const enableBodyScroll = () => {
|
||||
document && document.removeEventListener('wheel', preventDefault, false)
|
||||
}
|
||||
const disableBodyScroll = () => {
|
||||
document &&
|
||||
document.addEventListener('wheel', preventDefault, {
|
||||
passive: false
|
||||
})
|
||||
}
|
||||
|
||||
export default function usePreventScroll() {
|
||||
const [hidden, setHidden] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
hidden ? disableBodyScroll() : enableBodyScroll()
|
||||
|
||||
return enableBodyScroll
|
||||
}, [hidden])
|
||||
|
||||
const disableScroll = useCallback(() => setHidden(true), [])
|
||||
const enableScroll = useCallback(() => setHidden(false), [])
|
||||
return { disableScroll, enableScroll }
|
||||
}
|
||||
67
components/slack/project.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import { Box, Grid, Image, Text } from 'theme-ui'
|
||||
|
||||
export default function Project({ title, description, color, img, itemId }) {
|
||||
return (
|
||||
<Grid
|
||||
sx={{
|
||||
borderRadius: 12,
|
||||
gridTemplateColumns: 'auto ',
|
||||
my: '2rem',
|
||||
backgroundImage: t =>
|
||||
`linear-gradient(to bottom, ${color[0]}, ${color[1]})`,
|
||||
color: 'white',
|
||||
overflow: 'clip',
|
||||
width: ['100vw', '40rem', '50rem', '70rem'],
|
||||
height: ['25rem', '40rem'],
|
||||
transformOrigin: 'center',
|
||||
mr: 16,
|
||||
// this is v janky please ignore, thank you.
|
||||
ml: ['1rem', '1rem', '1rem', `${itemId === 0 && 'calc(50vw - 36.5rem)'}`]
|
||||
}}
|
||||
itemId={itemId}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
paddingX: '8px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
placeItems: 'center',
|
||||
height: ['full', '12.5rem', '20rem'],
|
||||
placeSelf: 'center',
|
||||
placeContent: 'end'
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
as="h1"
|
||||
variant="title"
|
||||
sx={{
|
||||
width: ['full', 'copyUltra'],
|
||||
textAlign: 'center',
|
||||
fontSize: ['36px', 6]
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
<Text
|
||||
as="p"
|
||||
variant="subtitle"
|
||||
sx={{
|
||||
width: ['full', 'copyPlus'],
|
||||
opacity: '75%',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
</Box>
|
||||
<Image
|
||||
src={`/slack/${img}.png`}
|
||||
sx={{
|
||||
visibility: ['visible'],
|
||||
height: ['100%'],
|
||||
objectFit: 'cover'
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
87
components/slack/projects.js
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
const projects = [
|
||||
{
|
||||
title: 'Brainwave device for thought-based computer interaction.',
|
||||
description:
|
||||
'The team of teens behind BCI is building both the hardware and software for a brainwave reading device to interact with computers using thoughts',
|
||||
img: 'bci',
|
||||
color: ['#ec3750', '#F58695'],
|
||||
itemId: 0
|
||||
},
|
||||
{
|
||||
title: 'A free domain service.',
|
||||
description:
|
||||
'The teenage hackers behind Oblong are building a free domain service and non-profit to break down the barriers of entry for building a website.',
|
||||
img: 'oblong',
|
||||
color: ['#ff8c37', '#F2A510'],
|
||||
itemId: 1
|
||||
},
|
||||
{
|
||||
title: 'An open source VPN.',
|
||||
description:
|
||||
'Lead by an ex-Apple engineer, the team behind Burrow is building an open source VPN to burrow through school firewalls and keep your data safe.',
|
||||
img: 'burrow',
|
||||
color: ['#f1c40f', '#FAE078'],
|
||||
itemId: 2
|
||||
},
|
||||
{
|
||||
title: 'Free compute infrastructure.',
|
||||
description:
|
||||
"The team behind Nest is building a free compute infrastructure for high schoolers to run their code on. It's like AWS, but free and for students.",
|
||||
img: 'nest',
|
||||
color: ['#33d6a6', '#51F5C5'],
|
||||
itemId: 3
|
||||
},
|
||||
{
|
||||
title: 'A chat app and cell phone carrier.',
|
||||
description:
|
||||
'The teenage PurpleBubble team are building a private, secure and open source chat app and cell phone carrier',
|
||||
img: 'purplebubble',
|
||||
color: ['#5bc0de', '#88e5f8'],
|
||||
itemId: 4
|
||||
}
|
||||
]
|
||||
|
||||
export default projects
|
||||
|
||||
/*
|
||||
Here lies the horizontal scroll menu. It's not currently in use, but it's here if anyone every wants it! - Toby
|
||||
const triggerRef = useRef(null)
|
||||
gsap.registerPlugin(ScrollTrigger)
|
||||
useEffect(() => {
|
||||
const sections = gsap.utils.toArray('.project')
|
||||
|
||||
const projects = gsap.to(sections, {
|
||||
xPercent: -100 * (sections.length - 1),
|
||||
ease: 'none',
|
||||
duration: 1,
|
||||
scrollTrigger: {
|
||||
trigger: triggerRef.current,
|
||||
start: 'top top',
|
||||
end: () => '+=' + document.querySelector('.container').offsetWidth,
|
||||
scrub: 1.25,
|
||||
pin: true,
|
||||
anticipatePin: 1,
|
||||
invalidateOnRefresh: true,
|
||||
snap: 0.5 * (1 / (sections.length - 1))
|
||||
},
|
||||
onUpdate: function () {
|
||||
const progress = this.progress()
|
||||
if (progress < 1 / 6) {
|
||||
setColors(['red', '#F58695'])
|
||||
} else if (progress < 2 / 6) {
|
||||
setColors(['orange', '#F2A510'])
|
||||
} else if (progress < 3 / 6) {
|
||||
setColors(['yellow', '#FAE078'])
|
||||
} else if (progress < 4 / 6) {
|
||||
setColors(['green', '#51F5C5'])
|
||||
} else if (progress < 5 / 6) {
|
||||
setColors(['cyan', '#88e5f8'])
|
||||
} else {
|
||||
setColors(['purple', '#d786ff'])
|
||||
}
|
||||
}
|
||||
})
|
||||
return () => {
|
||||
projects.kill()
|
||||
}
|
||||
}, [])*/
|
||||
24
components/slack/quote.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { Box, Flex, Image, Text } from 'theme-ui'
|
||||
|
||||
export default function Quote({ text, person, age, location, img }) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
p: '32px',
|
||||
borderRadius: 12,
|
||||
backgroundColor: '#F9FAFC',
|
||||
width: 'full'
|
||||
}}
|
||||
>
|
||||
<Text as="h3" variant="title" sx={{ mb: 3, fontSize: ['36px', 4, 5] }}>
|
||||
"{text}"
|
||||
</Text>
|
||||
<Flex sx={{ gap: '8px' }}>
|
||||
<Image src={img} sx={{ height: 24, width: 24, borderRadius: 100 }} />
|
||||
<Text as="h3" sx={{ fontWeight: 400 }}>
|
||||
{person}, {age} from {location}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ const Submit = ({
|
|||
}) => (
|
||||
<Button
|
||||
as="button"
|
||||
type="submit"
|
||||
type={'submit' || props.type}
|
||||
sx={{
|
||||
py: 2,
|
||||
px: 3,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
"format": "prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.9.5",
|
||||
"@apollo/client": "^3.9.9",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@github/time-elements": "^4.0.0",
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
"@tracespace/plotter": "^5.0.0-alpha.0",
|
||||
"@tracespace/renderer": "^5.0.0-alpha.0",
|
||||
"@tracespace/xml-id": "^4.2.7",
|
||||
"@sendgrid/mail": "^8.1.1",
|
||||
"add": "^2.0.6",
|
||||
"airtable-plus": "^1.0.4",
|
||||
"animated-value": "^0.2.4",
|
||||
|
|
@ -60,6 +61,7 @@
|
|||
"react-before-after-slider-component": "^1.1.8",
|
||||
"react-datepicker": "^4.24.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-horizontal-scrolling-menu": "^6.0.2",
|
||||
"react-konami-code": "^2.3.0",
|
||||
"react-marquee-slider": "^1.1.5",
|
||||
"react-masonry-css": "^1.0.16",
|
||||
|
|
|
|||
12
pages/api/channels/get.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
export default async function handler(req, res) {
|
||||
const channelDataReq = await fetch(
|
||||
`https://slack.com/api/conversations.info?channel=${req.body.id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}`
|
||||
}
|
||||
}
|
||||
)
|
||||
console.log(channelDataReq)
|
||||
return res.status(200).send(channelDataReq)
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import AirtablePlus from 'airtable-plus'
|
||||
import { getCode } from 'country-list'
|
||||
|
||||
const applicationsTable = new AirtablePlus({
|
||||
baseID: 'apppALh5FEOKkhjLR',
|
||||
|
|
@ -14,8 +15,8 @@ export default async function handler(req, res) {
|
|||
body: JSON.stringify({
|
||||
email: data.userEmail,
|
||||
name: data.eventName,
|
||||
transparent: data.transparent
|
||||
// country: data.eventCountryCode,
|
||||
country: getCode(data.eventLocation) || '',
|
||||
transparent: data.transparent,
|
||||
}),
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const getMessage = (type, payload, repo) => {
|
|||
const getUrl = (type, payload, repo) => {
|
||||
switch (type) {
|
||||
case 'PushEvent':
|
||||
return payload.commits?.[0].url
|
||||
return payload.commits?.[0]?.url
|
||||
? normalizeGitHubCommitUrl(payload.commits[0].url)
|
||||
: 'https://github.com/hackclub'
|
||||
case 'PullRequestEvent':
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import AirtablePlus from 'airtable-plus'
|
||||
|
||||
const sgMail = require('@sendgrid/mail')
|
||||
|
||||
sgMail.setApiKey(process.env.SENDGRID_API_KEY)
|
||||
|
||||
const joinTable = new AirtablePlus({
|
||||
apiKey: process.env.AIRTABLE_API_KEY,
|
||||
baseID: 'appaqcJtn33vb59Au',
|
||||
|
|
@ -36,15 +40,29 @@ export default async function handler(req, res) {
|
|||
error: '*PUT that request away!* (Method not allowed, use POST)'
|
||||
})
|
||||
case 'POST':
|
||||
console.log('POST request received. WOO!')
|
||||
break
|
||||
default:
|
||||
return res.status(405).json({ error: 'Method not allowed, use POST' })
|
||||
}
|
||||
|
||||
const data = req.body || {}
|
||||
let data = req.body || {}
|
||||
const open = process.env.NEXT_PUBLIC_OPEN === 'true'
|
||||
const waitlist = !open
|
||||
const isAdult = data.educationLevel === 'tertiary'
|
||||
const isAdult = data.year === 'tertiary'
|
||||
|
||||
if (isAdult) {
|
||||
const mail = {
|
||||
to: data.email,
|
||||
from: 'Hack Club Slack <team@hackclub.com>',
|
||||
subject: 'Slack Waiting List update',
|
||||
text: 'Hello world',
|
||||
html: "Hey! Thanks for your interest in the Hack Club Slack. <br/> Our online community is for minors, and thus only pre-approved adults are permitted.\nTo find out more about what all we do, check out our <a href='https://github.com/hackclub'>Github</a>. If you're a parent or educator & want to talk to a member of our team, send us a email at <a href='mailto:team@hackclub.com'>team@hackclub.com</a>.",
|
||||
imageUrl: 'https://assets.hackclub.com/icon-rounded.png'
|
||||
}
|
||||
|
||||
sgMail.send(mail)
|
||||
}
|
||||
|
||||
const secrets = (process.env.NAUGHTY || '').split(',')
|
||||
|
||||
|
|
@ -58,7 +76,7 @@ export default async function handler(req, res) {
|
|||
const airtablePromise = joinTable.create({
|
||||
'Full Name': data.name,
|
||||
'Email Address': data.email,
|
||||
Student: !isAdult,
|
||||
Minor: !isAdult,
|
||||
Reason: data.reason,
|
||||
Invited: !waitlist,
|
||||
Club: data.club ? data.club : '',
|
||||
|
|
@ -76,7 +94,7 @@ export default async function handler(req, res) {
|
|||
const slackPromise = postData(
|
||||
'https://toriel.hackclub.com/slack-invite',
|
||||
{
|
||||
email: data.email,
|
||||
email: !isAdult ? data.email : null,
|
||||
ip: req.headers['x-forwarded-for'] || req.socket.remoteAddress,
|
||||
continent: data.continent,
|
||||
teen: !isAdult,
|
||||
|
|
@ -93,6 +111,7 @@ export default async function handler(req, res) {
|
|||
res.json({ status: 'success', message: 'You’ve been invited to Slack!' })
|
||||
)
|
||||
.catch(error => {
|
||||
console.error(error)
|
||||
res.status(500).json({ error })
|
||||
})
|
||||
}
|
||||
|
|
|
|||
16
pages/api/onboard/project-count.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
async function onboardProjectCount() {
|
||||
const url = 'https://api.github.com/repos/hackclub/onboard/contents/projects'
|
||||
|
||||
const response = await fetch(url).then(r => r.json())
|
||||
const countedProjects = response.filter(
|
||||
folder =>
|
||||
folder.type === 'dir' && folder.name[0] !== '.' && folder.name[0] !== '!'
|
||||
)
|
||||
return countedProjects.length
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const count = await onboardProjectCount()
|
||||
|
||||
res.json({ count })
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ const Page = () => (
|
|||
pb: 3
|
||||
}}
|
||||
>
|
||||
Don’t run your coding club alone.
|
||||
Don’t run your coding club alone.{' '}
|
||||
</Text>
|
||||
Make it a{' '}
|
||||
<Text
|
||||
|
|
@ -258,11 +258,12 @@ const Page = () => (
|
|||
showAlt
|
||||
/>*/}
|
||||
<iframe
|
||||
width={660}
|
||||
height={515}
|
||||
width="100%"
|
||||
height="500px"
|
||||
src="https://www.youtube.com/embed/xXIxwV7bQTw?si=gmhvvHTcUxKTVMjt"
|
||||
title="YouTube video player"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowFullScreen
|
||||
style={{ borderRadius: 12, border: 'hidden' }}
|
||||
/>
|
||||
<Grid
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, Card, Container, Flex, Link, Text } from 'theme-ui'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Box, Container, Flex, Link, Text } from 'theme-ui'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { keyframes } from '@emotion/react'
|
||||
import FlexCol from '../../components/flex-col'
|
||||
import Meta from '@hackclub/meta'
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
import { useState, useRef } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Box, Text, Flex, Heading, Grid, Alert, Button } from 'theme-ui'
|
||||
import ForceTheme from '../../../components/force-theme'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Alert, Box, Button, Flex, Grid, Heading, Text } from 'theme-ui'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import Icon from '@hackclub/icons'
|
||||
import Meta from '@hackclub/meta'
|
||||
import { onSubmit } from '../../../components/fiscal-sponsorship/apply/submit'
|
||||
import Watermark from '../../../components/fiscal-sponsorship/apply/watermark'
|
||||
import ForceTheme from '../../../components/force-theme'
|
||||
import FormContainer from '../../../components/fiscal-sponsorship/apply/form-container'
|
||||
import HCBInfo from '../../../components/fiscal-sponsorship/apply/hcb-info'
|
||||
import OrganizationInfoForm from '../../../components/fiscal-sponsorship/apply/org-form'
|
||||
import PersonalInfoForm from '../../../components/fiscal-sponsorship/apply/personal-form'
|
||||
import Icon from '@hackclub/icons'
|
||||
import Link from 'next/link'
|
||||
import { onSubmit } from '../../../components/fiscal-sponsorship/apply/submit'
|
||||
import Watermark from '../../../components/fiscal-sponsorship/apply/watermark'
|
||||
import ContactBanner from '../../../components/fiscal-sponsorship/contact'
|
||||
|
||||
export default function Apply() {
|
||||
const router = useRouter()
|
||||
|
|
@ -47,10 +48,9 @@ export default function Apply() {
|
|||
<Flex
|
||||
sx={{
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
px: [3, 5],
|
||||
py: 5,
|
||||
gap: [4, 5],
|
||||
py: 4,
|
||||
gap: 4,
|
||||
height: [null, '100svh'],
|
||||
position: [null, null, 'sticky'],
|
||||
top: 0,
|
||||
|
|
@ -58,7 +58,7 @@ export default function Apply() {
|
|||
}}
|
||||
>
|
||||
{/* vertically align h1 to top of form */}
|
||||
<Box as="header" sx={{ mt: [null, null, -24] }}>
|
||||
<Box as="header" sx={{ mt: [null, 3], mb: 'auto' }}>
|
||||
<Link href="/fiscal-sponsorship" passHref legacyBehavior>
|
||||
<Text
|
||||
as="a"
|
||||
|
|
@ -101,6 +101,7 @@ export default function Apply() {
|
|||
</Heading>
|
||||
</Box>
|
||||
<HCBInfo />
|
||||
<ContactBanner sx={{ borderRadius: 'default', bg: 'snow', width: 'fit-content' }} />
|
||||
</Flex>
|
||||
<FormContainer
|
||||
ref={formContainer}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { useEffect } from 'react'
|
||||
import { Box, Container, Text, Link, Flex, Image } from 'theme-ui'
|
||||
import { Container, Text, Link, Image } from 'theme-ui'
|
||||
import JSConfetti from 'js-confetti'
|
||||
import Icon from '../../../components/icon'
|
||||
import { Balancer } from 'react-wrap-balancer'
|
||||
|
||||
function fireConfetti() {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {
|
|||
Flex,
|
||||
Grid,
|
||||
Heading,
|
||||
Input,
|
||||
Select
|
||||
Input
|
||||
} from 'theme-ui'
|
||||
import Meta from '@hackclub/meta'
|
||||
import Head from 'next/head'
|
||||
|
|
@ -16,10 +15,10 @@ import Footer from '../../../components/footer'
|
|||
import MSparkles from '../../../components/sparkles/money'
|
||||
import { Text, Button, Card } from 'theme-ui'
|
||||
import Icon from '@hackclub/icons'
|
||||
import OrganizationCard, { Badge } from '../../../components/fiscal-sponsorship/directory/card'
|
||||
import Zoom from 'react-reveal/Zoom'
|
||||
import OrganizationCard, {
|
||||
Badge
|
||||
} from '../../../components/fiscal-sponsorship/directory/card'
|
||||
import fuzzysort from 'fuzzysort'
|
||||
import ScrollHint from '../../../components/scroll-hint'
|
||||
import { useEffect, useState } from 'react'
|
||||
/** @jsxImportSource theme-ui */
|
||||
import NextLink from 'next/link'
|
||||
|
|
@ -93,8 +92,7 @@ export const regions = [
|
|||
icon: 'photo',
|
||||
image:
|
||||
'https://cloud-cberabu5z-hack-club-bot.vercel.app/3north_america.png',
|
||||
ogImage:
|
||||
'https://cloud-p9tu92fwx-hack-club-bot.vercel.app/3northamerica.png'
|
||||
ogImage: '/fiscal-sponsorship/climate/NorthAmerica.png'
|
||||
},
|
||||
{
|
||||
label: 'South America',
|
||||
|
|
@ -103,8 +101,7 @@ export const regions = [
|
|||
icon: 'photo',
|
||||
image:
|
||||
'https://cloud-cberabu5z-hack-club-bot.vercel.app/4south_america.png',
|
||||
ogImage:
|
||||
'https://cloud-p9tu92fwx-hack-club-bot.vercel.app/4southamerica.png'
|
||||
ogImage: '/fiscal-sponsorship/climate/SouthAmerica.png'
|
||||
},
|
||||
{
|
||||
label: 'Africa',
|
||||
|
|
@ -112,7 +109,7 @@ export const regions = [
|
|||
iconColor: 'purple',
|
||||
icon: 'explore',
|
||||
image: 'https://cloud-cberabu5z-hack-club-bot.vercel.app/0africa.png',
|
||||
ogImage: 'https://cloud-p9tu92fwx-hack-club-bot.vercel.app/0africa.png'
|
||||
ogImage: '/fiscal-sponsorship/climate/Africa.png'
|
||||
},
|
||||
{
|
||||
label: 'Europe',
|
||||
|
|
@ -120,7 +117,7 @@ export const regions = [
|
|||
iconColor: 'blue',
|
||||
icon: 'explore',
|
||||
image: 'https://cloud-oax3m4v0t-hack-club-bot.vercel.app/1europe.png',
|
||||
ogImage: 'https://cloud-p9tu92fwx-hack-club-bot.vercel.app/2europe.png'
|
||||
ogImage: '/fiscal-sponsorship/climate/Europe.png'
|
||||
},
|
||||
{
|
||||
label: 'Asia & Oceania',
|
||||
|
|
@ -129,8 +126,7 @@ export const regions = [
|
|||
icon: 'explore',
|
||||
image:
|
||||
'https://cloud-oax3m4v0t-hack-club-bot.vercel.app/0asia___oceania.png',
|
||||
ogImage:
|
||||
'https://cloud-p9tu92fwx-hack-club-bot.vercel.app/1asia_oceania.png'
|
||||
ogImage: '/fiscal-sponsorship/climate/Asia+Oceania.png'
|
||||
}
|
||||
]
|
||||
|
||||
|
|
@ -153,8 +149,8 @@ const FilterPanel = ({ filter, mobile }) => {
|
|||
cursor: mobile ? 'pointer' : 'default',
|
||||
':hover': mobile
|
||||
? {
|
||||
color: 'blue'
|
||||
}
|
||||
color: 'blue'
|
||||
}
|
||||
: {}
|
||||
}}
|
||||
onClick={() => setHiddenOnMobile(!hiddenOnMobile)}
|
||||
|
|
@ -245,7 +241,7 @@ const FilterPanel = ({ filter, mobile }) => {
|
|||
textDecoration: 'none',
|
||||
color:
|
||||
currentSelections.length === baseData.length ||
|
||||
!currentSelections.includes(item.id)
|
||||
!currentSelections.includes(item.id)
|
||||
? 'black'
|
||||
: 'primary',
|
||||
transition: 'color 0.2s',
|
||||
|
|
@ -325,8 +321,8 @@ const RegionPanel = ({ currentRegion, mobile }) => {
|
|||
cursor: mobile ? 'pointer' : 'default',
|
||||
':hover': mobile
|
||||
? {
|
||||
color: 'blue'
|
||||
}
|
||||
color: 'blue'
|
||||
}
|
||||
: {}
|
||||
}}
|
||||
onClick={() => setHiddenOnMobile(!hiddenOnMobile)}
|
||||
|
|
@ -403,7 +399,9 @@ const RegionPanel = ({ currentRegion, mobile }) => {
|
|||
<NextLink
|
||||
key={idx}
|
||||
scroll={false}
|
||||
href={`/fiscal-sponsorship/climate/organizations-in-${kebabCase(item.label)}`}
|
||||
href={`/fiscal-sponsorship/climate/organizations-in-${kebabCase(
|
||||
item.label
|
||||
)}`}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
|
|
@ -535,8 +533,7 @@ export default function ClimatePage({ rawOrganizations, pageRegion }) {
|
|||
" with HCB's fiscal sponsorship and financial tools. Explore the climate efforts running on HCB."
|
||||
}
|
||||
image={
|
||||
region?.ogImage ??
|
||||
'https://cloud-gv8bzwz6z-hack-club-bot.vercel.app/0frame_14__1_.png'
|
||||
region?.ogImage ?? '/fiscal-sponsorship/climate/social-preview.png'
|
||||
}
|
||||
/>
|
||||
<style>{styles}</style>
|
||||
|
|
@ -965,7 +962,7 @@ export default function ClimatePage({ rawOrganizations, pageRegion }) {
|
|||
viewBox="0 0 512 512"
|
||||
>
|
||||
<img
|
||||
src="/fiscal-sponsorship/climate/earth-on-hcb.svg"
|
||||
src="/fiscal-sponsorship/climate/earth-on-hcb.png"
|
||||
alt=""
|
||||
height="82px"
|
||||
/>
|
||||
|
|
@ -1135,7 +1132,7 @@ export default function ClimatePage({ rawOrganizations, pageRegion }) {
|
|||
return (
|
||||
currentBadges.length === badges.length ||
|
||||
intersection(organizationBadgeIds, currentBadges).length ===
|
||||
currentBadges.length
|
||||
currentBadges.length
|
||||
)
|
||||
})
|
||||
.map(organization => (
|
||||
|
|
@ -1214,7 +1211,7 @@ export default function ClimatePage({ rawOrganizations, pageRegion }) {
|
|||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Footer light key="footer" />
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1401,7 +1398,7 @@ export async function fetchRawClimateOrganizations() {
|
|||
while (lastLength >= 100) {
|
||||
const json = await fetch(
|
||||
'https://hcb.hackclub.com/api/v3/directory/organizations?per_page=100&page=' +
|
||||
page
|
||||
page
|
||||
).then(res => res.json())
|
||||
lastLength = json.length
|
||||
page++
|
||||
|
|
|
|||
|
|
@ -1,13 +1,4 @@
|
|||
import {
|
||||
Box,
|
||||
Heading,
|
||||
Container,
|
||||
Card,
|
||||
Text,
|
||||
Flex,
|
||||
Button,
|
||||
Badge
|
||||
} from 'theme-ui'
|
||||
import { Box, Heading, Container, Text, Button, Badge } from 'theme-ui'
|
||||
|
||||
import Meta from '@hackclub/meta'
|
||||
import Head from 'next/head'
|
||||
|
|
@ -186,7 +177,7 @@ export default function First({ stats }) {
|
|||
<Start stats={stats} />
|
||||
</Box>
|
||||
</Box>
|
||||
<Footer dark key="footer" />
|
||||
<Footer dark />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,29 @@
|
|||
import Meta from '@hackclub/meta'
|
||||
import Head from 'next/head'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { Balancer } from 'react-wrap-balancer'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Container,
|
||||
Flex,
|
||||
Link as UILink,
|
||||
Heading,
|
||||
Text,
|
||||
Grid,
|
||||
Button
|
||||
Heading,
|
||||
Link as UILink,
|
||||
Text
|
||||
} from 'theme-ui'
|
||||
import { Balancer } from 'react-wrap-balancer'
|
||||
import Meta from '@hackclub/meta'
|
||||
import Head from 'next/head'
|
||||
import ForceTheme from '../../components/force-theme'
|
||||
import Nav from '../../components/nav'
|
||||
import Footer from '../../components/footer'
|
||||
import Photo from '../../components/photo'
|
||||
import Stat from '../../components/stat'
|
||||
import Tilt from '../../components/tilt'
|
||||
import Photo from '../../components/photo'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
|
||||
import OuternetImgFile from '../../public/home/outernet-110.jpg'
|
||||
import ContactBanner from '../../components/fiscal-sponsorship/contact'
|
||||
import Features from '../../components/fiscal-sponsorship/features'
|
||||
import OuternetImgFile from '../../public/home/outernet-110.jpg'
|
||||
|
||||
const organizations = [
|
||||
{
|
||||
|
|
@ -375,8 +376,11 @@ export default function Page() {
|
|||
color="slate"
|
||||
sx={{ maxWidth: '52ch' }}
|
||||
>
|
||||
This fee goes directly to Hack Club's operations staff, including teen interns working under mentors. This allows us to deliver
|
||||
best-in-class software and support, grow sustainably, while also providing paid career training for young people from diverse backgrounds.
|
||||
This fee goes directly to Hack Club's operations staff,
|
||||
including teen interns working under mentors. This allows us to
|
||||
deliver best-in-class software and support, grow sustainably,
|
||||
while also providing paid career training for young people from
|
||||
diverse backgrounds.
|
||||
</Text>
|
||||
</div>
|
||||
<Text
|
||||
|
|
@ -393,10 +397,10 @@ export default function Page() {
|
|||
'linear-gradient(to right, #f06844 0%, #ee4c54 25%, #d45e95 50%, #9c6ca6 75%, #6583c1 100%) !important'
|
||||
},
|
||||
'@supports (-webkit-background-clip: text) and (background: linear-gradient(to right in oklch, white, black)':
|
||||
{
|
||||
backgroundImage:
|
||||
'linear-gradient(to right in oklch, #f06844 0%, #ee4c54 25%, #d45e95 50%, #9c6ca6 75%, #6583c1 100%) !important'
|
||||
}
|
||||
{
|
||||
backgroundImage:
|
||||
'linear-gradient(to right in oklch, #f06844 0%, #ee4c54 25%, #d45e95 50%, #9c6ca6 75%, #6583c1 100%) !important'
|
||||
}
|
||||
}}
|
||||
style={{ margin: 0 }}
|
||||
>
|
||||
|
|
@ -498,10 +502,11 @@ export default function Page() {
|
|||
src={OuternetImgFile}
|
||||
alt="Each year, 1000s of teenagers attend Hack Club events like this"
|
||||
showAlt
|
||||
sx={{ height: '100%' }}
|
||||
/>
|
||||
</Link>
|
||||
<div>
|
||||
<Heading as="h2" variant="headline">
|
||||
<Heading as="h2" variant="headline" sx={{ mt: [0, 0] }}>
|
||||
Built by Hack Club
|
||||
</Heading>
|
||||
<p>
|
||||
|
|
@ -514,11 +519,44 @@ export default function Page() {
|
|||
clubs around the world.
|
||||
</p>
|
||||
<p>
|
||||
We started HCB in 2018 to support teen-led clubs and hackathons. After
|
||||
showing it to our educational partners, we knew we had tapped into
|
||||
something much larger. Today, HCB removes financial and
|
||||
legal barriers for thousands doing good in their community.
|
||||
We started HCB in 2018 to support teen-led clubs and hackathons.
|
||||
After showing it to our educational partners, we knew we had
|
||||
tapped into something much larger. Today, HCB removes financial
|
||||
and legal barriers for thousands doing good in their community.
|
||||
</p>
|
||||
<Flex
|
||||
as="footer"
|
||||
sx={{
|
||||
alignItems: 'center',
|
||||
gap: 3,
|
||||
color: 'slate',
|
||||
borderRadius: 'default',
|
||||
lineHeight: 'caption',
|
||||
textWrap: 'balance',
|
||||
svg: { flexShrink: 0, fill: 'blue' }
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={32}
|
||||
height={32}
|
||||
viewBox="0 0 16 16"
|
||||
aria-hidden
|
||||
>
|
||||
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0M2.04 4.326c.325 1.329 2.532 2.54 3.717 3.19.48.263.793.434.743.484q-.121.12-.242.234c-.416.396-.787.749-.758 1.266.035.634.618.824 1.214 1.017.577.188 1.168.38 1.286.983.082.417-.075.988-.22 1.52-.215.782-.406 1.48.22 1.48 1.5-.5 3.798-3.186 4-5 .138-1.243-2-2-3.5-2.5-.478-.16-.755.081-.99.284-.172.15-.322.279-.51.216-.445-.148-2.5-2-1.5-2.5.78-.39.952-.171 1.227.182.078.099.163.208.273.318.609.304.662-.132.723-.633.039-.322.081-.671.277-.867.434-.434 1.265-.791 2.028-1.12.712-.306 1.365-.587 1.579-.88A7 7 0 1 1 2.04 4.327Z" />
|
||||
</svg>
|
||||
<span>
|
||||
As part of our commitment to climate justice, funding for HCB’s
|
||||
operations and staff will never come from the{' '}
|
||||
<UILink
|
||||
href="https://www.ffisolutions.com/the-carbon-underground-200-500/"
|
||||
color="blue"
|
||||
>
|
||||
fossil fuel industry
|
||||
</UILink>
|
||||
.
|
||||
</span>
|
||||
</Flex>
|
||||
</div>
|
||||
</Grid>
|
||||
</Container>
|
||||
|
|
@ -576,11 +614,12 @@ export default function Page() {
|
|||
Apply now
|
||||
</Button>
|
||||
</Link>
|
||||
<Text as="p" variant="lead" sx={{ color: 'white' }}>
|
||||
<Text as="p" variant="lead" sx={{ color: 'white', mb: [0, 0] }}>
|
||||
<Balancer>No startup fees, no minimum balance.</Balancer>
|
||||
</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
<ContactBanner sx={{ justifyContent: 'center' }} />
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -203,12 +203,11 @@ function Page({
|
|||
priority
|
||||
gradient="linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.45))"
|
||||
/>
|
||||
<Announcement
|
||||
<Announcement
|
||||
copy="Hop OnBoard and create your first PCB"
|
||||
caption="Join 1,000 others to create your first circuit board."
|
||||
href="https://hackclub.com/onboard/"
|
||||
iconLeft="idea"
|
||||
color="primary"
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import usePrefersReducedMotion from '../../lib/use-prefers-reduced-motion'
|
|||
import { useEffect, useRef, useState } from 'react'
|
||||
import sleep from '../../lib/sleep'
|
||||
import Announcement from '../../components/announcement'
|
||||
import YoutubeVideo from '../../components/onboard/youtube-video'
|
||||
import Icon from '@hackclub/icons'
|
||||
|
||||
/**
|
||||
* @type {import('theme-ui').ThemeUIStyleObject}
|
||||
|
|
@ -202,7 +204,7 @@ const ShipPage = () => {
|
|||
<Box sx={{ pt: [3, 6]}}>
|
||||
<Announcement
|
||||
copy="Steve Wozniak, Apple co-founder, about OnBoard"
|
||||
caption="I’m so glad young people can create PCBs online."
|
||||
caption="I’m so glad young people can create PCBs online. May your creativity change the world! Mine did."
|
||||
imgSrc="https://cloud-iddh16j0r-hack-club-bot.vercel.app/0stevew.png"
|
||||
imgAlt="A picture of Steve Wozniak who is a co-founder of Apple."
|
||||
color="primary"
|
||||
|
|
@ -324,48 +326,6 @@ const ShipPage = () => {
|
|||
</Flex>
|
||||
</Grid>
|
||||
|
||||
<Flex
|
||||
as="div"
|
||||
sx={{
|
||||
flexDirection: 'row',
|
||||
gap: 3,
|
||||
alignItems: 'end',
|
||||
justifyContent: 'center',
|
||||
margin: '0 auto',
|
||||
padding: '0.8rem 1rem',
|
||||
borderRadius: 'default',
|
||||
border: '1px dashed white',
|
||||
background: '#000000',
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src="https://cloud-iddh16j0r-hack-club-bot.vercel.app/0stevew.png"
|
||||
alt="A picture of Steve Wozniak who is a co-founder of Apple."
|
||||
sx={{
|
||||
width: 50,
|
||||
height: 50
|
||||
}}
|
||||
/>
|
||||
<Flex
|
||||
as="div"
|
||||
sx={{ flexDirection: 'column', gap: 1, width: '90%' }}
|
||||
>
|
||||
<Text as="p" sx={{ fontSize: 20 }}>
|
||||
<Balancer>
|
||||
"I’m so glad young people can create PCBs online. May your
|
||||
creativity change the world! Mine did.”
|
||||
</Balancer>
|
||||
</Text>
|
||||
<Text
|
||||
as="p"
|
||||
sx={{ fontSize: 20, fontStyle: 'italic' }}
|
||||
>
|
||||
<Balancer>
|
||||
-<span style={{ textDecoration: 'underline' }}>Steve Wozniak "Woz"</span>, Apple co-founder, on Hack Club OnBoard
|
||||
</Balancer>
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
|
|
@ -402,6 +362,16 @@ const ShipPage = () => {
|
|||
Never made a circuit board before? No problem.
|
||||
</Balancer>
|
||||
</Heading>
|
||||
<Flex sx={{flexDirection:"column"}}>
|
||||
<YoutubeVideo youtube-id="LrSKs35nR8k" list="PLbNbddgD-XxECO7C2z-FAlSoJ57VqcJA3" height="300px" />
|
||||
<Text sx={{ fontSize: 2, color: 'muted' }}>
|
||||
See the{' '}
|
||||
<Link href="https://www.youtube.com/watch?v=LrSKs35nR8k&list=PLbNbddgD-XxECO7C2z-FAlSoJ57VqcJA3" target="_blank">
|
||||
full playlist
|
||||
<Icon glyph="external" size={18} />
|
||||
</Link>
|
||||
</Text>
|
||||
</Flex>
|
||||
<Text sx={{ fontSize: 3 }}>
|
||||
Learn how to design your own circuit boards from scratch with our{' '}
|
||||
<strong>official tutorials</strong> and jams, like Maggie’s{' '}
|
||||
|
|
|
|||
|
|
@ -769,29 +769,23 @@ const PizzaPage = () => {
|
|||
}}
|
||||
>
|
||||
p.s. if you already lead a club, you can still get pizza! draw a
|
||||
pizza in
|
||||
<Link
|
||||
style={{ marginLeft: '8px' }}
|
||||
href="https://hackclub.slack.com/archives/C05RZ6K7RS5"
|
||||
>
|
||||
pizza in{' '}
|
||||
<Link href="https://hackclub.slack.com/archives/C05RZ6K7RS5">
|
||||
#pizza-party
|
||||
</Link>
|
||||
</Text>
|
||||
</Box>
|
||||
<Text
|
||||
as="p"
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
fontSize: 18,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
marginBottom: '32px'
|
||||
}}
|
||||
>
|
||||
Need help getting your Pizza Grant? Email{' '}
|
||||
<Link href="mailto:thomas@hackclub.com" style={{ marginLeft: 6 }}>
|
||||
thomas@hackclub.com
|
||||
</Link>
|
||||
<Link href="mailto:thomas@hackclub.com">thomas@hackclub.com</Link>
|
||||
</Text>
|
||||
</Container>
|
||||
<Footer
|
||||
|
|
|
|||
494
pages/slack.js
|
|
@ -1,35 +1,42 @@
|
|||
import { keyframes } from '@emotion/react'
|
||||
import Meta from '@hackclub/meta'
|
||||
import Head from 'next/head'
|
||||
import NextLink from 'next/link'
|
||||
import useSWR from 'swr'
|
||||
import { Badge, Box, Card, Container, Grid, Heading, Text } from 'theme-ui'
|
||||
import { Box, Container, Heading, Text } from 'theme-ui'
|
||||
import { useRef } from 'react'
|
||||
import { ScrollMenu } from 'react-horizontal-scrolling-menu'
|
||||
import 'react-horizontal-scrolling-menu/dist/styles.css'
|
||||
|
||||
import { thousands } from '../lib/members'
|
||||
import projects from '../components/slack/projects'
|
||||
import Channels from '../components/slack/channels'
|
||||
import Join from '../components/slack/join'
|
||||
import Footer from '../components/footer'
|
||||
import ForceTheme from '../components/force-theme'
|
||||
import Icon from '../components/icon'
|
||||
import Nav from '../components/nav'
|
||||
import Header from '../components/slack/header'
|
||||
import SlackEvents from '../components/slack/slack-events'
|
||||
import Stat from '../components/stat'
|
||||
import fetcher from '../lib/fetcher'
|
||||
import { formatted, thousands } from '../lib/members'
|
||||
|
||||
const zoomSlide = keyframes({
|
||||
from: { backgroundPosition: '-32px bottom' },
|
||||
to: { backgroundPosition: '32px bottom' }
|
||||
})
|
||||
|
||||
const withCommas = x => x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
import Project from '../components/slack/project'
|
||||
import Quote from '../components/slack/quote'
|
||||
import Arrows from '../components/slack/arrows'
|
||||
|
||||
const SlackPage = () => {
|
||||
const { data: millionCount } = useSWR(
|
||||
'https://jia.haas.hackclub.com/api/currentNumber',
|
||||
fetcher,
|
||||
{ refreshInterval: 10_000 }
|
||||
)
|
||||
|
||||
const nameInputRef = useRef(null)
|
||||
|
||||
return (
|
||||
<>
|
||||
<style css>
|
||||
{/*this hides the horizontal scrollbar in the projects gallery*/}
|
||||
{`
|
||||
::-webkit-scrollbar {
|
||||
width:0px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background:transparent;
|
||||
}`}
|
||||
</style>
|
||||
<Meta
|
||||
as={Head}
|
||||
name="Join our Slack"
|
||||
|
|
@ -37,373 +44,126 @@ const SlackPage = () => {
|
|||
image="https://cloud-n6i5i4zb9-hack-club-bot.vercel.app/02020-07-25_d2dd4egb1th5k71w4uj0abbfkvvtnc01.jpeg"
|
||||
/>
|
||||
<ForceTheme theme="light" />
|
||||
<Nav />
|
||||
<Header />
|
||||
<Container sx={{ py: [4, 5] }}>
|
||||
<Grid
|
||||
columns={[2, 5]}
|
||||
gap={2}
|
||||
sx={{ maxWidth: 'copyPlus', alignItems: 'end' }}
|
||||
>
|
||||
<Stat
|
||||
value={`${thousands}k+`}
|
||||
label="total members"
|
||||
color="red"
|
||||
lg
|
||||
sx={{ gridColumn: 'span 2' }}
|
||||
/>
|
||||
<Stat value={6} label="continents" />
|
||||
<Stat value="1M+" label="messages/yr" />
|
||||
</Grid>
|
||||
<Text
|
||||
variant="subtitle"
|
||||
as="p"
|
||||
sx={{ maxWidth: 'copy', fontSize: [2, 3], mt: 3, mb: [3, 4] }}
|
||||
>
|
||||
Have a coding question? Looking for project feedback? You’ll find some
|
||||
fabulous people to talk to in our global Slack (Discord-style online
|
||||
groupchat) with {formatted}+ members, active at all hours.
|
||||
</Text>
|
||||
<Nav slack={true} />
|
||||
{/* <Box sx={{ position: 'fixed', mt: 5, maxWidth: '1024px', backgroundColor: 'red', zIndex: 100 }}>
|
||||
<Text>Hack Club Slack</Text>
|
||||
</Box>*/}
|
||||
<Header nameInputRef={nameInputRef} />
|
||||
<Container sx={{ pt: [4, 5], pb: 4 }}>
|
||||
<Heading
|
||||
as="h2"
|
||||
variant="title"
|
||||
sx={{ mt: [4, 5], color: 'black', maxWidth: 'copyUltra' }}
|
||||
>
|
||||
Channels for every interest.
|
||||
No commitments, just exploration...
|
||||
</Heading>
|
||||
<Text
|
||||
as="p"
|
||||
variant="subtitle"
|
||||
sx={{ maxWidth: 'copy', fontSize: [2, 3], mt: 3 }}
|
||||
>
|
||||
<Text as="p" variant="subtitle" sx={{ fontSize: [2, 3], mt: 3 }}>
|
||||
Across 2,000 public channels, find the community for your favorite
|
||||
programming language, ask for advice, or just hang out.
|
||||
programming language, ask for advice, or just hang out. Find the
|
||||
worlds that suit you.
|
||||
</Text>
|
||||
<Grid
|
||||
columns={[2, 9, 15]}
|
||||
gap={3}
|
||||
<Channels />
|
||||
{/*<Flex
|
||||
sx={{
|
||||
py: [3, 4],
|
||||
h3: { my: 0 },
|
||||
'> div': {
|
||||
px: [2, 3],
|
||||
py: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
gridColumn: ['span 1', 'span 3']
|
||||
},
|
||||
a: {
|
||||
position: 'relative',
|
||||
':hover,:focus': {
|
||||
svg: {
|
||||
transform: 'translateX(28px) translateY(-28px)',
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
svg: {
|
||||
position: 'absolute',
|
||||
top: 2,
|
||||
right: 2,
|
||||
fill: 'white',
|
||||
transition:
|
||||
'transform 0.25s ease-in-out, opacity 0.25s ease-in-out'
|
||||
},
|
||||
h3: {
|
||||
variant: 'text.headline',
|
||||
color: 'white',
|
||||
lineHeight: 'title',
|
||||
m: 0,
|
||||
'+ p': {
|
||||
mt: 2,
|
||||
color: 'white',
|
||||
opacity: 0.75,
|
||||
fontSize: 2,
|
||||
lineHeight: 'caption'
|
||||
}
|
||||
}
|
||||
gridRow: [null, 'span 2'],
|
||||
gridColumn: ['span 2', 'span 3'],
|
||||
maxHeight: '100%',
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
as="aside"
|
||||
<Heading
|
||||
as="h2"
|
||||
variant="subheadline"
|
||||
sx={{
|
||||
gridRow: [null, 'span 2'],
|
||||
gridColumn: ['span 2', 'span 3'],
|
||||
maxHeight: '100%',
|
||||
overflow: 'hidden'
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 'headline',
|
||||
width: '400px'
|
||||
}}
|
||||
>
|
||||
<Heading
|
||||
as="h2"
|
||||
variant="subheadline"
|
||||
sx={{
|
||||
mt: 0,
|
||||
mb: 0,
|
||||
color: 'red',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 'headline'
|
||||
}}
|
||||
>
|
||||
Live from our Slack <br />
|
||||
</Heading>
|
||||
<Text
|
||||
as="p"
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontSize: 1,
|
||||
fontWeight: 300,
|
||||
fontStyle: 'italic',
|
||||
mb: '16px'
|
||||
}}
|
||||
>
|
||||
Waiting for more messages...
|
||||
</Text>
|
||||
<SlackEvents />
|
||||
</Box>
|
||||
<NextLink href="/ship" passHref>
|
||||
<Card
|
||||
as="a"
|
||||
variant="interactive"
|
||||
sx={{
|
||||
gridColumn: ['span 2', 'span 5'],
|
||||
bg: 'blue',
|
||||
backgroundImage: t => t.util.gx('cyan', 'blue')
|
||||
}}
|
||||
>
|
||||
<Icon glyph="external" size={24} />
|
||||
<Heading as="h3" variant="headline">
|
||||
#ship
|
||||
</Heading>
|
||||
<Text as="p">Launch your latest projects & get feedback</Text>
|
||||
</Card>
|
||||
</NextLink>
|
||||
<Card
|
||||
as="a"
|
||||
href="https://scrapbook.hackclub.com/"
|
||||
variant="interactive"
|
||||
sx={{
|
||||
gridColumn: ['span 2', 'span 5'],
|
||||
bg: 'dark',
|
||||
backgroundImage: t => t.util.gx('yellow', 'orange')
|
||||
}}
|
||||
>
|
||||
<Icon glyph="external" size={24} />
|
||||
<Heading as="h3" variant="headline">
|
||||
#scrapbook
|
||||
</Heading>
|
||||
<Text as="p">A daily diary of project updates</Text>
|
||||
</Card>
|
||||
<Card
|
||||
bg="red"
|
||||
sx={{
|
||||
gridColumn: ['span 2 !important', 'span 2 !important'],
|
||||
gridRow: ['span 1 !important', 'span 3 !important'],
|
||||
writingMode: ['lr-tb', 'tb-rl']
|
||||
}}
|
||||
>
|
||||
<Heading as="h3">#counttoamillion</Heading>
|
||||
<Text as="p" sx={{ display: 'flex', alignItems: 'baseline' }}>
|
||||
We’re at{' '}
|
||||
<Badge
|
||||
variant="outline"
|
||||
as="span"
|
||||
sx={{ ml: [2, 0], mt: [0, 2], px: [2, 0], py: [0, 2] }}
|
||||
>
|
||||
{millionCount ? withCommas(millionCount.number) : '???'}
|
||||
</Badge>
|
||||
!
|
||||
</Text>
|
||||
</Card>
|
||||
<Card bg="cyan">
|
||||
<h3>#lounge</h3>
|
||||
</Card>
|
||||
<Card
|
||||
sx={{
|
||||
backgroundImage:
|
||||
'url(https://cloud-n6i5i4zb9-hack-club-bot.vercel.app/12020-07-25_fqxym71bmqjr1d35btawn5q6ph1zt0mk.png)',
|
||||
backgroundColor: '#FEC62E',
|
||||
backgroundPosition: 'center center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundSize: '100% auto',
|
||||
gridColumn: ['span 2', 'span 3 !important', 'span 4 !important'],
|
||||
h3: { opacity: 0 }
|
||||
}}
|
||||
>
|
||||
<h3>#design</h3>
|
||||
</Card>
|
||||
<Card
|
||||
bg="dark"
|
||||
sx={{ h3: { color: 'green', textShadow: '0 0 4px currentColor' } }}
|
||||
>
|
||||
<h3>#code</h3>
|
||||
</Card>
|
||||
<Card
|
||||
bg="yellow"
|
||||
sx={{
|
||||
backgroundImage:
|
||||
'url(https://assets.hackclub.com/log/2020-06-29_dog.jpg)',
|
||||
backgroundSize: '100%',
|
||||
backgroundPosition: 'center',
|
||||
textShadow: 'text',
|
||||
gridColumn: ['span 2', 'span 3 !important']
|
||||
}}
|
||||
>
|
||||
<h3>#dogs</h3>
|
||||
</Card>
|
||||
<Card bg="purple">
|
||||
<h3>#music</h3>
|
||||
</Card>
|
||||
<Card
|
||||
bg="red"
|
||||
sx={{
|
||||
backgroundImage: ({ colors }) =>
|
||||
`linear-gradient(-184deg, ${colors.red} 0%, ${colors.red} 16.6666%, ${colors.orange} 16.6666%, ${colors.orange} 33.333%, ${colors.yellow} 33.333%, ${colors.yellow} 50%, ${colors.green} 50%, ${colors.green} 66.6666%, ${colors.blue} 66.6666%, ${colors.blue} 83.3333%, ${colors.purple} 83.3333%, ${colors.purple} 100%)`
|
||||
}}
|
||||
>
|
||||
<h3>#lgbtq</h3>
|
||||
</Card>
|
||||
<Card
|
||||
sx={{
|
||||
bg: 'dark',
|
||||
backgroundImage:
|
||||
'url(https://cloud-jnfb0t781-hack-club-bot.vercel.app/02020-07-25_r6thfxwv1u0c71uw0qk94juv6fxxjygf.png)',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
textShadow: 'text',
|
||||
gridColumn: ['span 2 !important', 'span 4 !important']
|
||||
}}
|
||||
>
|
||||
<h3>#photography</h3>
|
||||
</Card>
|
||||
</Grid>
|
||||
<Heading
|
||||
as="h2"
|
||||
variant="title"
|
||||
sx={{ mt: [4, 5], color: 'black', maxWidth: 'copyUltra' }}
|
||||
>
|
||||
Events on Zoom that don’t suck.
|
||||
</Heading>
|
||||
<Grid
|
||||
columns={[null, 2]}
|
||||
gap={[3, 4]}
|
||||
Live from our Slack...
|
||||
</Heading>
|
||||
<SlackEvents />
|
||||
</Flex>*/}
|
||||
<Text as="h1" variant="title" sx={{ mt: [4, 5], mb: 3 }}>
|
||||
Where the makers hang out...
|
||||
</Text>
|
||||
<Text as="p" variant="subtitle" sx={{ fontSize: [2, 3], mt: 3 }}>
|
||||
These projects were built by Hack Clubbers all around the world on the
|
||||
Hack Club Slack.
|
||||
</Text>
|
||||
</Container>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: '#F9FAFC',
|
||||
paddingT: '1rem',
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
onMouseEnter={disableScroll}
|
||||
onMouseLeave={enableScroll}
|
||||
sx={{
|
||||
py: [3, 4],
|
||||
mx: [null, null, null, -4],
|
||||
h3: {
|
||||
variant: 'text.title',
|
||||
color: 'white',
|
||||
my: 0
|
||||
},
|
||||
p: {
|
||||
color: 'white',
|
||||
opacity: 0.875,
|
||||
fontSize: [2, 3],
|
||||
lineHeight: 'caption',
|
||||
mt: 2
|
||||
},
|
||||
a: {
|
||||
position: 'relative',
|
||||
pb: [4, 5],
|
||||
':hover,:focus': {
|
||||
svg: {
|
||||
transform: 'translateX(28px) translateY(-28px)',
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
svg: {
|
||||
position: 'absolute',
|
||||
top: 2,
|
||||
right: 2,
|
||||
fill: 'white',
|
||||
transition:
|
||||
'transform 0.25s ease-in-out, opacity 0.25s ease-in-out'
|
||||
}
|
||||
msScrollbarTrackColor: 'transparent',
|
||||
'::-webkit-scrollbar-track': 'background: transparent',
|
||||
'::-webkit-scrollbar-thumb': 'background: transparent'
|
||||
}}
|
||||
>
|
||||
<NextLink href="/amas" passHref>
|
||||
<Card
|
||||
as="a"
|
||||
variant="interactive"
|
||||
sx={{
|
||||
bg: '#000',
|
||||
backgroundImage:
|
||||
'linear-gradient(rgba(0,0,0,0.25),rgba(0,0,0,0.375)), url(https://cloud-n6i5i4zb9-hack-club-bot.vercel.app/22020-07-25_hz5hy2bw5x70ped8akzwtrj4hzuex3vw.jpeg)',
|
||||
backgroundSize: '100% auto',
|
||||
textShadow: 'text'
|
||||
}}
|
||||
>
|
||||
<Icon glyph="external" size={24} />
|
||||
<h3>AMAs</h3>
|
||||
<p>Zoom with someone remarkable</p>
|
||||
</Card>
|
||||
</NextLink>
|
||||
<NextLink href="/night" passHref>
|
||||
<Card
|
||||
as="a"
|
||||
variant="interactive"
|
||||
sx={{
|
||||
bg: 'dark',
|
||||
backgroundImage:
|
||||
'url(https://cloud-n6i5i4zb9-hack-club-bot.vercel.app/32020-07-25_pp7t4h8738hdm46r2xxrd8tz3kjc5x0t.png)',
|
||||
backgroundPosition: 'bottom center',
|
||||
backgroundSize: 'cover',
|
||||
h3: {
|
||||
textTransform: 'uppercase',
|
||||
WebkitTextStroke: 'white',
|
||||
WebkitTextStrokeWidth: '2px',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
filter: `drop-shadow(0 0 1px #50E3C2) drop-shadow(0 0 4px #50E3C2)`
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon glyph="external" size={24} />
|
||||
<h3>Hack Night</h3>
|
||||
<p>Weekly live coding & hangout on Zoom</p>
|
||||
</Card>
|
||||
</NextLink>
|
||||
<NextLink href="/minecraft" passHref>
|
||||
<Card
|
||||
as="a"
|
||||
variant="interactive"
|
||||
sx={{
|
||||
bg: '#759B40',
|
||||
backgroundImage:
|
||||
'url(https://cloud-n6i5i4zb9-hack-club-bot.vercel.app/42020-07-25_56ygmzej7r9kjrrudmnb0t0cmg0m3gtg.jpeg)',
|
||||
backgroundSize: 'cover',
|
||||
textShadow: 'text'
|
||||
}}
|
||||
>
|
||||
<Icon glyph="external" size={24} />
|
||||
<h3>Minecraft</h3>
|
||||
<p>Play on our server, build OSS plugins, compete</p>
|
||||
</Card>
|
||||
</NextLink>
|
||||
<Card
|
||||
as="a"
|
||||
href="https://events.hackclub.com/"
|
||||
variant="interactive"
|
||||
sx={{
|
||||
bg: '#3b6fce',
|
||||
backgroundImage:
|
||||
'url(https://cloud-n6i5i4zb9-hack-club-bot.vercel.app/52020-07-25_zoomus-icon.svg)',
|
||||
backgroundRepeat: 'repeat-x',
|
||||
backgroundPosition: '0 bottom',
|
||||
'@media (prefers-reduced-motion: no-preference)': {
|
||||
animation: `${zoomSlide} 2s linear infinite`
|
||||
}
|
||||
}}
|
||||
<ScrollMenu
|
||||
Footer={Arrows}
|
||||
transitionDuration={900}
|
||||
style={{ scrollbar: 'hidden' }}
|
||||
>
|
||||
<Icon glyph="external" size={24} />
|
||||
<h3>Community fun</h3>
|
||||
<p>Members run their own events—all with Zoom Pro</p>
|
||||
</Card>
|
||||
</Grid>
|
||||
{projects.map((project, i) => (
|
||||
<Project
|
||||
title={project.title}
|
||||
description={project.description}
|
||||
img={project.img}
|
||||
color={project.color}
|
||||
itemId={project.itemId}
|
||||
key={project.itemId}
|
||||
/>
|
||||
))}
|
||||
</ScrollMenu>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Container sx={{ py: [4, 5] }}>
|
||||
<Box sx={{ gap: '2rem', display: ['grid', 'grid', 'flex'] }}>
|
||||
<Quote
|
||||
text="I knew it's where I wanted to be"
|
||||
person="Shawn"
|
||||
img="https://cloud-8u876lgxi-hack-club-bot.vercel.app/0shawn.png"
|
||||
age={18}
|
||||
location="MD"
|
||||
/>
|
||||
<Quote
|
||||
text="I felt so free- there were no expectations"
|
||||
person="JC"
|
||||
img="https://ca.slack-edge.com/T0266FRGM-U03MNFDRSGJ-e6fb939acfd8-512"
|
||||
age={17}
|
||||
location="CT"
|
||||
/>
|
||||
<Quote
|
||||
text="Finally, I found my people!"
|
||||
person="Cheru"
|
||||
img="https://ca.slack-edge.com/T0266FRGM-U02UYFZQ0G0-eb4e3c7fb0cf-512"
|
||||
age={16}
|
||||
location="VT"
|
||||
/>
|
||||
</Box>
|
||||
<Join />
|
||||
</Container>
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function disableScroll() {
|
||||
document.body.style.overflowAnchor = 'hidden'
|
||||
}
|
||||
|
||||
function enableScroll() {
|
||||
document.body.style.overflowAnchor = 'scroll'
|
||||
}
|
||||
|
||||
export default SlackPage
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ export default function Team({ team }) {
|
|||
teamRole="Founder"
|
||||
text="Zach dropped out of high school after his freshman year to work in the technology industry and had over 5 million people using his software by the time he turned 17. He founded Hack Club to build the program he wish he had in high school and has been awarded the Thiel Fellowship and Forbes 30 Under 30 for his work."
|
||||
pronouns="he/him"
|
||||
email="zach"
|
||||
/>
|
||||
<Bio
|
||||
img="/team/christina.jpg"
|
||||
|
|
@ -94,6 +95,7 @@ export default function Team({ team }) {
|
|||
teamRole="Co-founder and COO"
|
||||
text="With more than a decade of experience in starting and leading organizations, Christina has built global teams and raised millions of dollars. She has 20 years experience as a journalist, including reporting for The New York Times from Iraq. She has an MA in education, and taught as a public school teacher in 2000, which inspired her book “The Emergency Teacher.”"
|
||||
pronouns="she/her"
|
||||
email="christina"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid columns={[1, null, 3]} gap={2}>
|
||||
|
|
@ -142,18 +144,21 @@ export default function Team({ team }) {
|
|||
>
|
||||
Hacker Resources Team
|
||||
</Text>
|
||||
<Grid columns={[1, null, 2]} gap={2}>
|
||||
{ team.current?.filter(member => member.department === "HQ").map(member => (
|
||||
<Bio
|
||||
img={member.avatar}
|
||||
name={member.name}
|
||||
teamRole={member.role}
|
||||
text={member.bio}
|
||||
pronouns={member.pronouns}
|
||||
key={member.name}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
<Grid columns={[1, null, 2]} gap={2}>
|
||||
{team.current
|
||||
?.filter(member => member.department === 'HQ')
|
||||
.map(member => (
|
||||
<Bio
|
||||
img={member.avatar}
|
||||
name={member.name}
|
||||
teamRole={member.role}
|
||||
text={member.bio}
|
||||
pronouns={member.pronouns}
|
||||
email={member.email}
|
||||
key={member.name}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box>
|
||||
|
|
@ -174,17 +179,20 @@ export default function Team({ team }) {
|
|||
HCB Team
|
||||
</Text>
|
||||
<Grid columns={[1, null, 2]} gap={2}>
|
||||
{ team.current?.filter(member => member.department === "HCB").map(member => (
|
||||
<Bio
|
||||
img={member.avatar}
|
||||
name={member.name}
|
||||
teamRole={member.role}
|
||||
text={member.bio}
|
||||
pronouns={member.pronouns}
|
||||
key={member.name}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
{team.current
|
||||
?.filter(member => member.department === 'HCB')
|
||||
.map(member => (
|
||||
<Bio
|
||||
img={member.avatar}
|
||||
name={member.name}
|
||||
teamRole={member.role}
|
||||
text={member.bio}
|
||||
pronouns={member.pronouns}
|
||||
email={member.email}
|
||||
key={member.name}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
|
@ -205,18 +213,21 @@ export default function Team({ team }) {
|
|||
>
|
||||
Community Team
|
||||
</Text>
|
||||
<Grid columns={[1, 2, null, 4]} gap={2}>
|
||||
{ team.current?.filter(member => member.department === "Community").map(member => (
|
||||
<Bio
|
||||
<Grid columns={[1, 2, null, 4]} gap={2}>
|
||||
{team.current
|
||||
?.filter(member => member.department === 'Community')
|
||||
.map(member => (
|
||||
<Bio
|
||||
img={member.avatar}
|
||||
name={member.name}
|
||||
teamRole={member.role}
|
||||
text={member.bio}
|
||||
pronouns={member.pronouns}
|
||||
key={member.name}
|
||||
email={member.email}
|
||||
key={member.name}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
<br />
|
||||
<Box sx={{ textAlign: 'center', mt: 2, mb: [3, 4] }}>
|
||||
|
|
@ -247,6 +258,13 @@ export default function Team({ team }) {
|
|||
</Text>
|
||||
</Box>
|
||||
<Grid columns={[1, null, 2, 4]} gap={2}>
|
||||
<Bio
|
||||
name="Lexi Mattick"
|
||||
teamRole="Clubs Engineering"
|
||||
text="Always driven by curiosity for how things work, Lexi fell in love with Hack Club in 2019 after joining a Hack Night call and discovering like-minded individuals. She spends her time programming, making music, and studying for her private pilot license; at Hack Club, she spends her time working on whatever fantastic project is happening in the present moment."
|
||||
img="/team/bean-man.jpg"
|
||||
pronouns="she/her"
|
||||
/>
|
||||
<Bio
|
||||
name="Holly Delisle"
|
||||
teamRole="Clubs Operations Lead"
|
||||
|
|
@ -460,10 +478,12 @@ When not busy juggling different tasks he takes up, he enjoys tinkering & buildi
|
|||
}
|
||||
|
||||
export const getServerSideProps = async () => {
|
||||
try {
|
||||
const team = await fetch("https://internal.hackclub.com/team").then((res) => res.json())
|
||||
return { props: { team } }
|
||||
} catch (e) {
|
||||
return { props: { team: [] }}
|
||||
}
|
||||
try {
|
||||
const team = await fetch('https://internal.hackclub.com/team').then(res =>
|
||||
res.json()
|
||||
)
|
||||
return { props: { team } }
|
||||
} catch (e) {
|
||||
return { props: { team: [] } }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
module.exports = {
|
||||
singleQuote: true,
|
||||
trailingComma: 'none',
|
||||
arrowParens: 'avoid',
|
||||
printWidth: 80,
|
||||
semi: false
|
||||
}
|
||||
BIN
public/fiscal-sponsorship/climate/Africa.png
Normal file
|
After Width: | Height: | Size: 1 MiB |
BIN
public/fiscal-sponsorship/climate/Asia+Oceania.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
public/fiscal-sponsorship/climate/Europe.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
public/fiscal-sponsorship/climate/NorthAmerica.png
Normal file
|
After Width: | Height: | Size: 708 KiB |
BIN
public/fiscal-sponsorship/climate/SouthAmerica.png
Normal file
|
After Width: | Height: | Size: 997 KiB |
BIN
public/fiscal-sponsorship/climate/earth-on-hcb.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 52 KiB |
BIN
public/fiscal-sponsorship/climate/social-preview.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
public/slack/bci.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
public/slack/burrow.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
public/slack/nest.png
Normal file
|
After Width: | Height: | Size: 556 KiB |
BIN
public/slack/oblong.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
public/slack/purplebubble.png
Normal file
|
After Width: | Height: | Size: 654 KiB |
BIN
public/team/bean-man.jpg
Normal file
|
After Width: | Height: | Size: 587 KiB |
94
yarn.lock
|
|
@ -15,10 +15,10 @@
|
|||
"@jridgewell/gen-mapping" "^0.3.0"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@apollo/client@^3.9.5":
|
||||
version "3.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.9.5.tgz#502ec191756a7f44788b5f08cbe7b8de594a7656"
|
||||
integrity sha512-7y+c8MTPU+hhTwvcGVtMMGIgWduzrvG1mz5yJMRyqYbheBkkky3Lki6ADWVSBXG1lZoOtPYvB2zDgVfKb2HSsw==
|
||||
"@apollo/client@^3.9.9":
|
||||
version "3.9.9"
|
||||
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.9.9.tgz#38f983a1ad24e2687abfced0a9c1c3bef8d32616"
|
||||
integrity sha512-/sMecU/M0WK9knrguts1lSLV8xFKzIgOMVb4mi6MOxgJXjliDB8PvOtmXhTqh2cVMMR4TzXgOnb+af/690zlQw==
|
||||
dependencies:
|
||||
"@graphql-typed-document-node/core" "^3.1.1"
|
||||
"@wry/caches" "^1.0.0"
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
hoist-non-react-statics "^3.3.2"
|
||||
optimism "^0.18.0"
|
||||
prop-types "^15.7.2"
|
||||
rehackt "0.0.5"
|
||||
rehackt "0.0.6"
|
||||
response-iterator "^0.2.6"
|
||||
symbol-observable "^4.0.0"
|
||||
ts-invariant "^0.10.3"
|
||||
|
|
@ -2065,6 +2065,29 @@
|
|||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz#5f1b518ec5fa54437c0b7c4a821546c64fed6922"
|
||||
integrity sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==
|
||||
|
||||
"@sendgrid/client@^8.1.1":
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@sendgrid/client/-/client-8.1.1.tgz#5c15b59973da3e108257883e408c4afd74844248"
|
||||
integrity sha512-pg0gYhAdyQil3Aga7/xHVcZFpvDAjAQMNBgMy5njTSkjACoWHmpSi1nWBZM7nIH/ptcRNMpnBbm9B5EvQ8fX2w==
|
||||
dependencies:
|
||||
"@sendgrid/helpers" "^8.0.0"
|
||||
axios "^1.6.4"
|
||||
|
||||
"@sendgrid/helpers@^8.0.0":
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@sendgrid/helpers/-/helpers-8.0.0.tgz#f74bf9743bacafe4c8573be46166130c604c0fc1"
|
||||
integrity sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==
|
||||
dependencies:
|
||||
deepmerge "^4.2.2"
|
||||
|
||||
"@sendgrid/mail@^8.1.1":
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@sendgrid/mail/-/mail-8.1.1.tgz#506bc02c3a884d5c979278d6966f118afce37f93"
|
||||
integrity sha512-tNtmgWLtBA7ZxKtPuEGOaIdEZP1vZSXsj5zg9iuoDBPVj/fNz+7LWzndvTcKumHk5eaDrS0UPXJqBm61m3+H1A==
|
||||
dependencies:
|
||||
"@sendgrid/client" "^8.1.1"
|
||||
"@sendgrid/helpers" "^8.0.0"
|
||||
|
||||
"@styled-system/background@^5.1.2":
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmjs.org/@styled-system/background/-/background-5.1.2.tgz"
|
||||
|
|
@ -2853,7 +2876,7 @@ axe-core@^4.6.2:
|
|||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.2.tgz#2f6f3cde40935825cf4465e3c1c9e77b240ff6ae"
|
||||
integrity sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g==
|
||||
|
||||
axios@^1.6.7:
|
||||
axios@^1.6.4, axios@^1.6.7:
|
||||
version "1.6.7"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7"
|
||||
integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==
|
||||
|
|
@ -3198,20 +3221,10 @@ camelize@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3"
|
||||
integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==
|
||||
|
||||
caniuse-lite@^1.0.30001202, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001228, caniuse-lite@^1.0.30001282, caniuse-lite@^1.0.30001541:
|
||||
version "1.0.30001554"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz#ba80d88dff9acbc0cd4b7535fc30e0191c5e2e2a"
|
||||
integrity sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==
|
||||
|
||||
caniuse-lite@^1.0.30001406:
|
||||
version "1.0.30001474"
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001474.tgz"
|
||||
integrity sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q==
|
||||
|
||||
caniuse-lite@^1.0.30001517:
|
||||
version "1.0.30001520"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz#62e2b7a1c7b35269594cf296a80bdf8cb9565006"
|
||||
integrity sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA==
|
||||
caniuse-lite@^1.0.30001202, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001228, caniuse-lite@^1.0.30001282, caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001541:
|
||||
version "1.0.30001600"
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz"
|
||||
integrity sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==
|
||||
|
||||
caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
|
|
@ -3410,6 +3423,11 @@ commondir@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||
integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
|
||||
|
||||
compute-scroll-into-view@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz#753f11d972596558d8fe7c6bcbc8497690ab4c87"
|
||||
integrity sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||
|
|
@ -4497,9 +4515,9 @@ flatted@^3.1.0:
|
|||
integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==
|
||||
|
||||
follow-redirects@^1.15.4:
|
||||
version "1.15.5"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020"
|
||||
integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==
|
||||
version "1.15.6"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
|
||||
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
|
||||
|
||||
for-each@^0.3.3:
|
||||
version "0.3.3"
|
||||
|
|
@ -7345,6 +7363,13 @@ react-fast-compare@^3.2.0:
|
|||
resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz"
|
||||
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
|
||||
|
||||
react-horizontal-scrolling-menu@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-horizontal-scrolling-menu/-/react-horizontal-scrolling-menu-6.0.2.tgz#9b34ce979880e60803e24f53db122ab6ef6a714c"
|
||||
integrity sha512-TuM9QunJ6ykA5OUjScBvB+e0IM60wXGSTmbzs5zoLwaCX3rnSoJejj8ScQ3wP/MWr88OeSEh1RN4TCa3fTGuqA==
|
||||
dependencies:
|
||||
smooth-scroll-into-view-if-needed "^2.0.2"
|
||||
|
||||
react-is@16.13.1, react-is@^16.10.2, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||
|
|
@ -7632,10 +7657,10 @@ regjsparser@^0.9.1:
|
|||
dependencies:
|
||||
jsesc "~0.5.0"
|
||||
|
||||
rehackt@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.0.5.tgz#184c82ea369d5b0b989ede0593ebea8b2bcfb1d6"
|
||||
integrity sha512-BI1rV+miEkaHj8zd2n+gaMgzu/fKz7BGlb4zZ6HAiY9adDmJMkaDcmuXlJFv0eyKUob+oszs3/2gdnXUrzx2Tg==
|
||||
rehackt@0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.0.6.tgz#7a0a2247f2295e7548915417e44fbbf03bf004f4"
|
||||
integrity sha512-l3WEzkt4ntlEc/IB3/mF6SRgNHA6zfQR7BlGOgBTOmx7IJJXojDASav+NsgXHFjHn+6RmwqsGPFgZpabWpeOdw==
|
||||
|
||||
rehype-parse@^8.0.0:
|
||||
version "8.0.5"
|
||||
|
|
@ -7955,6 +7980,13 @@ scheduler@^0.20.2:
|
|||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
scroll-into-view-if-needed@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz#fa9524518c799b45a2ef6bbffb92bcad0296d01f"
|
||||
integrity sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==
|
||||
dependencies:
|
||||
compute-scroll-into-view "^3.0.2"
|
||||
|
||||
semver@^5.4.1:
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||
|
|
@ -8067,6 +8099,13 @@ slash@^4.0.0:
|
|||
resolved "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz"
|
||||
integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
|
||||
|
||||
smooth-scroll-into-view-if-needed@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/smooth-scroll-into-view-if-needed/-/smooth-scroll-into-view-if-needed-2.0.2.tgz#5bd4ebef668474d6618ce8704650082e93068371"
|
||||
integrity sha512-z54WzUSlM+xHHvJu3lMIsh+1d1kA4vaakcAtQvqzeGJ5Ffau7EKjpRrMHh1/OBo5zyU2h30ZYEt77vWmPHqg7Q==
|
||||
dependencies:
|
||||
scroll-into-view-if-needed "^3.1.0"
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
|
||||
|
|
@ -8196,7 +8235,6 @@ string-hash@1.1.3:
|
|||
integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
|
||||
name string-width-cjs
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
|
|
|
|||