quick commit
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Failing after 6m9s
CI/CD Pipeline / Security Scanning (push) Successful in 26s
CI/CD Pipeline / Tests (3.11) (push) Failing after 5m24s
CI/CD Pipeline / Tests (3.12) (push) Failing after 5m23s
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Deploy to Staging (push) Has been skipped
CI/CD Pipeline / Deploy to Production (push) Has been skipped
CI/CD Pipeline / Notification (push) Successful in 1s
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Failing after 6m9s
CI/CD Pipeline / Security Scanning (push) Successful in 26s
CI/CD Pipeline / Tests (3.11) (push) Failing after 5m24s
CI/CD Pipeline / Tests (3.12) (push) Failing after 5m23s
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Deploy to Staging (push) Has been skipped
CI/CD Pipeline / Deploy to Production (push) Has been skipped
CI/CD Pipeline / Notification (push) Successful in 1s
This commit is contained in:
112
dashboard/frontend/src/components/Layout.tsx
Normal file
112
dashboard/frontend/src/components/Layout.tsx
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Main dashboard layout with navigation
|
||||
*/
|
||||
|
||||
import { Link, Outlet, useLocation } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { authApi } from '../services/api';
|
||||
|
||||
const navigation = [
|
||||
{ name: 'Dashboard', href: '/' },
|
||||
{ name: 'Analytics', href: '/analytics' },
|
||||
{ name: 'Users', href: '/users' },
|
||||
{ name: 'Moderation', href: '/moderation' },
|
||||
{ name: 'Settings', href: '/settings' },
|
||||
];
|
||||
|
||||
export function Layout() {
|
||||
const location = useLocation();
|
||||
const { data: me } = useQuery({
|
||||
queryKey: ['me'],
|
||||
queryFn: authApi.getMe,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
{/* Header */}
|
||||
<header className="bg-white border-b border-gray-200">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
<div className="flex items-center">
|
||||
<h1 className="text-xl font-bold text-gray-900">GuardDen</h1>
|
||||
<nav className="ml-10 flex space-x-4">
|
||||
{navigation.map((item) => {
|
||||
const isActive = location.pathname === item.href;
|
||||
return (
|
||||
<Link
|
||||
key={item.name}
|
||||
to={item.href}
|
||||
className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||
isActive
|
||||
? 'bg-gray-100 text-gray-900'
|
||||
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'
|
||||
}`}
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-4">
|
||||
{me?.owner ? (
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-sm text-gray-600">
|
||||
{me.entra ? '✓ Entra' : ''} {me.discord ? '✓ Discord' : ''}
|
||||
</span>
|
||||
<a
|
||||
href="/auth/logout"
|
||||
className="text-sm text-gray-600 hover:text-gray-900"
|
||||
>
|
||||
Logout
|
||||
</a>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex space-x-2">
|
||||
<a href="/auth/entra/login" className="btn-secondary text-sm">
|
||||
Login with Entra
|
||||
</a>
|
||||
<a href="/auth/discord/login" className="btn-primary text-sm">
|
||||
Connect Discord
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Main content */}
|
||||
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
{!me?.owner ? (
|
||||
<div className="card text-center py-12">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-4">
|
||||
Authentication Required
|
||||
</h2>
|
||||
<p className="text-gray-600 mb-6">
|
||||
Please authenticate with both Entra ID and Discord to access the dashboard.
|
||||
</p>
|
||||
<div className="flex justify-center space-x-4">
|
||||
<a href="/auth/entra/login" className="btn-secondary">
|
||||
Login with Entra
|
||||
</a>
|
||||
<a href="/auth/discord/login" className="btn-primary">
|
||||
Connect Discord
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<Outlet />
|
||||
)}
|
||||
</main>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="mt-12 border-t border-gray-200 py-6">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center text-sm text-gray-500">
|
||||
© {new Date().getFullYear()} GuardDen. Discord Moderation Bot.
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user