dramaling-vocab-learning/frontend/app/login/page.tsx

155 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import { useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { useAuth } from '@/contexts/AuthContext'
export default function LoginPage() {
const router = useRouter()
const { login } = useAuth()
const [email, setEmail] = useState(
process.env.NODE_ENV === 'development' ? 'john@mail.com' : ''
)
const [password, setPassword] = useState(
process.env.NODE_ENV === 'development' ? '1qaz@WSX' : ''
)
const [rememberMe, setRememberMe] = useState(false)
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setLoading(true)
setError('')
const result = await login(email, password)
if (result.success) {
router.push('/dashboard')
} else {
setError(result.error || '登入失敗')
}
setLoading(false)
}
const handleGoogleLogin = () => {
// Mock Google login
setLoading(true)
setTimeout(() => {
router.push('/dashboard')
}, 1000)
}
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center px-4">
<div className="max-w-md w-full bg-white rounded-2xl shadow-xl p-8">
<div className="text-center mb-8">
<h1 className="text-3xl font-bold text-gray-900"></h1>
<p className="text-gray-600 mt-2"> DramaLing </p>
{process.env.NODE_ENV === 'development' && (
<div className="mt-4 p-2 bg-yellow-100 border border-yellow-300 rounded-lg">
<p className="text-yellow-800 text-xs">
🚧 -
</p>
</div>
)}
</div>
<form onSubmit={handleSubmit} className="space-y-6">
{error && (
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
<p className="text-red-600 text-sm">{error}</p>
</div>
)}
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-2">
Email
</label>
<input
id="email"
type="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent outline-none transition"
placeholder="your@email.com"
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-gray-700 mb-2">
</label>
<input
id="password"
type="password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent outline-none transition"
placeholder="••••••••"
/>
</div>
<div className="flex items-center justify-between">
<label className="flex items-center">
<input
type="checkbox"
checked={rememberMe}
onChange={(e) => setRememberMe(e.target.checked)}
className="h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded"
/>
<span className="ml-2 text-sm text-gray-600"></span>
</label>
<Link href="/forgot-password" className="text-sm text-primary hover:text-primary-hover">
</Link>
</div>
<button
type="submit"
disabled={loading}
className="w-full bg-primary text-white py-3 rounded-lg font-semibold hover:bg-primary-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
{loading ? '登入中...' : '登入'}
</button>
</form>
<div className="mt-6">
<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300"></div>
</div>
<div className="relative flex justify-center text-sm">
<span className="px-2 bg-white text-gray-500"></span>
</div>
</div>
<button
onClick={handleGoogleLogin}
disabled={loading}
className="mt-4 w-full flex items-center justify-center px-4 py-3 border border-gray-300 rounded-lg shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
<svg className="w-5 h-5 mr-2" viewBox="0 0 24 24">
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
<path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
<path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
<path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
</svg>
使 Google
</button>
</div>
<p className="mt-8 text-center text-sm text-gray-600">
{' '}
<Link href="/register" className="font-medium text-primary hover:text-primary-hover">
</Link>
</p>
</div>
</div>
)
}