| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import { HTMLAttributes, useState } from 'react'
- import { cn } from '@/lib/utils'
- import { zodResolver } from '@hookform/resolvers/zod'
- import { useForm } from 'react-hook-form'
- import { z } from 'zod'
- import { Button } from '@/components/ui/button'
- import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
- } from '@/components/ui/form'
- import { Input } from '@/components/ui/input'
- import {
- IconBrandFacebook,
- IconBrandGithub,
- IconLoader2,
- } from '@tabler/icons-react'
- import { PasswordInput } from '@/components/password-input'
- interface SignUpFormProps extends HTMLAttributes<HTMLDivElement> {}
- const formSchema = z
- .object({
- email: z
- .string()
- .min(1, { message: 'Please enter your email' })
- .email({ message: 'Invalid email address' }),
- password: z
- .string()
- .min(1, {
- message: 'Please enter your password',
- })
- .min(7, {
- message: 'Password must be at least 7 characters long',
- }),
- confirmPassword: z.string(),
- })
- .refine((data) => data.password === data.confirmPassword, {
- message: "Passwords don't match.",
- path: ['confirmPassword'],
- })
- export function SignUpForm({ className, ...props }: SignUpFormProps) {
- const [isLoading, setIsLoading] = useState(false)
- const form = useForm<z.infer<typeof formSchema>>({
- resolver: zodResolver(formSchema),
- defaultValues: {
- email: '',
- password: '',
- confirmPassword: '',
- },
- })
- function onSubmit(data: z.infer<typeof formSchema>) {
- setIsLoading(true)
- console.log(data)
- setTimeout(() => {
- setIsLoading(false)
- }, 3000)
- }
- return (
- <div className={cn('grid gap-6', className)} {...props}>
- <Form {...form}>
- <form onSubmit={form.handleSubmit(onSubmit)}>
- <div className='grid gap-2'>
- <FormField
- control={form.control}
- name='email'
- render={({ field }) => (
- <FormItem className='space-y-1'>
- <FormLabel>Email</FormLabel>
- <FormControl>
- <Input placeholder='name@example.com' {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name='password'
- render={({ field }) => (
- <FormItem className='space-y-1'>
- <FormLabel>Password</FormLabel>
- <FormControl>
- <PasswordInput placeholder='********' {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name='confirmPassword'
- render={({ field }) => (
- <FormItem className='space-y-1'>
- <FormLabel>Confirm Password</FormLabel>
- <FormControl>
- <PasswordInput placeholder='********' {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <Button className='mt-2' disabled={isLoading}>
- {isLoading && (
- <IconLoader2 className='mr-2 h-4 w-4 animate-spin' />
- )}
- Create Account
- </Button>
- <div className='relative my-2'>
- <div className='absolute inset-0 flex items-center'>
- <span className='w-full border-t' />
- </div>
- <div className='relative flex justify-center text-xs uppercase'>
- <span className='bg-background px-2 text-muted-foreground'>
- Or continue with
- </span>
- </div>
- </div>
- <div className='flex items-center gap-2'>
- <Button
- variant='outline'
- className='w-full'
- type='button'
- disabled={isLoading}
- >
- {isLoading ? (
- <IconLoader2 className='mr-2 h-4 w-4 animate-spin' />
- ) : (
- <IconBrandGithub className='mr-2 h-4 w-4' />
- )}{' '}
- GitHub
- </Button>
- <Button
- variant='outline'
- className='w-full'
- type='button'
- disabled={isLoading}
- >
- {isLoading ? (
- <IconLoader2 className='mr-2 h-4 w-4 animate-spin' />
- ) : (
- <IconBrandFacebook className='mr-2 h-4 w-4' />
- )}{' '}
- Facebook
- </Button>
- </div>
- </div>
- </form>
- </Form>
- </div>
- )
- }
|