layout errer
This commit is contained in:
@@ -9,9 +9,10 @@ export const metadata = { title: "DMS | Protected" };
|
|||||||
const API_BASE = (process.env.NEXT_PUBLIC_API_BASE || "").replace(/\/$/, "");
|
const API_BASE = (process.env.NEXT_PUBLIC_API_BASE || "").replace(/\/$/, "");
|
||||||
|
|
||||||
async function fetchSessionFromAPI() {
|
async function fetchSessionFromAPI() {
|
||||||
const cookieStore = await cookies(); // ✅ ต้อง await
|
const cookieStore = await cookies(); // ✅ ต้อง await
|
||||||
const cookieHeader = cookieStore.toString();
|
const cookieHeader = cookieStore.toString();
|
||||||
const hdrs = await headers(); // ✅ ต้อง await
|
|
||||||
|
const hdrs = await headers(); // ✅ ต้อง await
|
||||||
const hostHdr = hdrs.get("host");
|
const hostHdr = hdrs.get("host");
|
||||||
const protoHdr = hdrs.get("x-forwarded-proto") || "https";
|
const protoHdr = hdrs.get("x-forwarded-proto") || "https";
|
||||||
|
|
||||||
@@ -46,10 +47,7 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
<section className="grid grid-cols-12 gap-6 p-4 mx-auto max-w-7xl">
|
<section className="grid grid-cols-12 gap-6 p-4 mx-auto max-w-7xl">
|
||||||
<aside className="col-span-12 lg:col-span-3 xl:col-span-3">
|
<aside className="col-span-12 lg:col-span-3 xl:col-span-3">
|
||||||
<div className="p-4 border rounded-3xl bg-white/70">
|
<div className="p-4 border rounded-3xl bg-white/70">
|
||||||
<div className="mb-3 text-sm">
|
<div className="mb-3 text-sm">RBAC: <b>{user.role}</b></div>
|
||||||
RBAC: <b>{user.role}</b>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav className="space-y-2">
|
<nav className="space-y-2">
|
||||||
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/dashboard">แดชบอร์ด</Link>
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/dashboard">แดชบอร์ด</Link>
|
||||||
<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="/drawings">Drawings</Link>
|
||||||
@@ -58,7 +56,6 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
<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="/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="/contracts-volumes">Contracts & Volumes</Link>
|
||||||
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/reports">Reports</Link>
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/reports">Reports</Link>
|
||||||
|
|
||||||
{can(user, "workflow:view") && <Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/workflow">Workflow (n8n)</Link>}
|
{can(user, "workflow:view") && <Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" 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, "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>}
|
{can(user, "users:manage") && <Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/users">ผู้ใช้/บทบาท</Link>}
|
||||||
@@ -67,12 +64,8 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main className="col-span-12 space-y-6 lg:col-span-9 xl:col-span-9">
|
<main className="col-span-12 space-y-6 lg:col-span-9 xl:col-span-9">
|
||||||
{/* 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 — LCBP3 Phase 3</div>
|
||||||
Document Management System — LCBP3 Phase 3
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{can(user, "admin:view") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/admin">Admin</a>}
|
{can(user, "admin:view") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/admin">Admin</a>}
|
||||||
{can(user, "users:manage") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/users">ผู้ใช้/บทบาท</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, "health:view") && <a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/health">Health</a>}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// File: frontend/app/(protected)/layout.jsx
|
// File: frontend/app/layout.jsx
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { cookies, headers } from "next/headers";
|
import { cookies, headers } from "next/headers";
|
||||||
// ถ้ามี lib rbac เดิมอยู่ให้ใช้ต่อได้
|
// ถ้ามี lib rbac เดิมà¸à¸¢à¸¹à¹ˆà¹ƒà¸«à¹‰à¹ƒà¸Šà¹‰à¸•่à¸à¹„ด้
|
||||||
import { can } from "@/lib/rbac";
|
import { can } from "@/lib/rbac";
|
||||||
|
|
||||||
// แก้ title ให้ถูกสะกด
|
// à¹à¸à¹‰ title ให้ถูà¸à¸ªà¸°à¸à¸”
|
||||||
export const metadata = { title: "DMS | Protected" };
|
export const metadata = { title: "DMS | Protected" };
|
||||||
|
|
||||||
const API_BASE = (process.env.NEXT_PUBLIC_API_BASE || "").replace(/\/$/, "");
|
const API_BASE = (process.env.NEXT_PUBLIC_API_BASE || "").replace(/\/$/, "");
|
||||||
|
|
||||||
async function fetchSessionFromAPI() {
|
async function fetchSessionFromAPI() {
|
||||||
// ดึงคุกกี้จริงจากฝั่งเซิร์ฟเวอร์ แล้วส่งต่อให้ backend
|
// ดึงคุà¸à¸à¸µà¹‰à¸ˆà¸£à¸´à¸‡à¸ˆà¸²à¸à¸à¸±à¹ˆà¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ à¹à¸¥à¹‰à¸§à¸ªà¹ˆà¸‡à¸•่à¸à¹ƒà¸«à¹‰ backend
|
||||||
const cookieHeader = cookies().toString(); // serialize ทั้งชุด
|
const cookieHeader = cookies().toString(); // serialize ทั้งชุด
|
||||||
const hostHdr = headers().get("host");
|
const hostHdr = headers().get("host");
|
||||||
const protoHdr = headers().get("x-forwarded-proto") || "https";
|
const protoHdr = headers().get("x-forwarded-proto") || "https";
|
||||||
|
|
||||||
@@ -20,12 +20,12 @@ async function fetchSessionFromAPI() {
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
Cookie: cookieHeader,
|
Cookie: cookieHeader,
|
||||||
// เผื่อ backend ตรวจ origin/proto/host
|
// เผื่ภbackend ตรวจ origin/proto/host
|
||||||
"X-Forwarded-Host": hostHdr || "",
|
"X-Forwarded-Host": hostHdr || "",
|
||||||
"X-Forwarded-Proto": protoHdr,
|
"X-Forwarded-Proto": protoHdr,
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
},
|
},
|
||||||
// server component ไม่ต้องใช้ credentials
|
// server component ไม่ต้à¸à¸‡à¹ƒà¸Šà¹‰ credentials
|
||||||
cache: "no-store",
|
cache: "no-store",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ async function fetchSessionFromAPI() {
|
|||||||
export default async function ProtectedLayout({ children }) {
|
export default async function ProtectedLayout({ children }) {
|
||||||
const session = await fetchSessionFromAPI();
|
const session = await fetchSessionFromAPI();
|
||||||
if (!session) {
|
if (!session) {
|
||||||
// พยายามส่ง next path กลับไปที่ /login
|
// พยายามส่ง next path à¸à¸¥à¸±à¸šà¹„ปที่ /login
|
||||||
redirect("/login?next=/dashboard");
|
redirect("/login?next=/dashboard");
|
||||||
}
|
}
|
||||||
const { user } = session;
|
const { user } = session;
|
||||||
@@ -53,7 +53,7 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
<div className="mb-3 text-sm">RBAC: <b>{user.role}</b></div>
|
<div className="mb-3 text-sm">RBAC: <b>{user.role}</b></div>
|
||||||
|
|
||||||
<nav className="space-y-2">
|
<nav className="space-y-2">
|
||||||
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/dashboard">แดชบอร์ด</Link>
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/dashboard">à¹à¸”ชบà¸à¸£à¹Œà¸”</Link>
|
||||||
<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="/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="/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="/transmittals">Transmittals</Link>
|
||||||
@@ -68,7 +68,7 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/health">Health</Link>
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/health">Health</Link>
|
||||||
)}
|
)}
|
||||||
{can(user, "users:manage") && (
|
{can(user, "users:manage") && (
|
||||||
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/users">ผู้ใช้/บทบาท</Link>
|
<Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/users">ผู้ใช้/บทบาท</Link>
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -77,13 +77,13 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
<main className="col-span-12 space-y-6 lg:col-span-9 xl:col-span-9">
|
<main className="col-span-12 space-y-6 lg:col-span-9 xl:col-span-9">
|
||||||
{/* 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">Document Management System — LCBP3 Phase 3</div>
|
<div className="flex-1 text-lg font-semibold">Document Management System — LCBP3 Phase 3</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 className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/admin">Admin</a>
|
||||||
)}
|
)}
|
||||||
{can(user, "users:manage") && (
|
{can(user, "users:manage") && (
|
||||||
<a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/users">ผู้ใช้/บทบาท</a>
|
<a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/users">ผู้ใช้/บทบาท</a>
|
||||||
)}
|
)}
|
||||||
{can(user, "health:view") && (
|
{can(user, "health:view") && (
|
||||||
<a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/health">Health</a>
|
<a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/health">Health</a>
|
||||||
@@ -101,7 +101,7 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
<a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/transmittals/new">+ Transmittal</a>
|
<a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/transmittals/new">+ Transmittal</a>
|
||||||
)}
|
)}
|
||||||
{can(user, "correspondence:create") && (
|
{can(user, "correspondence:create") && (
|
||||||
<a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/correspondences/new">+ หนังสือสื่อสาร</a>
|
<a className="px-3 py-2 text-white rounded-xl" style={{ background: "#0D5C75" }} href="/correspondences/new">+ หนังสืà¸à¸ªà¸·à¹ˆà¸à¸ªà¸²à¸£</a>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -109,4 +109,4 @@ export default async function ProtectedLayout({ children }) {
|
|||||||
</main>
|
</main>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
1
|
1
|
||||||
/var/lib/postgresql/data
|
/var/lib/postgresql/data
|
||||||
1759295885
|
1759310848
|
||||||
5432
|
5432
|
||||||
/var/run/postgresql
|
/var/run/postgresql
|
||||||
*
|
*
|
||||||
|
|||||||
Binary file not shown.
@@ -272,4 +272,3 @@ if ($request_method = OPTIONS) {
|
|||||||
# Custom
|
# Custom
|
||||||
include /data/nginx/custom/server_proxy[.]conf;
|
include /data/nginx/custom/server_proxy[.]conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user