Files
mylder-frontend/src/app/(auth)/signup/page.tsx
christiankrag 01739a50cd Switch from magic link to password-based authentication
- Update signup page with password and confirm password fields
- Update login page with password field
- Remove magic link/OTP flow entirely
- Auto-redirect to dashboard after successful auth

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 12:40:05 +01:00

147 lines
4.6 KiB
TypeScript

'use client'
import { useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { createClient } from '@/lib/supabase/client'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
import { Bot, Loader2 } from 'lucide-react'
export default function SignupPage() {
const router = useRouter()
const [email, setEmail] = useState('')
const [fullName, setFullName] = useState('')
const [password, setPassword] = useState('')
const [confirmPassword, setConfirmPassword] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const handleSignup = async (e: React.FormEvent) => {
e.preventDefault()
setError(null)
if (password !== confirmPassword) {
setError('Passwords do not match')
return
}
if (password.length < 6) {
setError('Password must be at least 6 characters')
return
}
setIsLoading(true)
const supabase = createClient()
const { error } = await supabase.auth.signUp({
email,
password,
options: {
data: {
full_name: fullName,
},
},
})
if (error) {
setError(error.message)
setIsLoading(false)
return
}
router.push('/dashboard')
}
return (
<div className="min-h-screen flex items-center justify-center bg-zinc-50 dark:bg-zinc-950 px-4">
<Card className="w-full max-w-md">
<CardHeader className="text-center">
<Link href="/" className="inline-flex items-center justify-center gap-2 mb-4">
<Bot className="h-8 w-8 text-primary" />
<span className="text-xl font-bold">Mylder</span>
</Link>
<CardTitle>Create your account</CardTitle>
<CardDescription>Start building with AI in minutes</CardDescription>
</CardHeader>
<form onSubmit={handleSignup}>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Full Name</Label>
<Input
id="name"
type="text"
placeholder="John Doe"
value={fullName}
onChange={(e) => setFullName(e.target.value)}
required
disabled={isLoading}
/>
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
disabled={isLoading}
/>
</div>
<div className="space-y-2">
<Label htmlFor="password">Password</Label>
<Input
id="password"
type="password"
placeholder="••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
disabled={isLoading}
/>
</div>
<div className="space-y-2">
<Label htmlFor="confirmPassword">Confirm Password</Label>
<Input
id="confirmPassword"
type="password"
placeholder="••••••••"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
disabled={isLoading}
/>
</div>
{error && (
<p className="text-sm text-red-500">{error}</p>
)}
</CardContent>
<CardFooter className="flex flex-col gap-4">
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Creating account...
</>
) : (
'Create Account'
)}
</Button>
<p className="text-sm text-center text-zinc-500">
Already have an account?{' '}
<Link href="/login" className="text-primary hover:underline">
Log in
</Link>
</p>
</CardFooter>
</form>
</Card>
</div>
)
}