/
Mihaham
/
Table-Time
Обзор
Документация
Войти
/
Mihaham
/
Table-Time
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
apps/web/components/admin/AdminShell.tsx
103 строки
4 KB
MihahamYT
feat: dedicated web panels for all 46 games
14 июн 2026, 21:36
14 июн 2026, 21:36
4e11c3f
Код
Авторство
О чём код?
"use client"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; import { useState } from "react"; import { clearAdminToken } from "@/lib/adminApi"; const NAV = [ { href: "/admin/dashboard", label: "Обзор", icon: "📊" }, { href: "/admin/games", label: "Игры", icon: "🎮" }, { href: "/admin/sessions", label: "Сессии", icon: "🚪" }, { href: "/admin/security", label: "Безопасность", icon: "🛡" }, { href: "/admin/system", label: "Система", icon: "⚙" }, ]; export function AdminShell({ children }: { children: React.ReactNode }) { const pathname = usePathname(); const router = useRouter(); const [mobileOpen, setMobileOpen] = useState(false); const handleLogout = () => { clearAdminToken(); router.push("/admin/login"); }; const handleRefresh = () => { router.refresh(); window.location.reload(); }; return ( <div className="flex min-h-screen bg-board-bg"> {mobileOpen && ( <button type="button" className="fixed inset-0 z-40 bg-black/30 lg:hidden" aria-label="Закрыть меню" onClick={() => setMobileOpen(false)} /> )} <aside className={`fixed inset-y-0 left-0 z-50 flex w-56 flex-col border-r border-brand/20 bg-white/90 backdrop-blur transition-transform lg:static lg:translate-x-0 ${ mobileOpen ? "translate-x-0" : "-translate-x-full" }`} > <div className="border-b border-brand/10 px-4 py-5"> <p className="text-lg font-bold text-brand">TableTime Admin</p> <p className="text-xs text-gray-500">Панель оператора</p> </div> <nav className="flex-1 space-y-1 p-3"> {NAV.map((item) => { const active = pathname === item.href || pathname.startsWith(`${item.href}/`); return ( <Link key={item.href} href={item.href} onClick={() => setMobileOpen(false)} className={`flex items-center gap-2 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors ${ active ? "border-l-4 border-brand bg-brand/10 text-brand" : "text-gray-700 hover:bg-brand/5" }`} > <span aria-hidden>{item.icon}</span> {item.label} </Link> ); })} </nav> </aside> <div className="flex min-w-0 flex-1 flex-col"> <header className="sticky top-0 z-30 flex items-center justify-between gap-3 border-b border-brand/20 bg-white/80 px-4 py-3 backdrop-blur"> <button type="button" className="rounded-lg border px-3 py-1.5 text-sm lg:hidden" onClick={() => setMobileOpen(true)} > ☰ Меню </button> <div className="ml-auto flex items-center gap-2"> <button type="button" onClick={handleRefresh} className="rounded-lg border px-3 py-1.5 text-sm hover:bg-gray-50" > Обновить </button> <button type="button" onClick={handleLogout} className="rounded-lg border border-brand/30 px-3 py-1.5 text-sm text-brand hover:bg-brand/5" > Выйти </button> </div> </header> <main className="flex-1 p-4 lg:p-6">{children}</main> </div> </div> ); }