| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- import { z } from 'zod'
- import { Link } from 'react-router-dom'
- import { useFieldArray, useForm } from 'react-hook-form'
- import { Button } from '@/components/custom/button'
- import {
- Form,
- FormControl,
- FormDescription,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
- } from '@/components/ui/form'
- import { Input } from '@/components/ui/input'
- import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
- } from '@/components/ui/select'
- import { Textarea } from '@/components/ui/textarea'
- import { toast } from '@/components/ui/use-toast'
- import { cn } from '@/lib/utils'
- import { zodResolver } from '@hookform/resolvers/zod'
- const profileFormSchema = z.object({
- username: z
- .string()
- .min(2, {
- message: 'Username must be at least 2 characters.',
- })
- .max(30, {
- message: 'Username must not be longer than 30 characters.',
- }),
- email: z
- .string({
- required_error: 'Please select an email to display.',
- })
- .email(),
- bio: z.string().max(160).min(4),
- urls: z
- .array(
- z.object({
- value: z.string().url({ message: 'Please enter a valid URL.' }),
- })
- )
- .optional(),
- })
- type ProfileFormValues = z.infer<typeof profileFormSchema>
- // This can come from your database or API.
- const defaultValues: Partial<ProfileFormValues> = {
- bio: 'I own a computer.',
- urls: [
- { value: 'https://shadcn.com' },
- { value: 'http://twitter.com/shadcn' },
- ],
- }
- export default function ProfileForm() {
- const form = useForm<ProfileFormValues>({
- resolver: zodResolver(profileFormSchema),
- defaultValues,
- mode: 'onChange',
- })
- const { fields, append } = useFieldArray({
- name: 'urls',
- control: form.control,
- })
- function onSubmit(data: ProfileFormValues) {
- toast({
- title: 'You submitted the following values:',
- description: (
- <pre className='mt-2 w-[340px] rounded-md bg-slate-950 p-4'>
- <code className='text-white'>{JSON.stringify(data, null, 2)}</code>
- </pre>
- ),
- })
- }
- return (
- <Form {...form}>
- <form onSubmit={form.handleSubmit(onSubmit)} className='space-y-8'>
- <FormField
- control={form.control}
- name='username'
- render={({ field }) => (
- <FormItem>
- <FormLabel>Username</FormLabel>
- <FormControl>
- <Input placeholder='shadcn' {...field} />
- </FormControl>
- <FormDescription>
- This is your public display name. It can be your real name or a
- pseudonym. You can only change this once every 30 days.
- </FormDescription>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name='email'
- render={({ field }) => (
- <FormItem>
- <FormLabel>Email</FormLabel>
- <Select onValueChange={field.onChange} defaultValue={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder='Select a verified email to display' />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- <SelectItem value='m@example.com'>m@example.com</SelectItem>
- <SelectItem value='m@google.com'>m@google.com</SelectItem>
- <SelectItem value='m@support.com'>m@support.com</SelectItem>
- </SelectContent>
- </Select>
- <FormDescription>
- You can manage verified email addresses in your{' '}
- <Link to='/examples/forms'>email settings</Link>.
- </FormDescription>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name='bio'
- render={({ field }) => (
- <FormItem>
- <FormLabel>Bio</FormLabel>
- <FormControl>
- <Textarea
- placeholder='Tell us a little bit about yourself'
- className='resize-none'
- {...field}
- />
- </FormControl>
- <FormDescription>
- You can <span>@mention</span> other users and organizations to
- link to them.
- </FormDescription>
- <FormMessage />
- </FormItem>
- )}
- />
- <div>
- {fields.map((field, index) => (
- <FormField
- control={form.control}
- key={field.id}
- name={`urls.${index}.value`}
- render={({ field }) => (
- <FormItem>
- <FormLabel className={cn(index !== 0 && 'sr-only')}>
- URLs
- </FormLabel>
- <FormDescription className={cn(index !== 0 && 'sr-only')}>
- Add links to your website, blog, or social media profiles.
- </FormDescription>
- <FormControl>
- <Input {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- ))}
- <Button
- type='button'
- variant='outline'
- size='sm'
- className='mt-2'
- onClick={() => append({ value: '' })}
- >
- Add URL
- </Button>
- </div>
- <Button type='submit'>Update profile</Button>
- </form>
- </Form>
- )
- }
|