/
guselnikov
/
inst
Обзор
Документация
Войти
/
guselnikov
/
inst
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
admin/src/components/Layout.tsx
97 строк
3 KB
Viktor Guselnikov
new
26 июл 2026, 18:42
26 июл 2026, 18:42
322e1f1
Код
Авторство
О чём код?
import { NavLink, Outlet, Navigate } from 'react-router-dom'; import { Filter, Hash, Heart, Image, LogOut, Sparkles, Upload, Users, } from 'lucide-react'; import { InstagramIcon } from './icons/InstagramIcon'; import { useAuth } from '../hooks/useAuth'; import { ThemeToggle } from './ui/ThemeToggle'; import styles from './Layout.module.css'; const navGroups = [ { label: 'Сбор данных', items: [ { to: '/parsing', label: 'Парсинг', icon: Hash }, { to: '/filters', label: 'Фильтры', icon: Filter }, { to: '/audiences', label: 'Аудитории', icon: Users }, { to: '/vatago', label: 'Vatago', icon: Upload }, ], }, { label: 'Автоматизация', items: [ { to: '/mass-like', label: 'Масслайкинг', icon: Heart }, { to: '/ai-studio', label: 'AI-студия', icon: Sparkles }, { to: '/posts', label: 'Посты', icon: Image }, ], }, { label: 'Настройки', items: [{ to: '/ig-accounts', label: 'IG аккаунты', icon: InstagramIcon }], }, ] as const; export function Layout() { const { logout } = useAuth(); return ( <div className={styles.shell}> <aside className={styles.sidebar}> <div className={styles.brand}> <div className={styles.logo}> <InstagramIcon size={20} /> </div> <div className={styles.brandText}> <span className={styles.brandName}>inst</span> <span className={styles.brandTag}>Vatago parser</span> </div> </div> <nav className={styles.nav} aria-label="Основная навигация"> {navGroups.map((group) => ( <div key={group.label} className={styles.navGroup}> <span className={styles.navGroupLabel}>{group.label}</span> {group.items.map(({ to, label, icon: Icon }) => ( <NavLink key={to} to={to} className={({ isActive }) => [styles.navLink, isActive ? styles.navLinkActive : ''].filter(Boolean).join(' ') } > <Icon size={18} strokeWidth={2} aria-hidden /> {label} </NavLink> ))} </div> ))} </nav> <div className={styles.footer}> <ThemeToggle /> <button type="button" className={styles.logout} onClick={logout}> <LogOut size={16} aria-hidden /> Выйти </button> </div> </aside> <main className={styles.main}> <Outlet /> </main> </div> ); } export function ProtectedRoute() { const { token } = useAuth(); if (!token) return <Navigate to="/login" replace />; return <Layout />; }