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}