fantus/screens/form.tsx

142 lines
3.8 KiB
TypeScript
Raw Normal View History

2021-01-02 00:21:29 +01:00
import React, { useState, useCallback } from 'react'
2020-01-12 18:34:51 +01:00
import { useForm } from 'formhero'
const initial = {
2021-01-02 00:21:29 +01:00
contact: '',
description: '',
2020-01-12 18:34:51 +01:00
}
const Form: React.FC = () => {
2021-01-02 00:21:29 +01:00
const [loading, setLoading] = useState(false)
const [message, setMessage] = useState({
title: '',
error: false,
})
const { field, form, setForm } = useForm(initial)
const [files, setFiles] = useState([] as File[])
const _onFileChange = useCallback(
async (e: React.ChangeEvent<HTMLInputElement>) => {
setMessage({ title: '', error: false })
const uploaded = Array.from(e.target.files || [])
const nonAudio = uploaded.find((file) => !/^audio\//.test(file.type))
if (nonAudio) {
setMessage({
title: `Error: ${nonAudio.name} You can only select audio files.`,
error: true,
})
return
}
2020-01-12 18:34:51 +01:00
2021-01-02 00:21:29 +01:00
setFiles([...files, ...uploaded])
},
[files]
)
2020-01-12 18:34:51 +01:00
2021-01-02 00:21:29 +01:00
const _clear = useCallback(() => {
setFiles([])
}, [])
2020-01-12 18:34:51 +01:00
2021-01-02 00:21:29 +01:00
const _submit = useCallback(
(e: React.FormEvent) => {
e.preventDefault()
2020-01-12 18:34:51 +01:00
2021-01-02 00:21:29 +01:00
if (loading) return
2020-01-12 18:34:51 +01:00
2021-01-02 00:21:29 +01:00
// @ts-ignore
window.grecaptcha.ready(() => {
2020-01-12 18:34:51 +01:00
// @ts-ignore
2021-01-02 00:21:29 +01:00
window.grecaptcha
.execute(process.env.NEXT_PUBLIC_RECAPTCHA_CLIENT, { action: 'homepage' })
.then(function (token: string) {
setLoading(true)
setMessage({ title: '', error: false })
const body = new FormData()
body.append(
'json',
JSON.stringify({
...form,
token,
})
)
for (const file of files) {
body.append(file.name, file)
}
fetch('/api/form', {
method: 'POST',
body,
2020-01-12 18:34:51 +01:00
})
2021-01-02 00:21:29 +01:00
.then(() => {
setForm(initial)
setFiles([])
setMessage({ title: 'Uploaded 🚀', error: false })
})
.catch(() => setMessage({ title: 'Something went wrong 😥', error: true }))
.finally(() => setLoading(false))
})
})
},
[form, files, loading]
)
return (
<form onSubmit={_submit}>
<div className="body">
<h3 className="ma0 mb3">submit track</h3>
<label className="text">
<small>contact email</small>
<input type="email" disabled={loading} placeholder={'me@example.org'} {...field('contact')} />
</label>
<br />
<label className="text">
<small>description</small>
<textarea
rows={2}
placeholder="reference trakcs, comments, ..."
disabled={loading}
{...field('description')}
/>
</label>
<br />
<label className="file">
<input type="file" multiple disabled={loading} onChange={_onFileChange} />
upload tracks [max. 300MiB]
</label>
{files.length > 0 && (
<div>
<input onClick={_clear} type="button" value="clear all" />
<ul>
{files.map((file, i) => (
<li key={i}>{file.name}</li>
))}
</ul>
</div>
)}
<br />
<input type="submit" value={loading ? 'uploading...' : 'submit'} disabled={loading} />
{!!message.title && (
<div>
<br />
<div className={`pa2 ba br1 ${message.error ? 'b--red' : 'b--light-blue'}`}>{message.title}</div>
</div>
)}
</div>
<div className="grc">
This site is protected by reCAPTCHA and the Google&nbsp;
<a href="https://policies.google.com/privacy">Privacy Policy</a> and&nbsp;
<a href="https://policies.google.com/terms">Terms of Service</a> apply.
</div>
</form>
)
2020-01-12 18:34:51 +01:00
}
2021-01-02 00:21:29 +01:00
export default Form