"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { LanguageSelect } from "@/components/LanguageSelect"; import { ThemeSelect } from "@/components/ThemeSelect"; import { User, Lock, Eye, EyeOff, ArrowRight } from "lucide-react"; export function LoginPage() { const router = useRouter(); const t = useTranslations('auth'); const tCommon = useTranslations('common'); const tValidation = useTranslations('validation'); const [userId, setUserId] = useState(""); const [password, setPassword] = useState(""); const [showPassword, setShowPassword] = useState(false); const [rememberMe, setRememberMe] = useState(false); const [error, setError] = useState(""); const handleLogin = async () => { setError(""); // Validation if (!userId || !password) { setError(tValidation('required')); return; } try { // ✅ HttpOnly Cookie 방식: Next.js API Route로 프록시 // 토큰은 JavaScript에서 접근 불가능한 HttpOnly 쿠키로 저장됨 const response = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ user_id: userId, user_pwd: password, }), }); const data = await response.json(); if (!response.ok) { throw { status: response.status, message: data.error || 'Login failed', }; } console.log('✅ 로그인 성공:', data.message); console.log('📦 사용자 정보:', data.user); console.log('🔐 토큰은 안전한 HttpOnly 쿠키에 저장됨 (JavaScript 접근 불가)'); // 대시보드로 이동 router.push("/dashboard"); } catch (err) { console.error('❌ 로그인 실패:', err); const error = err as { status?: number; message?: string }; if (error.status === 401 || error.status === 422) { setError(t('invalidCredentials')); } else if (error.status === 429) { setError('Too many login attempts. Please try again later.'); } else if (error.status && error.status >= 500) { setError('Service temporarily unavailable. Please try again later.'); } else { setError(error.message || t('invalidCredentials')); } } }; return (
{/* Header */}
{/* Main Content */}
{/* Login Card */}

{t('login')}

{tCommon('welcome')} SAM MES

{error && (

{error}

)}
{ e.preventDefault(); handleLogin(); }} className="space-y-4">
setUserId(e.target.value)} className="clean-input" />
setPassword(e.target.value)} className="clean-input pr-10" />
{tCommon('or')}
{/* Signup Link */}

{t('noAccount')}{" "}

); }