59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import { cn } from '@/lib/utils'
|
|
import { createClient } from '@/registry/default/clients/nextjs/lib/supabase/client'
|
|
import { Button } from '@/registry/default/components/ui/button'
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from '@/registry/default/components/ui/card'
|
|
import { useState } from 'react'
|
|
|
|
export function LoginForm({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
|
|
const [error, setError] = useState<string | null>(null)
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
|
|
const handleSocialLogin = async (e: React.FormEvent) => {
|
|
e.preventDefault()
|
|
const supabase = createClient()
|
|
setIsLoading(true)
|
|
setError(null)
|
|
|
|
try {
|
|
const { error } = await supabase.auth.signInWithOAuth({
|
|
provider: 'github',
|
|
})
|
|
|
|
if (error) throw error
|
|
location.href = '/protected'
|
|
} catch (error: unknown) {
|
|
setError(error instanceof Error ? error.message : 'An error occurred')
|
|
setIsLoading(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className={cn('flex flex-col gap-6', className)} {...props}>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-2xl">Welcome!</CardTitle>
|
|
<CardDescription>Sign in to your account to continue</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<form onSubmit={handleSocialLogin}>
|
|
<div className="flex flex-col gap-6">
|
|
{error && <p className="text-sm text-destructive-500">{error}</p>}
|
|
<Button type="submit" className="w-full" disabled={isLoading}>
|
|
{isLoading ? 'Logging in...' : 'Continue with GitHub'}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|