← back to Letsbegin
app/login/page.tsx
147 lines
'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
export default function LoginPage() {
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [showPassword, setShowPassword] = useState(false)
const [error, setError] = useState('')
const [isLoading, setIsLoading] = useState(false)
const router = useRouter()
async function handleSubmit(e: React.FormEvent) {
e.preventDefault()
setError('')
setIsLoading(true)
try {
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
})
const data = await res.json()
if (res.ok && data.success) {
router.push('/')
router.refresh()
} else {
setError(data.error || 'Login failed')
}
} catch (err) {
setError('Connection error. Please try again.')
console.error('Login error:', err)
} finally {
setIsLoading(false)
}
}
return (
<div className="min-h-screen bg-[var(--background)] flex items-center justify-center p-4">
<div className="w-full max-w-md">
{/* Logo/Title */}
<div className="text-center mb-8">
<div className="text-5xl mb-4">🚀</div>
<h1 className="text-3xl font-bold bg-gradient-to-r from-[var(--primary)] to-[var(--secondary)] bg-clip-text text-transparent">
Good Question Ralph
</h1>
<p className="text-[var(--foreground-secondary)] mt-2">
PRD to Code Automation
</p>
</div>
{/* Login Card */}
<div className="card p-6">
<h2 className="text-xl font-semibold mb-6 text-center">Admin Login</h2>
<form onSubmit={handleSubmit} className="space-y-4">
{error && (
<div className="p-3 rounded-lg bg-red-500/10 border border-red-500/30 text-red-400 text-sm">
{error}
</div>
)}
<div>
<label className="block text-sm font-medium mb-2">Username</label>
<input
type="text"
className="input"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Enter username"
required
autoFocus
disabled={isLoading}
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">Password</label>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
className="input pr-12"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter password"
required
disabled={isLoading}
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-[var(--foreground-secondary)] hover:text-[var(--foreground)] transition-colors"
tabIndex={-1}
>
{showPassword ? '🙈' : '👁️'}
</button>
</div>
</div>
<button
type="submit"
className="btn-primary w-full py-3"
disabled={isLoading}
>
{isLoading ? (
<>
<svg className="w-4 h-4 animate-spin mr-2 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
Logging in...
</>
) : (
'🔐 Login'
)}
</button>
</form>
<div className="mt-6 pt-6 border-t border-[var(--border)]">
<div className="text-xs text-[var(--foreground-tertiary)] text-center space-y-1">
<p>Protected by DW-Agents Authentication</p>
<p>Server: 45.61.58.125</p>
</div>
</div>
</div>
{/* Security Info */}
<div className="mt-6 text-center text-xs text-[var(--foreground-tertiary)]">
<div className="flex items-center justify-center gap-4">
<span className="flex items-center gap-1">
<span className="text-[var(--success)]">●</span>
Encrypted Session
</span>
<span className="flex items-center gap-1">
<span className="text-[var(--success)]">●</span>
IP Whitelisting
</span>
</div>
</div>
</div>
</div>
)
}