bug: hydration fix

This commit is contained in:
DeathKaioken 2025-10-28 22:01:29 +01:00
parent 2eca3007e4
commit 294d4eb8a3
2 changed files with 42 additions and 2 deletions

View File

@ -1,13 +1,41 @@
'use client'; 'use client';
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import PageLayout from '../../components/PageLayout'; import PageLayout from '../../components/PageLayout';
import ContractEditor from './components/contractEditor'; import ContractEditor from './components/contractEditor';
import ContractUploadCompanyStamp from './components/contractUploadCompanyStamp'; import ContractUploadCompanyStamp from './components/contractUploadCompanyStamp';
import ContractTemplateList from './components/contractTemplateList'; import ContractTemplateList from './components/contractTemplateList';
import useAuthStore from '../../store/authStore';
import { useRouter } from 'next/navigation';
export default function ContractManagementPage() { export default function ContractManagementPage() {
const [refreshKey, setRefreshKey] = useState(0); 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); const bumpRefresh = () => setRefreshKey((k) => k + 1);

View File

@ -197,6 +197,12 @@ export default function Header() {
((user as any)?.roles?.includes?.('admin')) ((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 <div style={{ minHeight: 80 }} />;
}
return ( return (
<header <header
// Remove bottom border when admin subheader is present to avoid a blue line under the gold bar // Remove bottom border when admin subheader is present to avoid a blue line under the gold bar
@ -411,13 +417,19 @@ export default function Header() {
> >
User Verify User Verify
</button> </button>
{/* NEW: Matrix Management link */}
<button <button
onClick={() => { console.log('🧭 Admin: navigate to /admin/matrix-management'); router.push('/admin/matrix-management') }} onClick={() => { console.log('🧭 Admin: navigate to /admin/matrix-management'); router.push('/admin/matrix-management') }}
className="text-sm font-semibold text-[#0F1D37] hover:text-[#7A5E1A]" className="text-sm font-semibold text-[#0F1D37] hover:text-[#7A5E1A]"
> >
Matrix Management Matrix Management
</button> </button>
{/* Contract Management only for admin */}
<button
onClick={() => { console.log('🧭 Admin: navigate to /admin/contract-management'); router.push('/admin/contract-management') }}
className="text-sm font-semibold text-[#0F1D37] hover:text-[#7A5E1A]"
>
Contract Management
</button>
</div> </div>
</div> </div>
</div> </div>