diff options
Diffstat (limited to 'src/components/group-form.tsx')
| -rw-r--r-- | src/components/group-form.tsx | 136 |
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> + ) +} |
