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}