diff --git a/src/app/admin/contract-management/page.tsx b/src/app/admin/contract-management/page.tsx index a09c51b..a8349d0 100644 --- a/src/app/admin/contract-management/page.tsx +++ b/src/app/admin/contract-management/page.tsx @@ -1,13 +1,41 @@ 'use client'; -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import PageLayout from '../../components/PageLayout'; import ContractEditor from './components/contractEditor'; import ContractUploadCompanyStamp from './components/contractUploadCompanyStamp'; import ContractTemplateList from './components/contractTemplateList'; +import useAuthStore from '../../store/authStore'; +import { useRouter } from 'next/navigation'; export default function ContractManagementPage() { const [refreshKey, setRefreshKey] = useState(0); + const user = useAuthStore((s) => s.user); + const [mounted, setMounted] = useState(false); + const router = useRouter(); + + useEffect(() => { + setMounted(true); + }, []); + + // Only allow admin + const isAdmin = + !!user && + ( + (user as any)?.role === 'admin' || + (user as any)?.userType === 'admin' || + (user as any)?.isAdmin === true || + ((user as any)?.roles?.includes?.('admin')) + ); + + useEffect(() => { + if (mounted && !isAdmin) { + router.replace('/'); // or show a 403 page + } + }, [mounted, isAdmin, router]); + + if (!mounted) return null; + if (!isAdmin) return null; const bumpRefresh = () => setRefreshKey((k) => k + 1); diff --git a/src/app/components/nav/Header.tsx b/src/app/components/nav/Header.tsx index 87420d7..b91b427 100644 --- a/src/app/components/nav/Header.tsx +++ b/src/app/components/nav/Header.tsx @@ -197,6 +197,12 @@ export default function Header() { ((user as any)?.roles?.includes?.('admin')) ) + // Fix: Only render header after hydration to avoid SSR/CSR mismatch + if (!mounted) { + // Optionally, render a skeleton or nothing + return
; + } + return (