/
DaniilSk
/
DesignLab
Обзор
Документация
Войти
/
DaniilSk
/
DesignLab
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
admin-frontend/src/widgets/AdminLayout.vue
146 строк
3 KB
Даниил
feat(admin): initialize admin frontend
13 июл 2026, 23:42
13 июл 2026, 23:42
1cc58f6
Код
Авторство
О чём код?
<template> <div class="admin-layout" :class="{ 'admin-layout--collapsed': collapsed }"> <aside class="sidebar"> <RouterLink class="brand" :to="{ name: 'dashboard' }">Design Lab</RouterLink> <nav> <RouterLink v-for="item in items" :key="item.name" :to="{ name: item.name }">{{ item.label }}</RouterLink> </nav> </aside> <div class="workspace"> <header class="topbar"> <button class="menu" type="button" @click="collapsed = !collapsed">☰</button> <strong>{{ auth.username }}</strong> <button class="button secondary" type="button" @click="signOut">Выйти</button> </header> <main class="content"> <RouterView /> </main> </div> </div> </template> <script setup lang="ts"> import { ref } from 'vue' import { useRouter } from 'vue-router' import { useAuthStore } from '@/stores/auth' const router = useRouter() const auth = useAuthStore() const collapsed = ref(false) const items = [ { name: 'dashboard', label: 'Dashboard' }, { name: 'users', label: 'Пользователи' }, { name: 'events', label: 'Лабы' }, { name: 'speakers', label: 'Спикеры' }, { name: 'loyalty', label: 'Лояльность' }, { name: 'media', label: 'Медиа' }, ] async function signOut() { await auth.logout() await router.push({ name: 'login' }) } </script> <style scoped> .admin-layout { display: grid; min-height: 100vh; grid-template-columns: 260px minmax(0, 1fr); } .sidebar { position: sticky; top: 0; height: 100vh; padding: 24px; background: #131313; color: #fff; } .brand { display: block; margin-bottom: 28px; font-size: 24px; font-weight: 900; text-decoration: none; } nav { display: flex; flex-direction: column; gap: 8px; } nav a { padding: 12px 14px; border-radius: 14px; color: rgba(255,255,255,.72); text-decoration: none; font-weight: 700; } nav a.router-link-active { background: #fff; color: #131313; } .workspace { min-width: 0; } .topbar { position: sticky; top: 0; z-index: 3; display: flex; height: 72px; align-items: center; justify-content: flex-end; gap: 14px; padding: 0 28px; background: rgba(240,240,240,.86); backdrop-filter: blur(16px); } .menu { display: none; width: 44px; height: 44px; border-radius: 50%; background: #fff; } .content { padding: 28px; } @media (max-width: 900px) { .admin-layout { grid-template-columns: 1fr; } .sidebar { position: fixed; z-index: 10; width: 260px; transform: translateX(0); transition: transform 180ms ease; } .admin-layout--collapsed .sidebar { transform: translateX(-100%); } .menu { display: inline-grid; place-items: center; margin-right: auto; } .content { padding: 16px; } } </style>