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 adminToken: z.string(), 24}) 25 26type FormValues = z.infer<typeof formSchema> 27 28export function AuthForms() { 29 const [activeTab, setActiveTab] = useState<'login' | 'register'>('login') 30 const { login, register } = useAuth() 31 const { toast } = useToast() 32 33 const form = useForm<FormValues>({ 34 resolver: zodResolver(formSchema), 35 defaultValues: { 36 email: '', 37 password: '', 38 adminToken: '', 39 }, 40 }) 41 42 const onSubmit = async (values: FormValues) => { 43 try { 44 if (activeTab === 'login') { 45 await login(values.email, values.password) 46 } else { 47 await register(values.email, values.password, values.adminToken) 48 } 49 form.reset() 50 } catch (err: any) { 51 toast({ 52 variant: 'destructive', 53 title: 'Error', 54 description: err.response?.data || 'An error occurred', 55 }) 56 } 57 } 58 59 return ( 60 <Card className="w-full max-w-md mx-auto p-6"> 61 <Tabs value={activeTab} onValueChange={(value: string) => setActiveTab(value as 'login' | 'register')}> 62 <TabsList className="grid w-full grid-cols-2"> 63 <TabsTrigger value="login">Login</TabsTrigger> 64 <TabsTrigger value="register">Register</TabsTrigger> 65 </TabsList> 66 67 <TabsContent value={activeTab}> 68 <Form {...form}> 69 <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> 70 <FormField 71 control={form.control} 72 name="email" 73 render={({ field }) => ( 74 <FormItem> 75 <FormLabel>Email</FormLabel> 76 <FormControl> 77 <Input type="email" {...field} /> 78 </FormControl> 79 <FormMessage /> 80 </FormItem> 81 )} 82 /> 83 84 <FormField 85 control={form.control} 86 name="password" 87 render={({ field }) => ( 88 <FormItem> 89 <FormLabel>Password</FormLabel> 90 <FormControl> 91 <Input type="password" {...field} /> 92 </FormControl> 93 <FormMessage /> 94 </FormItem> 95 )} 96 /> 97 98 {activeTab === 'register' && ( 99 <FormField 100 control={form.control} 101 name="adminToken" 102 render={({ field }) => ( 103 <FormItem> 104 <FormLabel>Admin Setup Token</FormLabel> 105 <FormControl> 106 <Input type="text" {...field} /> 107 </FormControl> 108 <FormMessage /> 109 </FormItem> 110 )} 111 /> 112 )} 113 114 <Button type="submit" className="w-full"> 115 {activeTab === 'login' ? 'Sign in' : 'Create account'} 116 </Button> 117 </form> 118 </Form> 119 </TabsContent> 120 </Tabs> 121 </Card> 122 ) 123}