Skip to content
This repository was archived by the owner on Nov 5, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"parser": "babel-eslint",
"extends": ["standard", "standard-react"],
"rules": {
"react/react-in-jsx-scope": "disable"
"react/react-in-jsx-scope": "disable",
"no-unused-vars": ["error", { "varsIgnorePattern": "^jsx$" }]
}
}
265 changes: 265 additions & 0 deletions frontend/components/creator/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
/* @jsx jsx */
import posed from 'react-pose'
import { Formik } from 'formik'
import { Component } from 'react'
import { lighten } from 'polished'
import { jsx } from '@emotion/core'
import { object, string } from 'yup'
import slugify from '@sindresorhus/slugify'
import { string as str, func } from 'prop-types'
import { Heading, Card, Flex, Text, Button, Box } from '@rebass/emotion'

import theme from '../../theme'

const ValidationSchema = object().shape({
title: string()
.trim()
.min(2, 'Your event name needs to be a bit longer.')
.required('We need a name for your event!'),
slug: string()
.trim()
.transform(val => slugify(val))
.min(2, 'Your url handle needs to be a bit longer.')
})

const Form = posed.form({
enter: { opacity: 1, delay: 200, staggerChildren: 400 },
exit: { opacity: 0 }
})

const FormSection = posed(Box)({
enter: { opacity: 1 },
exit: { opacity: 0 }
})

const ErrorMessage = posed(Text)({
error: { opacity: 1, height: 'auto', y: 0 },
ok: { opacity: 0, height: 0, y: -20 }
})

class Creator extends Component {
state = {
slugModified: false
}

trimTitle (event, setFieldValue) {
const { value } = event.target

setFieldValue('title', value.trim())
}

formatSlug (event, setFieldValue) {
const { slugModified } = this.state
const { value } = event.target

if (!slugModified) this.setState({ slugModified: true })

const newSlug = value
.toLowerCase()
.split(' ')
.map(val =>
val
.split('-')
.map(v => slugify(v))
.join('-')
)
.join('-')

setFieldValue('slug', newSlug)
}

trimSlug (event, setFieldValue) {
const slug = event.target.value
const newSlug = slug
.split('-')
.filter(c => c !== '')
.join('-')

setFieldValue('slug', slugify(newSlug))
}

render () {
const { example, onSubmit } = this.props
const { slugModified } = this.state

return (
<Formik
initialValues={{ title: '', slug: '' }}
validationSchema={ValidationSchema}
onSubmit={onSubmit}
>
{({
values,
touched,
errors,
dirty,
isSubmitting,
handleChange,
handleSubmit,
handleReset,
setFieldValue
}) => (
<Form onSubmit={handleSubmit} initialPose='exit' pose='enter'>
<FormSection mb={4}>
<Heading as='label' fontFamily='sans' htmlFor='title'>
Event Name
</Heading>
<Card
as='input'
id='title'
placeholder={example}
type='text'
value={values.title}
onChange={handleChange}
onBlur={e => this.trimTitle(e, setFieldValue)}
width={1}
mt={2}
p={2}
border={'three'}
borderColor={errors.title && touched.title ? 'pink' : 'black'}
borderRadius={4}
fontSize={16}
css={{
textAlign: 'center',
fontFamily: 'Inter UI, sans-serif'
}}
/>
{errors.title && touched.title && (
<ErrorMessage
initialPose='ok'
pose='error'
fontFamily='sans'
color='pink'
textAlign='right'
mt={2}
>
{errors.title}
</ErrorMessage>
)}
</FormSection>
<FormSection mb={4}>
<Heading as='label' fontFamily='sans' htmlFor='slug'>
Event URL
</Heading>
<Flex>
<Card
width={1 / 6}
p={2}
mt={2}
border='three'
borderColor={errors.slug && touched.slug ? 'pink' : 'black'}
borderRadius='4px 0 0 4px'
css={{
textAlign: 'center'
}}
bg={errors.slug && touched.slug ? 'pink' : 'black'}
>
<Text fontFamily='serif' color='white'>
https://
</Text>
</Card>
<Card
as='input'
id='slug'
placeholder={slugify(example)}
type='text'
value={touched.title && !slugModified ? slugify(values.title) : values.slug}
onFocus={e => {
;(!slugModified || e.target.value === '') &&
setFieldValue('slug', slugify(values.title))
}}
onChange={e => this.formatSlug(e, setFieldValue)}
onBlur={e => this.trimSlug(e, setFieldValue)}
width={1 / 2}
fontSize={16}
mt={2}
p={2}
border={'three'}
borderColor={errors.slug && touched.slug ? 'pink' : 'black'}
color={errors.slug && touched.slug ? 'pink' : 'black'}
css={{
textAlign: 'center',
borderRight: 0,
borderLeft: 0,
fontFamily: 'Inter UI, sans-serif'
}}
/>
<Card
width={1 / 3}
p={2}
mt={2}
border='three'
borderColor={errors.slug && touched.slug ? 'pink' : 'black'}
borderRadius='0 4px 4px 0'
css={{
textAlign: 'center'
}}
bg={errors.slug && touched.slug ? 'pink' : 'black'}
>
<Text fontFamily='serif' color='white'>
.knife.sh
</Text>
</Card>
</Flex>
{errors.slug && touched.slug && (
<ErrorMessage
initialPose='ok'
pose='error'
fontFamily='sans'
color='pink'
textAlign='right'
mt={2}
>
{errors.slug}
</ErrorMessage>
)}
</FormSection>
<FormSection>
<Flex width={1} justifyContent='flex-end' alignItems='flex-end'>
<Button
onClick={handleReset}
disabled={!dirty || isSubmitting}
bg='white'
mx={1}
border='three'
color='black'
css={{
':disabled': {
color: lighten(0.5, theme.colors.black),
borderColor: lighten(0.5, theme.colors.black)
}
}}
>
Reset
</Button>
<Button
type='submit'
disabled={!dirty || isSubmitting}
bg='green'
border='three'
color='black'
css={{
':disabled': {
backgroundColor: lighten(0.4, theme.colors.green),
color: lighten(0.5, theme.colors.black),
borderColor: lighten(0.5, theme.colors.black)
}
}}
>
Submit
</Button>
</Flex>
</FormSection>
</Form>
)}
</Formik>
)
}
}

