Files
asle/frontend/app/admin/layout.tsx
defiQUG 507d9a35b1 Add initial project structure and documentation files
- Created .gitignore to exclude sensitive files and directories.
- Added API documentation in API_DOCUMENTATION.md.
- Included deployment instructions in DEPLOYMENT.md.
- Established project structure documentation in PROJECT_STRUCTURE.md.
- Updated README.md with project status and team information.
- Added recommendations and status tracking documents.
- Introduced testing guidelines in TESTING.md.
- Set up CI workflow in .github/workflows/ci.yml.
- Created Dockerfile for backend and frontend setups.
- Added various service and utility files for backend functionality.
- Implemented frontend components and pages for user interface.
- Included mobile app structure and services.
- Established scripts for deployment across multiple chains.
2025-12-03 21:22:31 -08:00

125 lines
4.1 KiB
TypeScript

'use client';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import Link from 'next/link';
export default function AdminLayout({
children,
}: {
children: React.ReactNode;
}) {
const router = useRouter();
const [admin, setAdmin] = useState<any>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem('admin_token');
if (!token) {
router.push('/admin/login');
return;
}
// Verify token
fetch('/api/admin/auth/verify', {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
if (!res.ok) {
router.push('/admin/login');
return;
}
return res.json();
})
.then((data) => {
if (data) setAdmin(data);
setLoading(false);
})
.catch(() => {
router.push('/admin/login');
});
}, [router]);
if (loading) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
</div>
);
}
if (!admin) return null;
return (
<div className="min-h-screen bg-gray-50">
<nav className="bg-white shadow-sm border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
<div className="flex">
<div className="flex-shrink-0 flex items-center">
<h1 className="text-xl font-bold text-gray-900">ASLE Admin</h1>
</div>
<div className="hidden sm:ml-6 sm:flex sm:space-x-8">
<Link
href="/admin"
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
>
Dashboard
</Link>
<Link
href="/admin/users"
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
>
Users
</Link>
<Link
href="/admin/config"
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
>
Config
</Link>
<Link
href="/admin/deployments"
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
>
Deployments
</Link>
<Link
href="/admin/white-label"
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
>
White-Label
</Link>
<Link
href="/admin/audit"
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
>
Audit Logs
</Link>
</div>
</div>
<div className="flex items-center">
<span className="text-sm text-gray-700 mr-4">{admin.email}</span>
<button
onClick={() => {
localStorage.removeItem('admin_token');
router.push('/admin/login');
}}
className="text-sm text-gray-500 hover:text-gray-700"
>
Logout
</button>
</div>
</div>
</div>
</nav>
<main className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
{children}
</main>
</div>
);
}