86 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // frontend/app/(protected)/layout.jsx
 | |
| import Link from "next/link";
 | |
| import { redirect } from "next/navigation";
 | |
| import { usePathname } from 'next/navigation';
 | |
| import { cookies, headers } from "next/headers";
 | |
| import { can } from "@/lib/rbac";
 | |
| import { Home, FileText, Users, Settings } from 'lucide-react'; // เพิ่ม Users, Settings หรือไอคอนที่ต้องการ
 | |
| 
 | |
| 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 }) {
 | |
|   const session = await fetchSessionFromAPI();
 | |
|   if (!session) {
 | |
|     redirect("/login?next=/dashboard");
 | |
|   }
 | |
|   const { user } = session;
 | |
| 
 | |
|   return (
 | |
|     <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">
 | |
|         <div className="p-4 border rounded-3xl bg-white/70">
 | |
|           <div className="mb-3 text-sm">RBAC: <b>{user.role}</b></div>
 | |
|           <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="/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") && <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, "users:manage") && <Link className="block px-4 py-2 rounded-xl bg-white/60 hover:bg-white" href="/users">ผู้ใช้/บทบาท</Link>}
 | |
|           </nav>
 | |
|         </div>
 | |
|       </aside>
 | |
| 
 | |
|       <main className="col-span-12 space-y-6 lg:col-span-9 xl:col-span-9">
 | |
|         <div className="flex items-center gap-2">
 | |
|           <div className="flex-1 text-lg font-semibold">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, "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>
 | |
| 
 | |
|         {children}
 | |
|       </main>
 | |
|     </section>
 | |
|   );
 | |
| }
 | 
