aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/group-form.tsx
diff options
context:
space:
mode:
authorSebastien Castiel <sebastien@castiel.me>2023-12-05 17:39:05 -0500
committerSebastien Castiel <sebastien@castiel.me>2023-12-05 17:39:05 -0500
commited55c696cd083bfaa5429082a9c5edd4ebde0cd8 (patch)
tree9f387881f85716bcb4a05d6fce13bfe59fbc9c17 /src/components/group-form.tsx
parent1fd6e48807d455f66d9cd79db64cbf9e9f947c6c (diff)
First version
Diffstat (limited to 'src/components/group-form.tsx')
-rw-r--r--src/components/group-form.tsx136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/components/group-form.tsx b/src/components/group-form.tsx
new file mode 100644
index 0000000..0b6e560
--- /dev/null
+++ b/src/components/group-form.tsx
@@ -0,0 +1,136 @@
+'use client'
+import { Button } from '@/components/ui/button'
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from '@/components/ui/card'
+import {
+ Form,
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from '@/components/ui/form'
+import { Input } from '@/components/ui/input'
+import { getGroup } from '@/lib/api'
+import { GroupFormValues, groupFormSchema } from '@/lib/schemas'
+import { zodResolver } from '@hookform/resolvers/zod'
+import { useFieldArray, useForm } from 'react-hook-form'
+
+export type Props = {
+ group?: NonNullable<Awaited<ReturnType<typeof getGroup>>>
+ onSubmit: (groupFormValues: GroupFormValues) => void
+}
+
+export function GroupForm({ group, onSubmit }: Props) {
+ const form = useForm<GroupFormValues>({
+ resolver: zodResolver(groupFormSchema),
+ defaultValues: group
+ ? {
+ name: group.name,
+ participants: group.participants,
+ }
+ : {
+ name: '',
+ participants: [{ name: 'John' }, { name: 'Jane' }, { name: 'Jack' }],
+ },
+ })
+ const { fields, append, remove } = useFieldArray({
+ control: form.control,
+ name: 'participants',
+ })
+
+ return (
+ <Form {...form}>
+ <form
+ onSubmit={form.handleSubmit((values) => {
+ onSubmit(values)
+ })}
+ className="space-y-8"
+ >
+ <Card>
+ <CardHeader>
+ <CardTitle>Group information</CardTitle>
+ </CardHeader>
+ <CardContent>
+ <FormField
+ control={form.control}
+ name="name"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>Group name</FormLabel>
+ <FormControl>
+ <Input placeholder="Summer vacations" {...field} />
+ </FormControl>
+ <FormDescription>
+ Enter a name for your group.
+ </FormDescription>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </CardContent>
+ </Card>
+ <Card>
+ <CardHeader>
+ <CardTitle>Participants</CardTitle>
+ <CardDescription>
+ Enter the name for each participant
+ </CardDescription>
+ </CardHeader>
+ <CardContent>
+ <ul className="flex flex-col gap-4">
+ {fields.map((item, index) => (
+ <li key={item.id}>
+ <FormField
+ control={form.control}
+ name={`participants.${index}.name`}
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel className="sr-only">
+ Participant #{index + 1}
+ </FormLabel>
+ <FormControl>
+ <div className="flex gap-2">
+ <Input {...field} />
+ <Button
+ variant="destructive"
+ onClick={() => remove(index)}
+ type="button"
+ >
+ Remove
+ </Button>
+ </div>
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </li>
+ ))}
+ </ul>
+ </CardContent>
+ <CardFooter>
+ <Button
+ variant="secondary"
+ onClick={() => {
+ append({ name: 'New' })
+ }}
+ type="button"
+ >
+ Add participant
+ </Button>
+ </CardFooter>
+ </Card>
+
+ <Button type="submit">Submit</Button>
+ </form>
+ </Form>
+ )
+}