deckhearth/components/AdminProtected.js
Randall Stillwell 0d6c6f1957 Implemented admin authentication and seamless card editing
- Created admin authentication system with useIsAdmin hook
- Added AdminProtected component for route protection
- Added prominent 'Edit Card (Admin)' button on card detail pages
- Protected all admin routes (/admin/*) with authentication
- Added admin navigation item to main layout sidebar
- Updated auth verification API to return mock admin user
- Integrated admin edit button that redirects to card editor with card ID
- Added proper access denied page for non-admin users
- Admin-only features now show/hide based on user role
- Seamless workflow: spot incorrect card → click edit → fix immediately
2025-07-24 16:31:29 -05:00

87 lines
No EOL
2.7 KiB
JavaScript

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import Layout from './Layout';
export default function AdminProtected({ children }) {
const router = useRouter();
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [accessDenied, setAccessDenied] = useState(false);
useEffect(() => {
checkAdminAccess();
}, []);
const checkAdminAccess = async () => {
try {
const response = await fetch('/api/auth/verify');
if (response.ok) {
const userData = await response.json();
if (userData.role === 'admin') {
setUser(userData);
setAccessDenied(false);
} else {
setAccessDenied(true);
}
} else {
setAccessDenied(true);
}
} catch (error) {
console.error('Admin auth check failed:', error);
setAccessDenied(true);
} finally {
setLoading(false);
}
};
if (loading) {
return (
<Layout user={null}>
<div className="flex items-center justify-center min-h-screen">
<div className="text-center">
<div className="animate-spin rounded-full h-32 w-32 border-b-2 mx-auto mb-4" style={{ borderColor: 'var(--text-accent)' }}></div>
<p style={{ color: 'var(--text-secondary)' }}>Checking admin access...</p>
</div>
</div>
</Layout>
);
}
if (accessDenied) {
return (
<Layout user={user}>
<div className="flex items-center justify-center min-h-screen">
<div className="text-center">
<div className="text-6xl mb-4">🚫</div>
<h2 className="text-2xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
Access Denied
</h2>
<p className="mb-6" style={{ color: 'var(--text-secondary)' }}>
You need administrator privileges to access this page.
</p>
<div className="space-x-4">
<button
onClick={() => router.push('/login')}
className="px-6 py-3 rounded-xl font-medium gradient-bg-purple text-white hover:shadow-lg transition-all duration-200"
>
Login as Admin
</button>
<button
onClick={() => router.push('/')}
className="px-6 py-3 rounded-xl font-medium border transition-all duration-200"
style={{
borderColor: 'var(--border)',
color: 'var(--text-primary)'
}}
>
Go Home
</button>
</div>
</div>
</div>
</Layout>
);
}
return children;
}