Creator.propTypes = {
example: str.isRequired,
onSubmit: func.isRequired
}

export default Creator
2 changes: 1 addition & 1 deletion frontend/components/navbar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default () => (
</Flex>
<Flex width={2 / 3} justifyContent='flex-end'>
<a>
<Button bg='white' color='black' border='3px solid black'>
<Button bg='white' color='black' border={'three'}>
<Text fontFamily='sans'>Sign In</Text>
</Button>
</a>
Expand Down
8 changes: 7 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@
"@emotion/core": "^10.0.4",
"@emotion/styled": "^10.0.4",
"@rebass/emotion": "^3.0.0",
"@sindresorhus/slugify": "^0.6.0",
"cross-fetch": "^2.2.3",
"emotion-theming": "^10.0.4",
"formik": "^1.4.0",
"next": "^7.0.2",
"polished": "^2.3.1",
"prop-types": "^15.6.2",
"react": "^16.6.3",
"react-dom": "^16.6.3"
"react-dom": "^16.6.3",
"react-pose": "^4.0.4",
"sillyname": "^0.1.0",
"yup": "^0.26.6"
}
}
8 changes: 4 additions & 4 deletions frontend/pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ const Highlight = styled.div`
background: rgb(76, 255, 190);
background: linear-gradient(
35deg,
rgba(76, 255, 190, 1) 5%,
rgba(19, 85, 255, 1) 50%,
rgba(255, 19, 175, 1) 95%
rgba(0, 255, 162, 1) 5%,
rgba(0, 71, 255, 1) 50%,
rgba(255, 0, 168, 1) 95%
);
height: 20px;
width: 100%;
`

export default class MyApp extends App {
static async getInitialProps ({ Component, router, ctx }) {
static async getInitialProps ({ Component, ctx }) {
let pageProps = {}

if (Component.getInitialProps) {
Expand Down
59 changes: 59 additions & 0 deletions frontend/pages/create/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Component } from 'react'
import sillyname from 'sillyname'
import { string } from 'prop-types'
import { Flex, Card, Heading } from '@rebass/emotion'

import Creator from '../../components/creator'

class CreatePage extends Component {
static getInitialProps ({ req }) {
const isServer = typeof global === 'undefined'
const example = `${sillyname()} Jam`
let hostname
if (req) {
hostname = `https://${req.headers.host}`
} else {
const { protocol, host } = window.location
hostname = `${protocol}//${host}`
}

return { hostname, isServer, example }
}

render () {
return (
<main>
<Flex width={1} justifyContent='center' alignItems='center'>
<Card
m={3}
width={[1, null, 2 / 3, 1 / 2]}
p={[3, 4, 5]}
borderRadius={7}
boxShadow={[null, null, '0 2px 16px rgba(0, 0, 0, 0.25)']}
>
<Heading fontFamily='sans' mb={4} fontSize={[30, 50]} lineHeight={[1, 0.98]}>
Let's get your event started.
</Heading>
<Creator
example={this.props.example}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
window.alert(JSON.stringify(values, null, 2))
setSubmitting(false)
}, 400)
}}
/>
</Card>
</Flex>
</main>
)
}
}

CreatePage.propTypes = {
// hostname: string,
// isServer: bool,
example: string.isRequired
}

export default CreatePage
Loading