-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathsubmit-resource-form.tsx
107 lines (98 loc) · 2.9 KB
/
submit-resource-form.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { Dispatch, SetStateAction, useState } from 'react'
import { extractDomain } from '@/utils'
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { isDomainInvalid } from '@/utils/isDomainInvalid'
import { submitResource } from '@/services/request'
import { Button } from '@/components/ui/button'
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
const formSchema = z.object({
url: z.string().url({
message: 'Invalid URL.'
})
})
export function SubmitResourceForm({ setOpen }: { setOpen: Dispatch<SetStateAction<boolean>> }) {
const [successMessage, setSuccessMessage] = useState<string>('')
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
url: ''
}
})
const {
formState: { isSubmitting, errors },
setError
} = form
const hasErrors = Object.keys(errors).length > 0
const onSubmit = async (values: z.infer<typeof formSchema>) => {
const domain = extractDomain(values.url)
if (isDomainInvalid({ url: domain })) {
setError('url', {
type: 'manual',
message: 'Invalid URL.'
})
return
}
try {
const formData = new FormData()
formData.append('url', values.url)
const { msg } = await submitResource({ formData })
if (msg !== 'ok') {
setError('url', {
type: 'manual',
message: 'This resource has already been submitted or added.'
})
return
}
setSuccessMessage('Thank you for submitting your resource!')
setTimeout(() => {
setOpen(false)
}, 2000)
} catch (error) {
if (error instanceof Error) {
setError('root.api', { type: 'manual', message: error.message })
}
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className='space-y-4'>
<FormField
control={form.control}
name='url'
render={({ field }) => (
<FormItem>
<FormLabel>Website URL</FormLabel>
<FormControl>
<Input placeholder='https://example.com' {...field} autoComplete='off' />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{hasErrors && <p className='text-red-500 text-sm'>{errors?.root?.api?.message}</p>}
{successMessage && (
<p className='text-light-900 dark:text-green-500 text-sm font-semibold'>
{successMessage}
</p>
)}
<Button
type='submit'
className='w-full'
disabled={isSubmitting || Boolean(errors?.root?.api)}
>
{!isSubmitting || hasErrors ? 'Submit' : 'Submitting...'}
</Button>
</form>
</Form>
)
}