mirror of
https://github.com/System-End/site.git
synced 2026-04-19 19:45:07 +00:00
Prefill team name on FIRST page
This commit is contained in:
parent
b11e3f1fba
commit
c0a888fd07
4 changed files with 145 additions and 47 deletions
|
|
@ -1,14 +1,20 @@
|
|||
import { Box, Input, Label, Button, Select, Text } from 'theme-ui'
|
||||
import { useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import theme from '@hackclub/theme'
|
||||
import Icon from '../../icon'
|
||||
import { keyframes } from '@emotion/react'
|
||||
import debounce from 'lodash/debounce'
|
||||
|
||||
const hideAnimation = keyframes({
|
||||
from: { display: 'flex' },
|
||||
to: { display: 'none', opacity: 0, padding: 0, position: 'absolute' }
|
||||
})
|
||||
|
||||
const spinAnimation = keyframes({
|
||||
from: { transform: 'rotate(0deg)' },
|
||||
to: { transform: 'rotate(360deg)' }
|
||||
})
|
||||
|
||||
function Base({ children, action, target, method, onSubmit, id }) {
|
||||
return (
|
||||
<Box
|
||||
|
|
@ -32,25 +38,43 @@ function Field({
|
|||
type,
|
||||
value,
|
||||
onChange,
|
||||
required = true
|
||||
required = true,
|
||||
loading = false
|
||||
}) {
|
||||
return (
|
||||
<Box sx={{ my: 2 }}>
|
||||
<Label htmlFor={name} sx={{ color: 'muted', fontSize: 18 }}>
|
||||
{label}
|
||||
</Label>
|
||||
<Input
|
||||
id={name}
|
||||
placeholder={placeholder}
|
||||
name={name}
|
||||
type={type}
|
||||
sx={{
|
||||
bg: 'dark'
|
||||
}}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
required={required}
|
||||
/>
|
||||
<Box sx={{ position: 'relative' }}>
|
||||
{loading && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 10,
|
||||
right: 10,
|
||||
width: 20,
|
||||
height: 20,
|
||||
border: '1px solid white',
|
||||
borderRightStyle: 'none',
|
||||
animation: `${spinAnimation} 1s linear infinite`,
|
||||
borderRadius: '50%'
|
||||
}}
|
||||
></Box>
|
||||
)}
|
||||
<Input
|
||||
id={name}
|
||||
placeholder={placeholder}
|
||||
name={name}
|
||||
type={type}
|
||||
sx={{
|
||||
bg: 'dark'
|
||||
}}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
required={required}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
|
@ -58,34 +82,60 @@ function Field({
|
|||
export default function Signup() {
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
|
||||
const [values, setValues] = useState({
|
||||
locationState: '',
|
||||
locationCountry: '',
|
||||
teamName: '',
|
||||
teamType: '',
|
||||
teamNumber: '',
|
||||
userEmail: ''
|
||||
})
|
||||
const [eventName, setEventName] = useState('')
|
||||
const [teamType, setTeamType] = useState('')
|
||||
const [teamNumber, setTeamNumber] = useState('')
|
||||
const [userEmail, setUserEmail] = useState('')
|
||||
|
||||
const [teamNameLoading, setTeamNameLoading] = useState(false)
|
||||
|
||||
const debouncedTeamNameUpdate = useRef(
|
||||
debounce(async teamNumber => {
|
||||
try {
|
||||
const data = await fetch(
|
||||
`/api/first-team?teamNumber=${teamNumber}`
|
||||
).then(res => res.json())
|
||||
|
||||
setTeamNameLoading(false)
|
||||
|
||||
if (data.ok !== false) {
|
||||
setEventName(data.nickname)
|
||||
} else {
|
||||
setEventName('')
|
||||
}
|
||||
} catch (e) {}
|
||||
}, 200)
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (teamNumber && teamType === 'FRC') {
|
||||
setTeamNameLoading(true)
|
||||
debouncedTeamNameUpdate.current(teamNumber)
|
||||
} else {
|
||||
setEventName('')
|
||||
}
|
||||
}, [teamType, teamNumber])
|
||||
|
||||
const handleSubmit = async e => {
|
||||
e.preventDefault()
|
||||
|
||||
await fetch('/api/bank/demo', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(values)
|
||||
body: JSON.stringify({
|
||||
eventName,
|
||||
teamType,
|
||||
teamNumber,
|
||||
userEmail
|
||||
})
|
||||
})
|
||||
|
||||
setSubmitted(true)
|
||||
|
||||
// clear form
|
||||
setValues({
|
||||
locationState: '',
|
||||
locationCountry: '',
|
||||
eventName: '',
|
||||
teamType: '',
|
||||
teamNumber: '',
|
||||
userEmail: ''
|
||||
})
|
||||
setEventName('')
|
||||
setTeamType('')
|
||||
setTeamNumber('')
|
||||
setUserEmail('')
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -96,13 +146,6 @@ export default function Signup() {
|
|||
action="/api/bank/demo"
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<Field
|
||||
label="Team Name"
|
||||
name="eventName"
|
||||
placeholder="Poseidon Robotics"
|
||||
value={values.eventName}
|
||||
onChange={e => setValues({ ...values, eventName: e.target.value })}
|
||||
/>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'row', gap: 2, w: '100%' }}>
|
||||
<Box sx={{ my: 2 }}>
|
||||
<Label htmlFor="teamType" sx={{ color: 'muted', fontSize: 18 }}>
|
||||
|
|
@ -111,11 +154,9 @@ export default function Signup() {
|
|||
name="teamType"
|
||||
defaultValue="Select"
|
||||
sx={{ bg: 'dark' }}
|
||||
onChange={e =>
|
||||
setValues({ ...values, teamType: e.target.value })
|
||||
}
|
||||
onChange={e => setTeamType(e.target.value)}
|
||||
>
|
||||
<option value="Select" selected disabled>
|
||||
<option value="Select" disabled>
|
||||
Select
|
||||
</option>
|
||||
<option value="FLL">FLL</option>
|
||||
|
|
@ -129,18 +170,26 @@ export default function Signup() {
|
|||
label="Team number (optional)"
|
||||
name="teamNumber"
|
||||
placeholder="12345"
|
||||
value={values.teamNumber}
|
||||
onChange={e => setValues({ ...values, teamNumber: e.target.value })}
|
||||
value={teamNumber}
|
||||
loading={teamNameLoading}
|
||||
onChange={e => setTeamNumber(e.target.value)}
|
||||
required={false}
|
||||
/>
|
||||
</Box>
|
||||
<Field
|
||||
label="Team name"
|
||||
name="eventName"
|
||||
placeholder="Poseidon Robotics"
|
||||
value={eventName}
|
||||
onChange={e => setEventName(e.target.value)}
|
||||
/>
|
||||
<Field
|
||||
label="Email address"
|
||||
name="userEmail"
|
||||
placeholder="fiona@hackclub.com"
|
||||
type="email"
|
||||
value={values.userEmail}
|
||||
onChange={e => setValues({ ...values, userEmail: e.target.value })}
|
||||
value={userEmail}
|
||||
onChange={e => setUserEmail(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
sx={{
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
"airtable-plus": "^1.0.4",
|
||||
"animated-value": "^0.2.4",
|
||||
"animejs": "^3.2.1",
|
||||
"axios": "^1.1.3",
|
||||
"country-list-js": "^3.1.7",
|
||||
"globby": "^11.0.4",
|
||||
"jquery": "^3.6.1",
|
||||
|
|
|
|||
20
pages/api/first-team.js
Normal file
20
pages/api/first-team.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import axios from 'axios'
|
||||
|
||||
export default async function handler(req, res) {
|
||||
try {
|
||||
const { data } = await axios(
|
||||
`https://thebluealliance.com/api/v3/team/frc${encodeURIComponent(
|
||||
req.query.teamNumber
|
||||
)}`,
|
||||
{
|
||||
headers: {
|
||||
'X-TBA-Auth-Key': process.env.TBA_API_KEY
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
res.json(data)
|
||||
} catch (e) {
|
||||
res.status(404).json({ ok: false })
|
||||
}
|
||||
}
|
||||
30
yarn.lock
30
yarn.lock
|
|
@ -1351,6 +1351,15 @@ axe-core@^4.3.5:
|
|||
resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.3.5.tgz"
|
||||
integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==
|
||||
|
||||
axios@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35"
|
||||
integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
axobject-query@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz"
|
||||
|
|
@ -1576,7 +1585,7 @@ color-name@~1.1.4:
|
|||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
|
|
@ -2301,11 +2310,25 @@ flatted@^3.1.0:
|
|||
resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz"
|
||||
integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==
|
||||
|
||||
follow-redirects@^1.15.0:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
|
||||
forever-agent@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz"
|
||||
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz"
|
||||
|
|
@ -3589,6 +3612,11 @@ property-information@^5.0.0, property-information@^5.3.0:
|
|||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
psl@^1.1.24:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue