115 lines
3.5 KiB
JavaScript
Executable File
115 lines
3.5 KiB
JavaScript
Executable File
// frontend/app/layout.jsx
|
|
import "./globals.css";
|
|
import Link from "next/link";
|
|
import { redirect } from "next/navigation";
|
|
import { cookies, headers } from "next/headers";
|
|
|
|
export const metadata = {
|
|
title: "DMS",
|
|
description: "Document Management System — LCBP3 Phase 3",
|
|
};
|
|
|
|
const API_BASE = (process.env.NEXT_PUBLIC_API_BASE || "").replace(/\/$/, "");
|
|
|
|
/** ดึงสถานะผู้ใช้แบบ global (ไม่บังคับล็อกอิน) */
|
|
async function fetchGlobalSession() {
|
|
const cookieStore = await cookies();
|
|
const cookieHeader = cookieStore.toString();
|
|
|
|
const hdrs = await headers();
|
|
const hostHdr = hdrs.get("host");
|
|
const protoHdr = hdrs.get("x-forwarded-proto") || "https";
|
|
|
|
const res = await fetch(`${API_BASE}/api/auth/me`, {
|
|
method: "GET",
|
|
headers: {
|
|
Cookie: cookieHeader,
|
|
"X-Forwarded-Host": hostHdr || "",
|
|
"X-Forwarded-Proto": protoHdr,
|
|
Accept: "application/json",
|
|
},
|
|
cache: "no-store",
|
|
});
|
|
|
|
if (!res.ok) return null;
|
|
try {
|
|
const data = await res.json();
|
|
return data?.ok ? data : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** ปุ่ม Logout แบบ Server Action (ไม่ต้องมี client component) */
|
|
async function LogoutAction() {
|
|
"use server";
|
|
const cookieStore = await cookies();
|
|
const cookieHeader = cookieStore.toString();
|
|
|
|
const hdrs = await headers();
|
|
const hostHdr = hdrs.get("host");
|
|
const protoHdr = hdrs.get("x-forwarded-proto") || "https";
|
|
|
|
// เรียก backend ให้ลบคุกกี้ออก (HttpOnly cookies)
|
|
await fetch(`${API_BASE}/api/auth/logout`, {
|
|
method: "POST",
|
|
headers: {
|
|
Cookie: cookieHeader,
|
|
"X-Forwarded-Host": hostHdr || "",
|
|
"X-Forwarded-Proto": protoHdr,
|
|
Accept: "application/json",
|
|
},
|
|
cache: "no-store",
|
|
});
|
|
|
|
// กลับไปหน้า login พร้อม next ไป dashboard
|
|
redirect("/login?next=/dashboard");
|
|
}
|
|
|
|
export default async function RootLayout({ children }) {
|
|
const session = await fetchGlobalSession();
|
|
const loggedIn = !!session?.user;
|
|
|
|
return (
|
|
<html lang="th">
|
|
<body className="bg-slate-50">
|
|
{/* Header รวมทุกหน้า */}
|
|
<header className="flex items-center justify-between w-full px-4 py-3 text-white bg-sky-900">
|
|
<h1 className="font-bold">Document Management System</h1>
|
|
|
|
<div className="flex items-center gap-3">
|
|
{loggedIn ? (
|
|
<div className="text-sm">
|
|
สวัสดี, <b>{session.user.username}</b> ({session.user.role})
|
|
</div>
|
|
) : (
|
|
<div className="text-sm">ยังไม่ได้เข้าสู่ระบบ</div>
|
|
)}
|
|
|
|
{/* ปุ่ม Login/Logout */}
|
|
{loggedIn ? (
|
|
<form action={LogoutAction}>
|
|
<button
|
|
type="submit"
|
|
className="px-3 py-1.5 rounded-lg bg-white/10 hover:bg-white/20"
|
|
>
|
|
ออกจากระบบ
|
|
</button>
|
|
</form>
|
|
) : (
|
|
<Link
|
|
href="/login?next=/dashboard"
|
|
className="px-3 py-1.5 rounded-lg bg-white/10 hover:bg-white/20"
|
|
>
|
|
เข้าสู่ระบบ
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</header>
|
|
|
|
<main>{children}</main>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|