A very performant and light (2mb in memory) link shortener and tracker. Written in Rust and React and uses Postgres/SQLite.
1import { useState } from 'react' 2import { useForm } from 'react-hook-form' 3import { z } from 'zod' 4import { zodResolver } from '@hookform/resolvers/zod' 5import { useAuth } from '../context/AuthContext' 6import { Button } from '@/components/ui/button' 7import { Input } from '@/components/ui/input' 8import { Card } from '@/components/ui/card' 9import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' 10import { 11 Form, 12 FormControl, 13 FormField, 14 FormItem, 15 FormLabel, 16 FormMessage, 17} from '@/components/ui/form' 18import { useToast } from '@/hooks/use-toast' 19 20const formSchema = z.object({ 21 email: z.string().email('Invalid email address'), 22 password: z.string().min(6, 'Password must be at least 6 characters long'), 23}) 24 25type FormValues = z.infer<typeof formSchema> 26 27export function AuthForms() { 28 const [activeTab, setActiveTab] = useState<'login' | 'register'>('login') 29 const { login, register } = useAuth() 30 const { toast } = useToast() 31 32 const form = useForm<FormValues>({ 33 resolver: zodResolver(formSchema), 34 defaultValues: { 35 email: '', 36 password: '', 37 }, 38 }) 39 40 const onSubmit = async (values: FormValues) => { 41 try { 42 if (activeTab === 'login') { 43 await login(values.email, values.password) 44 } else { 45 await register(values.email, values.password) 46 } 47 form.reset() 48 } catch (err: any) { 49 toast({ 50 variant: 'destructive', 51 title: 'Error', 52 description: err.response?.data?.error || 'An error occurred', 53 }) 54 } 55 } 56 57 return ( 58 <Card className="w-full max-w-md mx-auto p-6"> 59 <Tabs value={activeTab} onValueChange={(value: string) => setActiveTab(value as 'login' | 'register')}> 60 <TabsList className="grid w-full grid-cols-2"> 61 <TabsTrigger value="login">Login</TabsTrigger> 62 <TabsTrigger value="register">Register</TabsTrigger> 63 </TabsList> 64 65 <TabsContent value={activeTab}> 66 <Form {...form}> 67 <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> 68 <FormField 69 control={form.control} 70 name="email" 71 render={({ field }) => ( 72 <FormItem> 73 <FormLabel>Email</FormLabel> 74 <FormControl> 75 <Input type="email" {...field} /> 76 </FormControl> 77 <FormMessage /> 78 </FormItem> 79 )} 80 /> 81 82 <FormField 83 control={form.control} 84 name="password" 85 render={({ field }) => ( 86 <FormItem> 87 <FormLabel>Password</FormLabel> 88 <FormControl> 89 <Input type="password" {...field} /> 90 </FormControl> 91 <FormMessage /> 92 </FormItem> 93 )} 94 /> 95 96 <Button type="submit" className="w-full"> 97 {activeTab === 'login' ? 'Sign in' : 'Create account'} 98 </Button> 99 </form> 100 </Form> 101 </TabsContent> 102 </Tabs> 103 </Card> 104 ) 105}