35 lines
1.7 KiB
TypeScript
35 lines
1.7 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { redirect } from "next/navigation";
|
|
|
|
import DotGrid from "@/components/DotGrid";
|
|
import LoginForm from "@/components/LoginForm";
|
|
import { getSessionUser } from "@/lib/session";
|
|
import { firstSearchParam, sanitizeNextPath } from "@/utils/external-file";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export const metadata: Metadata = { title: "เข้าสู่ระบบ | Judge's Note" };
|
|
|
|
export default function LoginPage({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Record<string, string | string[] | undefined>;
|
|
}) {
|
|
// N8 D5: path วนกลับหลัง login (middleware แนบมาตอน redirect เข้าหน้านี้) —
|
|
// ค่ามาจาก query ที่ใครก็แก้ได้ ต้อง sanitize กัน open-redirect ก่อนใช้เสมอ
|
|
const rawNext = firstSearchParam(searchParams.next);
|
|
const next = rawNext !== undefined ? sanitizeNextPath(rawNext) : null;
|
|
|
|
// เข้าสู่ระบบอยู่แล้ว (cookie ครบ) → ไม่ต้องเห็นฟอร์มอีก
|
|
const user = getSessionUser();
|
|
if (user) redirect(next ?? "/");
|
|
|
|
return (
|
|
// Genesis: กริดจุดอันตรกิริยา ( decorative element ชิ้นเดียวที่อนุญาต) เป็นพื้นหลัง
|
|
// หน้า login — DotGrid อยู่ก่อนการ์ดใน DOM จึงถูกทับโดยการ์ดเอง ไม่ต้องเล่น z-index
|
|
<main className="relative flex min-h-dvh items-center justify-center px-4 py-10">
|
|
<DotGrid />
|
|
<LoginForm next={next} />
|
|
</main>
|
|
);
|
|
}
|