ปรับ frontend/app/(protected)/layout.jsx
This commit is contained in:
@@ -1,16 +1,44 @@
|
|||||||
// frontend/app/(protected)/layout.jsx
|
// frontend/app/(protected)/layout.jsx
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { getSession } from "@/lib/auth";
|
import { cookies, headers } from "next/headers";
|
||||||
import { can } from "@/lib/rbac";
|
import { can } from "@/lib/rbac";
|
||||||
|
|
||||||
export const metadata = { title: "DMS | Protected" };
|
export const metadata = { title: "DMS | Protected" };
|
||||||
|
|
||||||
|
const API_BASE = (process.env.NEXT_PUBLIC_API_BASE || "").replace(/\/$/, "");
|
||||||
|
|
||||||
|
async function fetchSessionFromAPI() {
|
||||||
|
const cookieStore = await cookies(); // ✅ ต้อง await
|
||||||
|
const cookieHeader = cookieStore.toString();
|
||||||
|
const hdrs = await headers(); // ✅ ต้อง await
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default async function ProtectedLayout({ children }) {
|
export default async function ProtectedLayout({ children }) {
|
||||||
// ตรวจ session ฝั่งเซิร์ฟเวอร์ ด้วยคุกกี้จริง
|
const session = await fetchSessionFromAPI();
|
||||||
const session = await getSession();
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
redirect("/login");
|
redirect("/login?next=/dashboard");
|
||||||
}
|
}
|
||||||
const { user } = session;
|
const { user } = session;
|
||||||
|
|
||||||
@@ -23,73 +51,17 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav className="space-y-2">
|
<nav className="space-y-2">
|
||||||
<Link
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/dashboard">แดชบอร์ด</Link>
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/drawings">Drawings</Link>
|
||||||
href="/dashboard"
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/rfas">RFAs</Link>
|
||||||
>
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/transmittals">Transmittals</Link>
|
||||||
แดชบอร์ด
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/correspondences">Correspondences</Link>
|
||||||
</Link>
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/contracts-volumes">Contracts & Volumes</Link>
|
||||||
<Link
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/reports">Reports</Link>
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
|
||||||
href="/drawings"
|
|
||||||
>
|
|
||||||
Drawings
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
|
||||||
href="/rfas"
|
|
||||||
>
|
|
||||||
RFAs
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
|
||||||
href="/transmittals"
|
|
||||||
>
|
|
||||||
Transmittals
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
|
||||||
href="/correspondences"
|
|
||||||
>
|
|
||||||
Correspondences
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
|
||||||
href="/contracts-volumes"
|
|
||||||
>
|
|
||||||
Contracts & Volumes
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
|
||||||
href="/reports"
|
|
||||||
>
|
|
||||||
Reports
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{can(user, "workflow:view") && (
|
{can(user, "workflow:view") && <Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/workflow">Workflow (n8n)</Link>}
|
||||||
<Link
|
{can(user, "health:view") && <Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/health">Health</Link>}
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
{can(user, "users:manage") && <Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/users">ผู้ใช้/บทบาท</Link>}
|
||||||
href="/workflow"
|
|
||||||
>
|
|
||||||
Workflow (n8n)
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
{can(user, "health:view") && (
|
|
||||||
<Link
|
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
|
||||||
href="/health"
|
|
||||||
>
|
|
||||||
Health
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
{can(user, "users:manage") && (
|
|
||||||
<Link
|
|
||||||
className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white"
|
|
||||||
href="/users"
|
|
||||||
>
|
|
||||||
ผู้ใช้/บทบาท
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
@@ -98,81 +70,17 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
{/* System / Quick Actions */}
|
{/* System / Quick Actions */}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="flex-1 text-lg font-semibold">
|
<div className="flex-1 text-lg font-semibold">
|
||||||
Document Management System — LCP3 Phase 3
|
Document Management System — LCBP3 Phase 3
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{can(user, "admin:view") && (
|
{can(user, "admin:view") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/admin">Admin</a>}
|
||||||
<a
|
{can(user, "users:manage") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/users">ผู้ใช้/บทบาท</a>}
|
||||||
className="px-3 py-2 text-white rounded-xl"
|
{can(user, "health:view") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/health">Health</a>}
|
||||||
style={{ background: "#0D5C75" }}
|
{can(user, "workflow:view") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/workflow">Workflow</a>}
|
||||||
href="/admin"
|
{can(user, "rfa:create") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/rfas/new">+ RFA</a>}
|
||||||
>
|
{can(user, "drawing:upload") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/drawings/upload">+ Upload Drawing</a>}
|
||||||
Admin
|
{can(user, "transmittal:create") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/transmittals/new">+ Transmittal</a>}
|
||||||
</a>
|
{can(user, "correspondence:create") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/correspondences/new">+ หนังสือสื่อสาร</a>}
|
||||||
)}
|
|
||||||
{can(user, "users:manage") && (
|
|
||||||
<a
|
|
||||||
className="px-3 py-2 text-white rounded-xl"
|
|
||||||
style={{ background: "#0D5C75" }}
|
|
||||||
href="/users"
|
|
||||||
>
|
|
||||||
ผู้ใช้/บทบาท
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
{can(user, "health:view") && (
|
|
||||||
<a
|
|
||||||
className="px-3 py-2 text-white rounded-xl"
|
|
||||||
style={{ background: "#0D5C75" }}
|
|
||||||
href="/health"
|
|
||||||
>
|
|
||||||
Health
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
{can(user, "workflow:view") && (
|
|
||||||
<a
|
|
||||||
className="px-3 py-2 text-white rounded-xl"
|
|
||||||
style={{ background: "#0D5C75" }}
|
|
||||||
href="/workflow"
|
|
||||||
>
|
|
||||||
Workflow
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
{can(user, "rfa:create") && (
|
|
||||||
<a
|
|
||||||
className="px-3 py-2 text-white rounded-xl"
|
|
||||||
style={{ background: "#0D5C75" }}
|
|
||||||
href="/rfas/new"
|
|
||||||
>
|
|
||||||
+ RFA
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
{can(user, "drawing:upload") && (
|
|
||||||
<a
|
|
||||||
className="px-3 py-2 text-white rounded-xl"
|
|
||||||
style={{ background: "#0D5C75" }}
|
|
||||||
href="/drawings/upload"
|
|
||||||
>
|
|
||||||
+ Upload Drawing
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
{can(user, "transmittal:create") && (
|
|
||||||
<a
|
|
||||||
className="px-3 py-2 text-white rounded-xl"
|
|
||||||
style={{ background: "#0D5C75" }}
|
|
||||||
href="/transmittals/new"
|
|
||||||
>
|
|
||||||
+ Transmittal
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
{can(user, "correspondence:create") && (
|
|
||||||
<a
|
|
||||||
className="px-3 py-2 text-white rounded-xl"
|
|
||||||
style={{ background: "#0D5C75" }}
|
|
||||||
href="/correspondences/new"
|
|
||||||
>
|
|
||||||
+ หนังสือสื่อสาร
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
Reference in New Issue
Block a user