Parcourir la source

feat: добавить guard роли в admin layout + ссылка Админка в Header

neyrogovnarik il y a 1 mois
Parent
commit
f679fd6c3e
2 fichiers modifiés avec 30 ajouts et 8 suppressions
  1. 22 8
      frontend/src/app/admin/layout.tsx
  2. 8 0
      frontend/src/components/Header.tsx

+ 22 - 8
frontend/src/app/admin/layout.tsx

@@ -1,16 +1,30 @@
 'use client'
 
 import Link from 'next/link'
-import { usePathname } from 'next/navigation'
-
-/**
- * Layout панели администратора. Отображает боковую панель
- * с навигацией по разделам: модерация, пользователи, теги.
- * Подсвечивает активный пункт меню.
- * @param children - Контент текущей страницы админки
- */
+import { usePathname, useRouter } from 'next/navigation'
+import { useEffect } from 'react'
+import { useAuth } from '@/hooks/useAuth'
+
+const ALLOWED_ROLES = ['moderator', 'superadmin']
+
 export default function AdminLayout({ children }: { children: React.ReactNode }) {
   const pathname = usePathname()
+  const router = useRouter()
+  const { user, isLoading } = useAuth()
+
+  useEffect(() => {
+    if (!isLoading && (!user || !ALLOWED_ROLES.includes(user.role))) {
+      router.replace('/')
+    }
+  }, [user, isLoading, router])
+
+  if (isLoading || !user || !ALLOWED_ROLES.includes(user.role)) {
+    return (
+      <div className="flex min-h-screen items-center justify-center bg-[#0f172a]">
+        <p className="text-white/40">Загрузка...</p>
+      </div>
+    )
+  }
 
   const navItems = [
     { href: '/admin', label: 'Модерация', icon: '📋' },

+ 8 - 0
frontend/src/components/Header.tsx

@@ -39,6 +39,14 @@ export default function Header() {
             >
               Мои места
             </Link>
+            {(user.role === 'moderator' || user.role === 'superadmin') && (
+              <Link
+                href="/admin"
+                className="text-sm text-green-400 hover:text-green-300 transition"
+              >
+                Админка
+              </Link>
+            )}
             <span className="text-sm text-white/60">{user.name || user.email}</span>
             <button
               onClick={logout}