// File: frontend/app/(auth)/login/page.jsx "use client"; import { useState, useMemo, Suspense } from "react"; import { useSearchParams, useRouter } from "next/navigation"; import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, } from "@/components/ui/card"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Alert, AlertDescription } from "@/components/ui/alert"; const API_BASE = (process.env.NEXT_PUBLIC_API_BASE || "").replace(/\/$/, ""); const DEBUG = String(process.env.NEXT_PUBLIC_DEBUG_AUTH || "").trim() !== "" && process.env.NEXT_PUBLIC_DEBUG_AUTH !== "0" && process.env.NEXT_PUBLIC_DEBUG_AUTH !== "false"; function dlog(...args) { if (DEBUG && typeof window !== "undefined") console.debug("[login]", ...args); } function LoginForm() { const router = useRouter(); const searchParams = useSearchParams(); const nextPath = useMemo(() => searchParams.get("next") || "/dashboard", [searchParams]); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [showPw, setShowPw] = useState(false); const [submitting, setSubmitting] = useState(false); const [err, setErr] = useState(""); async function onSubmit(e) { e.preventDefault(); setErr(""); if (!username.trim() || !password) { setErr("กรอกชื่อผู้ใช้และรหัสผ่านให้ครบ"); return; } try { setSubmitting(true); dlog("API_BASE =", API_BASE || "(empty → relative path)"); dlog("nextPath =", nextPath); const res = await fetch(`${API_BASE}/api/auth/login`, { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", // << ใช้คุกกี้ cache: "no-store", body: JSON.stringify({ username, password }), }); dlog("status =", res.status, "ctype =", res.headers.get("content-type")); let data = {}; try { data = await res.json(); } catch {} if (!res.ok) { const msg = data?.error === "INVALID_CREDENTIALS" ? "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง" : data?.error || `เข้าสู่ระบบไม่สำเร็จ (HTTP ${res.status})`; setErr(msg); return; } // ✅ ยืนยันว่าเซสชันพร้อมใช้งานก่อน (กัน redirect วน) // ✅ รอ session ให้พร้อมจริง (retry สูงสุด ~1.5s) let me = null, ok = false; for (let i = 0; i < 5; i++) { me = await fetch(`${API_BASE}/api/auth/me`, { method: "GET", credentials: "include", cache: "no-store", }).then(r => r.ok ? r.json() : null).catch(() => null); if (me?.ok) { ok = true; break; } await new Promise(r => setTimeout(r, 300)); // เว้นระยะ 300ms } if (!ok) { setErr("ล็อกอินสำเร็จ แต่ยังไม่เห็นเซสชันจากเซิร์ฟเวอร์ (ลองใหม่หรือตรวจคุกกี้)"); return; } // ✅ ใช้ hard navigation ให้ SSR เห็นคุกกี้แน่นอน if (typeof window !== "undefined") { window.location.href = nextPath || "/dashboard"; } else { router.replace(nextPath || "/dashboard"); } } catch (e) { dlog("exception =", e); setErr("เชื่อมต่อเซิร์ฟเวอร์ไม่ได้ กรุณาลองใหม่"); } finally { setSubmitting(false); } } return (