mirror of
https://github.com/System-End/site.git
synced 2026-04-19 19:45:07 +00:00
Fix Replit form
This commit is contained in:
parent
3c0a47c9b9
commit
cc7fd17beb
5 changed files with 130 additions and 112 deletions
|
|
@ -1,19 +1,98 @@
|
|||
import { useState } from 'react'
|
||||
import { useState, useRef, useEffect } from 'react'
|
||||
import { Box, Button, Card, Link, Input, Text, Flex, Image } from 'theme-ui'
|
||||
import Icon from '@hackclub/icons'
|
||||
import JSConfetti from 'js-confetti'
|
||||
import { FilloutStandardEmbed } from '@fillout/react'
|
||||
import '@fillout/react/style.css'
|
||||
|
||||
import theme from '../../lib/theme'
|
||||
|
||||
const ReplitForm = ({ cssDark }) => {
|
||||
const [currentStep, setCurrentStep] = useState(1)
|
||||
const [isSubmitted, setIsSubmitted] = useState(false)
|
||||
const [buttonText, setButtonText] = useState('Submit')
|
||||
const [formData, setFormData] = useState({})
|
||||
let jsConfetti = useRef()
|
||||
let draggedSticker = useRef()
|
||||
|
||||
useEffect(() => {
|
||||
jsConfetti.current = new JSConfetti()
|
||||
|
||||
document.onmousedown = e => {
|
||||
if (e.target.classList.contains('sticker')) {
|
||||
const rect = e.target.getBoundingClientRect()
|
||||
const stickerCentreX = rect.left + rect.width / 2
|
||||
const stickerCentreY = rect.top + rect.height / 2
|
||||
|
||||
e.target.dataset.offsetX = e.clientX - stickerCentreX
|
||||
e.target.dataset.offsetY = e.clientY - stickerCentreY
|
||||
|
||||
document.body.appendChild(e.target)
|
||||
draggedSticker.current = e.target
|
||||
draggedSticker.current.style.left = `${e.pageX - draggedSticker.current.dataset.offsetX}px`
|
||||
draggedSticker.current.style.top = `${e.pageY - draggedSticker.current.dataset.offsetY}px`
|
||||
setTimeout(() => draggedSticker.current.classList.add('dragged'), 0)
|
||||
}
|
||||
}
|
||||
|
||||
document.onmousemove = e => {
|
||||
if (draggedSticker.current) {
|
||||
draggedSticker.current.style.left = `${e.pageX - draggedSticker.current.dataset.offsetX}px`
|
||||
draggedSticker.current.style.top = `${e.pageY - draggedSticker.current.dataset.offsetY}px`
|
||||
}
|
||||
}
|
||||
|
||||
document.onmouseup = () => {
|
||||
if (draggedSticker.current) {
|
||||
draggedSticker.current.classList.remove('dragged')
|
||||
draggedSticker.current = null
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleInputChange = e => {
|
||||
const { name, value } = e.target
|
||||
setFormData(prev => ({ ...prev, [name]: value }))
|
||||
}
|
||||
|
||||
const submitForm = () => {
|
||||
console.log('submitting')
|
||||
const submitForm = async () => {
|
||||
setIsSubmitted(true)
|
||||
try {
|
||||
const res = await fetch('/api/replit/signup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(formData)
|
||||
})
|
||||
|
||||
const data = await res.json()
|
||||
|
||||
if (res.ok) {
|
||||
setButtonText(data.message)
|
||||
if (data.success) {
|
||||
jsConfetti.current.addConfetti({
|
||||
confettiColors: [
|
||||
theme.colors.red,
|
||||
theme.colors.orange,
|
||||
theme.colors.yellow,
|
||||
theme.colors.green,
|
||||
theme.colors.cyan,
|
||||
theme.colors.blue,
|
||||
theme.colors.purple
|
||||
]
|
||||
})
|
||||
setCurrentStep(3)
|
||||
}
|
||||
} else {
|
||||
setButtonText('Error')
|
||||
console.error('Error', res, data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error)
|
||||
} finally {
|
||||
setIsSubmitted(false)
|
||||
}
|
||||
}
|
||||
|
||||
const stickers = [
|
||||
|
|
@ -36,7 +115,7 @@ const ReplitForm = ({ cssDark }) => {
|
|||
|
||||
const buttonStyle = ({ disabled }) => ({
|
||||
backgroundColor: cssDark,
|
||||
cursor: disabled ? 'not-allowed' : 'auto',
|
||||
cursor: disabled ? 'not-allowed' : 'pointer',
|
||||
opacity: disabled ? 0.5 : 1
|
||||
})
|
||||
|
||||
|
|
@ -151,7 +230,7 @@ const ReplitForm = ({ cssDark }) => {
|
|||
...buttonStyle({ disabled: submitButtonDisabled })
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
{buttonText}
|
||||
</Button>
|
||||
</Flex>
|
||||
<StepIndicator step={2} />
|
||||
|
|
@ -174,27 +253,13 @@ const ReplitForm = ({ cssDark }) => {
|
|||
Get free stickers Get free stickers{' '}
|
||||
</Text>
|
||||
|
||||
<style>
|
||||
{`
|
||||
.sticker {
|
||||
scale: 1;
|
||||
filter: drop-shadow(0 0 0.2rem #0008);
|
||||
transition: scale 0.1s, filter 0.1s;
|
||||
}
|
||||
|
||||
.sticker:hover {
|
||||
scale: 1.2;
|
||||
filter: drop-shadow(0 0 0.6rem #0004);
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
{stickers.map((sticker, idx) => {
|
||||
const pos = getRandomPointOnUnitSquare()
|
||||
return (
|
||||
<Image
|
||||
src={sticker}
|
||||
width="64"
|
||||
height="64"
|
||||
width="72"
|
||||
height="72"
|
||||
alt="orpheus dinosaur labelled 'hackers assemble'"
|
||||
className="sticker"
|
||||
sx={{
|
||||
|
|
@ -209,6 +274,9 @@ const ReplitForm = ({ cssDark }) => {
|
|||
/>
|
||||
)
|
||||
})}
|
||||
<Box sx={{ width: 'calc(100% + calc(1.82rem * 2))', marginX: '-1.82em' }}>
|
||||
<FilloutStandardEmbed filloutId="ji6Jw9xpBPus" />
|
||||
</Box>
|
||||
<StepIndicator step={3} />
|
||||
</Box>
|
||||
)
|
||||
|
|
@ -226,7 +294,7 @@ const ReplitForm = ({ cssDark }) => {
|
|||
case 2:
|
||||
return [1 + margin, 1 - position]
|
||||
case 3:
|
||||
return [1 - position, -margin]
|
||||
return [1 - position, 0]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +309,20 @@ const ReplitForm = ({ cssDark }) => {
|
|||
overflow: 'initial'
|
||||
}}
|
||||
>
|
||||
<style>{`.step { transition: opacity 0.1s; }`}</style>
|
||||
<style>{`
|
||||
.step { transition: opacity 0.1s; }
|
||||
|
||||
.sticker {
|
||||
scale: 1;
|
||||
filter: drop-shadow(0 0 0.2rem #0008);
|
||||
transition: scale 0.3s ease, filter 0.3s ease;
|
||||
}
|
||||
|
||||
.sticker.dragged {
|
||||
scale: 1.2;
|
||||
filter: drop-shadow(0 0 0.6rem #0004);
|
||||
}
|
||||
`}</style>
|
||||
{step1()}
|
||||
{step2()}
|
||||
{step3()}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"@apollo/client": "^3.9.11",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@fillout/react": "^1.1.2",
|
||||
"@github/time-elements": "^4.0.0",
|
||||
"@hackclub/icons": "^0.0.14",
|
||||
"@hackclub/markdown": "^0.0.43",
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default async function handler(req, res) {
|
|||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const data = await response.text()
|
||||
const data = await response.json()
|
||||
|
||||
// Send the response from the replit-takeout service back to the client
|
||||
res.status(200).json(data)
|
||||
|
|
|
|||
|
|
@ -1,97 +1,12 @@
|
|||
import {
|
||||
Box,
|
||||
Link,
|
||||
Grid,
|
||||
Image,
|
||||
Container,
|
||||
Button,
|
||||
Heading,
|
||||
Text,
|
||||
Label,
|
||||
Input,
|
||||
Card,
|
||||
Progress
|
||||
} from 'theme-ui'
|
||||
import { Box, Link, Image, Button, Heading, Text, Card } from 'theme-ui'
|
||||
import Head from 'next/head'
|
||||
import Meta from '@hackclub/meta'
|
||||
import Footer from '../components/footer'
|
||||
import Nav from '../components/nav'
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
import Submit from '../components/submit'
|
||||
import ForceTheme from '../components/force-theme'
|
||||
import ReplitForm from '../components/replit/form'
|
||||
|
||||
const ReplitPage = () => {
|
||||
const [token, setToken] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
|
||||
const [submitStatus, setSubmitStatus] = useState('default')
|
||||
const [responseText, setResponseText] = useState('')
|
||||
const [progressText, setProgressText] = useState(0)
|
||||
|
||||
const intervalRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem('token')
|
||||
const email = localStorage.getItem('email')
|
||||
|
||||
if (token) setToken(token)
|
||||
if (email) setEmail(email)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (token) {
|
||||
intervalRef.current = setInterval(() => {
|
||||
try {
|
||||
fetch(`/api/replit/progress?token=${token}`)
|
||||
.then(res => res.text())
|
||||
.then(data => {
|
||||
const split = data.split('/')
|
||||
setProgressText(split[0] / split[1])
|
||||
})
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
}
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalRef.current)
|
||||
}
|
||||
}, [token])
|
||||
|
||||
const handleSubmit = async event => {
|
||||
setSubmitStatus('submitting')
|
||||
event.preventDefault()
|
||||
const formData = new FormData(event.target)
|
||||
const data = {
|
||||
email: formData.get('email'),
|
||||
token: formData.get('token')
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/replit/signup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: new URLSearchParams(data).toString()
|
||||
})
|
||||
|
||||
const result = await response.text()
|
||||
setResponseText(result)
|
||||
|
||||
// Store the email and token in localStorage
|
||||
localStorage.setItem('token', data.token)
|
||||
localStorage.setItem('email', data.email)
|
||||
setSubmitStatus('success')
|
||||
} catch (error) {
|
||||
setSubmitStatus('error')
|
||||
setResponseText('Error submitting form')
|
||||
console.error('Error:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const steps = [
|
||||
'Enter your email',
|
||||
'Enter your replit token',
|
||||
|
|
|
|||
25
yarn.lock
25
yarn.lock
|
|
@ -1212,6 +1212,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f"
|
||||
integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==
|
||||
|
||||
"@fillout/react@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@fillout/react/-/react-1.1.2.tgz#833c28aa53aa79a712b61e915e3fc710312f02f9"
|
||||
integrity sha512-XyzLY74Zhxxwym3A9770Tb3NINwaaWyWwvaw1lMJ5sA/P6hgsdzvefUOqohzR3+KVyspvBOR4BoR0nBMPFd/Vw==
|
||||
|
||||
"@github/time-elements@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@github/time-elements/-/time-elements-4.0.0.tgz#ca6aec5e9fbc18348d3fc980610b79c244b1b81f"
|
||||
|
|
@ -8536,7 +8541,16 @@ string-hash@1.1.3:
|
|||
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
|
||||
integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
|
||||
"string-width-cjs@npm:string-width@^4.2.0":
|
||||
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==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^4.1.0:
|
||||
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==
|
||||
|
|
@ -8647,7 +8661,7 @@ stringify-entities@^4.0.0:
|
|||
character-entities-html4 "^2.0.0"
|
||||
character-entities-legacy "^3.0.0"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
|
|
@ -8661,6 +8675,13 @@ strip-ansi@6.0.0:
|
|||
dependencies:
|
||||
ansi-regex "^5.0.0"
|
||||
|
||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^7.0.1:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue