From 3b0bbfc85834c7e933d9d4318599aed821c6a87f Mon Sep 17 00:00:00 2001 From: Sergey Karmanov Date: Mon, 11 May 2026 14:43:14 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20svg=20=D0=B8=D0=BA=D0=BE=D0=BD=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/assets/icons/alarm.svg | 22 +++ frontend/src/assets/icons/alert-triangle.svg | 21 +++ frontend/src/assets/icons/bell.svg | 20 +++ frontend/src/assets/icons/book-2.svg | 21 +++ frontend/src/assets/icons/books.svg | 25 ++++ frontend/src/assets/icons/building.svg | 26 ++++ frontend/src/assets/icons/bulb.svg | 21 +++ frontend/src/assets/icons/calendar-event.svg | 23 ++++ frontend/src/assets/icons/calendar.svg | 24 ++++ frontend/src/assets/icons/chart-bar.svg | 22 +++ frontend/src/assets/icons/chart-line.svg | 20 +++ frontend/src/assets/icons/circle-check.svg | 20 +++ frontend/src/assets/icons/circle-x.svg | 20 +++ frontend/src/assets/icons/clipboard-list.svg | 24 ++++ frontend/src/assets/icons/clock.svg | 20 +++ frontend/src/assets/icons/coin.svg | 21 +++ frontend/src/assets/icons/hand-stop.svg | 22 +++ frontend/src/assets/icons/home.svg | 21 +++ frontend/src/assets/icons/inbox.svg | 20 +++ frontend/src/assets/icons/info-circle.svg | 21 +++ frontend/src/assets/icons/lock.svg | 21 +++ frontend/src/assets/icons/logout.svg | 21 +++ frontend/src/assets/icons/map-pin.svg | 20 +++ frontend/src/assets/icons/message-circle.svg | 19 +++ frontend/src/assets/icons/mood-neutral.svg | 21 +++ frontend/src/assets/icons/robot.svg | 27 ++++ frontend/src/assets/icons/search.svg | 20 +++ frontend/src/assets/icons/shield.svg | 19 +++ frontend/src/assets/icons/sparkles.svg | 19 +++ frontend/src/assets/icons/star.svg | 19 +++ frontend/src/assets/icons/stopwatch.svg | 22 +++ frontend/src/assets/icons/thumb-down.svg | 19 +++ frontend/src/assets/icons/thumb-up.svg | 19 +++ frontend/src/assets/icons/trophy.svg | 24 ++++ frontend/src/assets/icons/user.svg | 20 +++ frontend/src/assets/icons/users.svg | 22 +++ frontend/src/assets/icons/world.svg | 23 ++++ .../src/components/layout/AppBottomNav.vue | 29 ++-- frontend/src/components/layout/AppSidebar.vue | 45 ++++--- frontend/src/components/layout/AppTopbar.vue | 11 +- .../src/components/ui/AchievementBadge.vue | 26 +++- frontend/src/components/ui/AppIcon.vue | 68 ++++++++++ frontend/src/components/ui/CoinChip.vue | 6 +- frontend/src/components/ui/EmptyState.vue | 6 +- frontend/src/components/ui/LectureCard.vue | 31 ++++- frontend/src/components/ui/SearchInput.vue | 6 +- frontend/src/components/ui/StatsWidget.vue | 7 +- .../src/components/ui/ToastNotification.vue | 5 +- frontend/src/icons/index.ts | 127 ++++++++++++++++++ .../src/views/admin/AdminDashboardView.vue | 8 +- frontend/src/views/auth/LoginView.vue | 16 ++- frontend/src/views/student/DashboardView.vue | 55 ++++++-- .../src/views/student/NotificationsView.vue | 15 ++- 53 files changed, 1162 insertions(+), 88 deletions(-) create mode 100644 frontend/src/assets/icons/alarm.svg create mode 100644 frontend/src/assets/icons/alert-triangle.svg create mode 100644 frontend/src/assets/icons/bell.svg create mode 100644 frontend/src/assets/icons/book-2.svg create mode 100644 frontend/src/assets/icons/books.svg create mode 100644 frontend/src/assets/icons/building.svg create mode 100644 frontend/src/assets/icons/bulb.svg create mode 100644 frontend/src/assets/icons/calendar-event.svg create mode 100644 frontend/src/assets/icons/calendar.svg create mode 100644 frontend/src/assets/icons/chart-bar.svg create mode 100644 frontend/src/assets/icons/chart-line.svg create mode 100644 frontend/src/assets/icons/circle-check.svg create mode 100644 frontend/src/assets/icons/circle-x.svg create mode 100644 frontend/src/assets/icons/clipboard-list.svg create mode 100644 frontend/src/assets/icons/clock.svg create mode 100644 frontend/src/assets/icons/coin.svg create mode 100644 frontend/src/assets/icons/hand-stop.svg create mode 100644 frontend/src/assets/icons/home.svg create mode 100644 frontend/src/assets/icons/inbox.svg create mode 100644 frontend/src/assets/icons/info-circle.svg create mode 100644 frontend/src/assets/icons/lock.svg create mode 100644 frontend/src/assets/icons/logout.svg create mode 100644 frontend/src/assets/icons/map-pin.svg create mode 100644 frontend/src/assets/icons/message-circle.svg create mode 100644 frontend/src/assets/icons/mood-neutral.svg create mode 100644 frontend/src/assets/icons/robot.svg create mode 100644 frontend/src/assets/icons/search.svg create mode 100644 frontend/src/assets/icons/shield.svg create mode 100644 frontend/src/assets/icons/sparkles.svg create mode 100644 frontend/src/assets/icons/star.svg create mode 100644 frontend/src/assets/icons/stopwatch.svg create mode 100644 frontend/src/assets/icons/thumb-down.svg create mode 100644 frontend/src/assets/icons/thumb-up.svg create mode 100644 frontend/src/assets/icons/trophy.svg create mode 100644 frontend/src/assets/icons/user.svg create mode 100644 frontend/src/assets/icons/users.svg create mode 100644 frontend/src/assets/icons/world.svg create mode 100644 frontend/src/components/ui/AppIcon.vue create mode 100644 frontend/src/icons/index.ts diff --git a/frontend/src/assets/icons/alarm.svg b/frontend/src/assets/icons/alarm.svg new file mode 100644 index 0000000..89f98f8 --- /dev/null +++ b/frontend/src/assets/icons/alarm.svg @@ -0,0 +1,22 @@ + + + + + + + diff --git a/frontend/src/assets/icons/alert-triangle.svg b/frontend/src/assets/icons/alert-triangle.svg new file mode 100644 index 0000000..8d9332e --- /dev/null +++ b/frontend/src/assets/icons/alert-triangle.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/bell.svg b/frontend/src/assets/icons/bell.svg new file mode 100644 index 0000000..fdf276b --- /dev/null +++ b/frontend/src/assets/icons/bell.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/book-2.svg b/frontend/src/assets/icons/book-2.svg new file mode 100644 index 0000000..d3464f1 --- /dev/null +++ b/frontend/src/assets/icons/book-2.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/books.svg b/frontend/src/assets/icons/books.svg new file mode 100644 index 0000000..13f40f8 --- /dev/null +++ b/frontend/src/assets/icons/books.svg @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/frontend/src/assets/icons/building.svg b/frontend/src/assets/icons/building.svg new file mode 100644 index 0000000..7f85a63 --- /dev/null +++ b/frontend/src/assets/icons/building.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/frontend/src/assets/icons/bulb.svg b/frontend/src/assets/icons/bulb.svg new file mode 100644 index 0000000..b6577b3 --- /dev/null +++ b/frontend/src/assets/icons/bulb.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/calendar-event.svg b/frontend/src/assets/icons/calendar-event.svg new file mode 100644 index 0000000..d3b85c2 --- /dev/null +++ b/frontend/src/assets/icons/calendar-event.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/frontend/src/assets/icons/calendar.svg b/frontend/src/assets/icons/calendar.svg new file mode 100644 index 0000000..20d6753 --- /dev/null +++ b/frontend/src/assets/icons/calendar.svg @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/frontend/src/assets/icons/chart-bar.svg b/frontend/src/assets/icons/chart-bar.svg new file mode 100644 index 0000000..0e55695 --- /dev/null +++ b/frontend/src/assets/icons/chart-bar.svg @@ -0,0 +1,22 @@ + + + + + + + diff --git a/frontend/src/assets/icons/chart-line.svg b/frontend/src/assets/icons/chart-line.svg new file mode 100644 index 0000000..97a4c02 --- /dev/null +++ b/frontend/src/assets/icons/chart-line.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/circle-check.svg b/frontend/src/assets/icons/circle-check.svg new file mode 100644 index 0000000..73eb6ae --- /dev/null +++ b/frontend/src/assets/icons/circle-check.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/circle-x.svg b/frontend/src/assets/icons/circle-x.svg new file mode 100644 index 0000000..c0bba84 --- /dev/null +++ b/frontend/src/assets/icons/circle-x.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/clipboard-list.svg b/frontend/src/assets/icons/clipboard-list.svg new file mode 100644 index 0000000..654a4c5 --- /dev/null +++ b/frontend/src/assets/icons/clipboard-list.svg @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/frontend/src/assets/icons/clock.svg b/frontend/src/assets/icons/clock.svg new file mode 100644 index 0000000..e4814fa --- /dev/null +++ b/frontend/src/assets/icons/clock.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/coin.svg b/frontend/src/assets/icons/coin.svg new file mode 100644 index 0000000..b546a3b --- /dev/null +++ b/frontend/src/assets/icons/coin.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/hand-stop.svg b/frontend/src/assets/icons/hand-stop.svg new file mode 100644 index 0000000..2c46e10 --- /dev/null +++ b/frontend/src/assets/icons/hand-stop.svg @@ -0,0 +1,22 @@ + + + + + + + diff --git a/frontend/src/assets/icons/home.svg b/frontend/src/assets/icons/home.svg new file mode 100644 index 0000000..d5fa9e3 --- /dev/null +++ b/frontend/src/assets/icons/home.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/inbox.svg b/frontend/src/assets/icons/inbox.svg new file mode 100644 index 0000000..9356470 --- /dev/null +++ b/frontend/src/assets/icons/inbox.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/info-circle.svg b/frontend/src/assets/icons/info-circle.svg new file mode 100644 index 0000000..c035ec3 --- /dev/null +++ b/frontend/src/assets/icons/info-circle.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/lock.svg b/frontend/src/assets/icons/lock.svg new file mode 100644 index 0000000..984acce --- /dev/null +++ b/frontend/src/assets/icons/lock.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/logout.svg b/frontend/src/assets/icons/logout.svg new file mode 100644 index 0000000..50b5972 --- /dev/null +++ b/frontend/src/assets/icons/logout.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/map-pin.svg b/frontend/src/assets/icons/map-pin.svg new file mode 100644 index 0000000..7501d8f --- /dev/null +++ b/frontend/src/assets/icons/map-pin.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/message-circle.svg b/frontend/src/assets/icons/message-circle.svg new file mode 100644 index 0000000..e712c74 --- /dev/null +++ b/frontend/src/assets/icons/message-circle.svg @@ -0,0 +1,19 @@ + + + + diff --git a/frontend/src/assets/icons/mood-neutral.svg b/frontend/src/assets/icons/mood-neutral.svg new file mode 100644 index 0000000..58cf5b8 --- /dev/null +++ b/frontend/src/assets/icons/mood-neutral.svg @@ -0,0 +1,21 @@ + + + + + + diff --git a/frontend/src/assets/icons/robot.svg b/frontend/src/assets/icons/robot.svg new file mode 100644 index 0000000..cdbb7b7 --- /dev/null +++ b/frontend/src/assets/icons/robot.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + diff --git a/frontend/src/assets/icons/search.svg b/frontend/src/assets/icons/search.svg new file mode 100644 index 0000000..3498a25 --- /dev/null +++ b/frontend/src/assets/icons/search.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/shield.svg b/frontend/src/assets/icons/shield.svg new file mode 100644 index 0000000..071513a --- /dev/null +++ b/frontend/src/assets/icons/shield.svg @@ -0,0 +1,19 @@ + + + + diff --git a/frontend/src/assets/icons/sparkles.svg b/frontend/src/assets/icons/sparkles.svg new file mode 100644 index 0000000..16d2cab --- /dev/null +++ b/frontend/src/assets/icons/sparkles.svg @@ -0,0 +1,19 @@ + + + + diff --git a/frontend/src/assets/icons/star.svg b/frontend/src/assets/icons/star.svg new file mode 100644 index 0000000..38eecdb --- /dev/null +++ b/frontend/src/assets/icons/star.svg @@ -0,0 +1,19 @@ + + + + diff --git a/frontend/src/assets/icons/stopwatch.svg b/frontend/src/assets/icons/stopwatch.svg new file mode 100644 index 0000000..9d85b90 --- /dev/null +++ b/frontend/src/assets/icons/stopwatch.svg @@ -0,0 +1,22 @@ + + + + + + + diff --git a/frontend/src/assets/icons/thumb-down.svg b/frontend/src/assets/icons/thumb-down.svg new file mode 100644 index 0000000..01a987d --- /dev/null +++ b/frontend/src/assets/icons/thumb-down.svg @@ -0,0 +1,19 @@ + + + + diff --git a/frontend/src/assets/icons/thumb-up.svg b/frontend/src/assets/icons/thumb-up.svg new file mode 100644 index 0000000..823b4eb --- /dev/null +++ b/frontend/src/assets/icons/thumb-up.svg @@ -0,0 +1,19 @@ + + + + diff --git a/frontend/src/assets/icons/trophy.svg b/frontend/src/assets/icons/trophy.svg new file mode 100644 index 0000000..6b7d40e --- /dev/null +++ b/frontend/src/assets/icons/trophy.svg @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/frontend/src/assets/icons/user.svg b/frontend/src/assets/icons/user.svg new file mode 100644 index 0000000..52fc7ea --- /dev/null +++ b/frontend/src/assets/icons/user.svg @@ -0,0 +1,20 @@ + + + + + diff --git a/frontend/src/assets/icons/users.svg b/frontend/src/assets/icons/users.svg new file mode 100644 index 0000000..1eca1af --- /dev/null +++ b/frontend/src/assets/icons/users.svg @@ -0,0 +1,22 @@ + + + + + + + diff --git a/frontend/src/assets/icons/world.svg b/frontend/src/assets/icons/world.svg new file mode 100644 index 0000000..9803590 --- /dev/null +++ b/frontend/src/assets/icons/world.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/frontend/src/components/layout/AppBottomNav.vue b/frontend/src/components/layout/AppBottomNav.vue index 83fa441..f459b90 100644 --- a/frontend/src/components/layout/AppBottomNav.vue +++ b/frontend/src/components/layout/AppBottomNav.vue @@ -2,6 +2,7 @@ import { computed } from 'vue' import { useRoute } from 'vue-router' import { useAuthStore } from '@/stores/auth' +import AppIcon from '@/components/ui/AppIcon.vue' const auth = useAuthStore() const route = useRoute() @@ -9,22 +10,22 @@ const route = useRoute() const navItems = computed(() => { const role = auth.user?.role ?? 'student' if (role === 'teacher') return [ - { label: 'Дашборд', icon: '📊', to: '/teacher' }, - { label: 'Лекции', icon: '📖', to: '/teacher/lectures' }, - { label: 'Аналитика',icon: '📈', to: '/teacher/analytics' }, - { label: 'Профиль', icon: '👤', to: '/profile' }, + { label: 'Дашборд', icon: 'chart-bar', to: '/teacher' }, + { label: 'Лекции', icon: 'book-2', to: '/teacher/lectures' }, + { label: 'Аналитика', icon: 'chart-line', to: '/teacher/analytics' }, + { label: 'Профиль', icon: 'user', to: '/profile' }, ] if (role === 'admin') return [ - { label: 'Дашборд', icon: '🛡️', to: '/admin' }, - { label: 'Юзеры', icon: '👥', to: '/admin/users' }, - { label: 'Лекции', icon: '📚', to: '/admin/lectures' }, - { label: 'ИИ', icon: '🤖', to: '/admin/llm-queue' }, + { label: 'Дашборд', icon: 'shield', to: '/admin' }, + { label: 'Юзеры', icon: 'users', to: '/admin/users' }, + { label: 'Лекции', icon: 'books', to: '/admin/lectures' }, + { label: 'ИИ', icon: 'robot', to: '/admin/llm-queue' }, ] return [ - { label: 'Главная', icon: '🏠', to: '/' }, - { label: 'Лекции', icon: '📚', to: '/catalog' }, - { label: 'Мои', icon: '📋', to: '/my-lectures' }, - { label: 'Профиль', icon: '👤', to: '/profile' }, + { label: 'Главная', icon: 'home', to: '/' }, + { label: 'Лекции', icon: 'books', to: '/catalog' }, + { label: 'Мои', icon: 'clipboard-list', to: '/my-lectures' }, + { label: 'Профиль', icon: 'user', to: '/profile' }, ] }) @@ -43,7 +44,7 @@ function isActive(to: string) { class="bottom-nav-item" :class="{ active: isActive(item.to) }" > - {{ item.icon }} + {{ item.label }} @@ -78,7 +79,7 @@ function isActive(to: string) { transition: color 0.2s; } .bottom-nav-item.active { color: var(--color-primary-dark); } -.bottom-nav-icon { font-size: 20px; } +.bottom-nav-icon { color: currentColor; } .bottom-nav-label { font-size: 10px; font-weight: 600; } @media (max-width: 768px) { .bottom-nav { display: flex; } } diff --git a/frontend/src/components/layout/AppSidebar.vue b/frontend/src/components/layout/AppSidebar.vue index d2ae79c..1a46111 100644 --- a/frontend/src/components/layout/AppSidebar.vue +++ b/frontend/src/components/layout/AppSidebar.vue @@ -2,6 +2,7 @@ import { computed } from 'vue' import { useRouter, useRoute } from 'vue-router' import { useAuthStore } from '@/stores/auth' +import AppIcon from '@/components/ui/AppIcon.vue' const auth = useAuthStore() const router = useRouter() @@ -10,22 +11,22 @@ const route = useRoute() interface NavItem { label: string; icon: string; to: string; roles: string[] } const navItems: NavItem[] = [ - { label: 'Главная', icon: '🏠', to: '/', roles: ['student'] }, - { label: 'Каталог', icon: '📚', to: '/catalog', roles: ['student'] }, - { label: 'Мои лекции', icon: '📋', to: '/my-lectures', roles: ['student'] }, - { label: 'Достижения', icon: '🏆', to: '/achievements', roles: ['student'] }, - { label: 'Уведомления', icon: '🔔', to: '/notifications', roles: ['student'] }, - { label: 'Профиль', icon: '👤', to: '/profile', roles: ['student'] }, + { label: 'Главная', icon: 'home', to: '/', roles: ['student'] }, + { label: 'Каталог', icon: 'books', to: '/catalog', roles: ['student'] }, + { label: 'Мои лекции', icon: 'clipboard-list', to: '/my-lectures', roles: ['student'] }, + { label: 'Достижения', icon: 'trophy', to: '/achievements', roles: ['student'] }, + { label: 'Уведомления', icon: 'bell', to: '/notifications', roles: ['student'] }, + { label: 'Профиль', icon: 'user', to: '/profile', roles: ['student'] }, // Teacher - { label: 'Дашборд', icon: '📊', to: '/teacher', roles: ['teacher'] }, - { label: 'Лекции', icon: '📖', to: '/teacher/lectures',roles: ['teacher'] }, - { label: 'Аналитика', icon: '📈', to: '/teacher/analytics',roles: ['teacher'] }, - { label: 'Профиль', icon: '👤', to: '/profile', roles: ['teacher'] }, + { label: 'Дашборд', icon: 'chart-bar', to: '/teacher', roles: ['teacher'] }, + { label: 'Лекции', icon: 'book-2', to: '/teacher/lectures', roles: ['teacher'] }, + { label: 'Аналитика', icon: 'chart-line', to: '/teacher/analytics', roles: ['teacher'] }, + { label: 'Профиль', icon: 'user', to: '/profile', roles: ['teacher'] }, // Admin - { label: 'Дашборд', icon: '🛡️', to: '/admin', roles: ['admin'] }, - { label: 'Пользователи',icon: '👥', to: '/admin/users', roles: ['admin'] }, - { label: 'Лекции', icon: '📚', to: '/admin/lectures', roles: ['admin'] }, - { label: 'ИИ очередь', icon: '🤖', to: '/admin/llm-queue', roles: ['admin'] }, + { label: 'Дашборд', icon: 'shield', to: '/admin', roles: ['admin'] }, + { label: 'Пользователи', icon: 'users', to: '/admin/users', roles: ['admin'] }, + { label: 'Лекции', icon: 'books', to: '/admin/lectures', roles: ['admin'] }, + { label: 'ИИ очередь', icon: 'robot', to: '/admin/llm-queue', roles: ['admin'] }, ] const visible = computed(() => @@ -44,18 +45,19 @@ function isActive(to: string) { - {{ item.icon }} + :to="item.to" + class="nav-item" + :class="{ active: isActive(item.to) }" + > + {{ item.label }} @@ -107,7 +109,7 @@ function isActive(to: string) { font-weight: 700; box-shadow: 0 2px 8px rgba(34,197,94,0.12); } -.nav-icon { font-size: 17px; flex-shrink: 0; } +.nav-icon { flex-shrink: 0; color: currentColor; } .sidebar-footer { padding: 10px 18px 8px; } .logout-btn { width: 100%; @@ -124,6 +126,7 @@ function isActive(to: string) { align-items: center; gap: 6px; } +.logout-icon { color: currentColor; } .logout-btn:hover { background: rgba(239,68,68,0.15); } @media (max-width: 768px) { .sidebar { display: none; } } diff --git a/frontend/src/components/layout/AppTopbar.vue b/frontend/src/components/layout/AppTopbar.vue index 53af3d5..1b90ed8 100644 --- a/frontend/src/components/layout/AppTopbar.vue +++ b/frontend/src/components/layout/AppTopbar.vue @@ -5,6 +5,7 @@ import { useAuthStore } from '@/stores/auth' import { useUserStore } from '@/stores/user' import CoinChip from '@/components/ui/CoinChip.vue' import SearchInput from '@/components/ui/SearchInput.vue' +import AppIcon from '@/components/ui/AppIcon.vue' import { formatUserName } from '@/utils/formatUserName' const auth = useAuthStore() @@ -35,7 +36,7 @@ function openProfile() {