| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- import { HTMLAttributes, useState } from 'react'
- import { z } from 'zod'
- import { useForm } from 'react-hook-form'
- import { zodResolver } from '@hookform/resolvers/zod'
- import { Link } from '@tanstack/react-router'
- import { IconBrandFacebook, IconBrandGithub } from '@tabler/icons-react'
- import { cn } from '@/lib/utils'
- import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
- } from '@/components/ui/form'
- import { Input } from '@/components/ui/input'
- import { Button } from '@/components/button'
- import { PasswordInput } from '@/components/password-input'
- type UserAuthFormProps = 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',
- }),
- })
- export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
- const [isLoading, setIsLoading] = useState(false)
- const form = useForm<z.infer<typeof formSchema>>({
- resolver: zodResolver(formSchema),
- defaultValues: {
- email: '',
- password: '',
- },
- })
- function onSubmit(data: z.infer<typeof formSchema>) {
- setIsLoading(true)
- // eslint-disable-next-line no-console
- 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'>
- <div className='flex items-center justify-between'>
- <FormLabel>Password</FormLabel>
- <Link
- to='/forgot-password'
- className='text-sm font-medium text-muted-foreground hover:opacity-75'
- >
- Forgot password?
- </Link>
- </div>
- <FormControl>
- <PasswordInput placeholder='********' {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <Button className='mt-2' loading={isLoading}>
- Login
- </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'
- loading={isLoading}
- leftSection={<IconBrandGithub className='h-4 w-4' />}
- >
- GitHub
- </Button>
- <Button
- variant='outline'
- className='w-full'
- type='button'
- loading={isLoading}
- leftSection={<IconBrandFacebook className='h-4 w-4' />}
- >
- Facebook
- </Button>
- </div>
- </div>
- </form>
- </Form>
- </div>
- )
- }
|