# 🎨 Frontend ## Общая информация | Параметр | Значение | |----------|----------| | **Фреймворк** | Нет (Vanilla JavaScript) | | **Модульная система** | ES6 Modules (`import`/`export`) | | **Стили** | CSS (модульный подход) | | **Шрифт** | [Inter](https://fonts.google.com/specimen/Inter) (Google Fonts) | | **Веб-сервер** | Apache httpd:alpine | --- ## Структура файлов ``` frontend/ ├── index.html # 🔐 Страница авторизации (общая) ├── script.js # Логика авторизации ├── style.css # Стили страницы авторизации ├── theme-toggle.js # Переключение светлой/тёмной темы ├── Dockerfile # httpd:alpine │ ├── admin/ # 👨‍💼 Интерфейс администратора │ ├── index.html # SPA-оболочка с sidebar │ ├── css/ │ │ ├── main.css # CSS-переменные, цвета, типографика │ │ ├── layout.css # Раскладка (sidebar, topbar, content) │ │ ├── components.css # Кнопки, таблицы, карточки, формы │ │ ├── modals.css # Модальные окна │ │ ├── department.css # Стили кафедры │ │ └── departments-data.css # Стили создания кафедры/специальности │ ├── js/ │ │ ├── main.js # Инициализация, маршрутизация, навигация │ │ ├── api.js # HTTP-обёртка (fetch + Authorization) │ │ ├── utils.js # Утилиты │ │ ├── otel.js # OpenTelemetry (клиентская телеметрия, только прод) │ │ └── views/ # Модули представлений │ │ ├── users.js # Управление пользователями │ │ ├── groups.js # Управление группами │ │ ├── classrooms.js # Управление аудиториями │ │ ├── subjects.js # Управление дисциплинами │ │ ├── equipments.js # Управление оборудованием │ │ ├── edu-forms.js # Формы обучения │ │ ├── schedule.js # Расписание занятий │ │ ├── database.js # Управление тенантами │ │ ├── department.js # Кафедры │ │ └── departments-data.js # Создание кафедры/специальности │ ├── views/ # HTML-шаблоны представлений │ │ ├── users.html │ │ ├── groups.html │ │ ├── classrooms.html │ │ ├── subjects.html │ │ ├── equipments.html │ │ ├── edu-forms.html │ │ ├── schedule.html │ │ ├── database.html │ │ ├── department.html │ │ └── departments-data.html │ │ │ └── settings/ # ⚙️ Страница настроек (отдельный SPA) │ ├── index.html # Оболочка с собственной sidebar │ ├── css/ │ │ ├── main.css # CSS-переменные, базовые стили │ │ └── layout.css # Sidebar, topbar, content │ ├── js/ │ │ └── main.js # Навигация по вкладкам настроек │ └── views/ │ └── general.html # Общие настройки (заглушка) │ ├── teacher/ # 👩‍🏫 Интерфейс преподавателя │ └── index.html # Просмотр расписания │ └── student/ # 🎓 Интерфейс студента └── index.html # Просмотр расписания (read-only) ``` --- ## Система маршрутизации (Admin SPA) Админ-панель работает как **Single Page Application** без фреймворка. Навигация реализована через `data-tab` атрибуты на элементах sidebar: ```html Пользователи Группы Расписание занятий ``` При клике на пункт меню `main.js`: 1. Загружает HTML-шаблон из `views/{tab}.html` через `fetch()` 2. Вставляет его в `#app-content` 3. Подключает соответствующий JS-модуль из `js/views/{tab}.js` 4. Обновляет заголовок страницы (`#page-title`) ### Разделы админ-панели | Tab | Описание | API | |-----|----------|-----| | `users` | CRUD пользователей | `/api/users` | | `groups` | CRUD групп | `/api/groups` | | `edu-forms` | Формы обучения | `/api/education-forms` | | `equipments` | Оборудование | `/api/equipments` | | `classrooms` | Аудитории | `/api/classrooms` | | `subjects` | Дисциплины | `/api/subjects` | | `schedule` | Расписание | `/api/users/lessons` | | `database` | Тенанты | `/api/database` | | `department` | Кафедры | `/api/departments` | | `departments-data` | Создание кафедры/специальности | `/api/departments` | ### Страница настроек (`/admin/settings/`) Настройки — это **отдельный SPA** со своей боковой панелью и вкладками, не связанными с основной админ-панелью. - Доступ: через dropdown «Настройки» в footer боковой панели админки - Кнопка «Назад в панель» для возврата в `/admin/` - Текущие вкладки: - **Общие настройки** — заглушка (в разработке) --- ## API-клиент (`api.js`) Все HTTP-запросы проходят через обёртку `apiFetch()`: ```javascript export async function apiFetch(endpoint, method = 'GET', body = null) { const response = await fetch(endpoint, { method, headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: body ? JSON.stringify(body) : null }); if (!response.ok) { throw new Error(data?.message || `Ошибка HTTP: ${response.status}`); } return await response.json(); } // Shortcut-методы export const api = { get: (url) => apiFetch(url, 'GET'), post: (url, body) => apiFetch(url, 'POST', body), put: (url, body) => apiFetch(url, 'PUT', body), delete: (url, body) => apiFetch(url, 'DELETE', body) }; ``` Токен берётся из `localStorage.getItem('token')`. --- ## Аутентификация (Frontend) ### Страница входа (`/index.html`) 1. Пользователь вводит логин/пароль 2. `script.js` отправляет `POST /api/auth/login` 3. При успехе сохраняет в `localStorage`: - `token` — UUID-токен - `role` — роль пользователя 4. Перенаправляет на соответствующий интерфейс: - `ADMIN` → `/admin/` - `TEACHER` → `/teacher/` - `STUDENT` → `/student/` ### Проверка авторизации На каждой странице проверяется наличие токена и роли: ```javascript export function isAuthenticatedAsAdmin() { const role = localStorage.getItem('role'); return token && role === 'ADMIN'; } ``` ### Выход Кнопка «Выйти» находится в dropdown-меню «Настройки» в footer боковой панели. Очищает `localStorage` и перенаправляет на `/`. --- ## CSS-архитектура ### Модульный подход Стили разделены на модульные файлы (порядок подключения важен): 1. **`main.css`** — CSS-переменные (цвета, шрифты, отступы), глобальные стили, тёмная тема 2. **`layout.css`** — Sidebar, topbar, content area, dropdown настроек, responsive 3. **`components.css`** — Кнопки, таблицы, карточки, badge, формы, theme-toggle 4. **`modals.css`** — Модальные окна 5. **`department.css`** — Стили страницы кафедр 6. **`departments-data.css`** — Стили создания кафедры/специальности ### Темизация CSS-переменные позволяют поддерживать светлую/тёмную тему: ```css :root { --bg-primary: #ffffff; --text-primary: #1a1a2e; --accent: #6366f1; } [data-theme="dark"] { --bg-primary: #0f0f23; --text-primary: #e2e8f0; --accent: #818cf8; } ``` Переключение — через `theme-toggle.js`. --- ## Боковая панель (Sidebar) - **Скрытие/раскрытие** — кнопка-крестик в правом верхнем углу sidebar - **Десктоп** (`>768px`): sidebar складывается влево, контент расширяется; состояние сохраняется в `localStorage` (`sidebar-collapsed`) - **Мобильные** (`≤768px`): sidebar скрывается за кнопкой-гамбургер, выезжает как overlay с затемнением - **Dropdown «Настройки»** в footer sidebar — содержит ссылку на страницу настроек и кнопку выхода --- ## OpenTelemetry (`otel.js`) Клиентская телеметрия (document-load, fetch, XHR) отправляется через `BatchSpanProcessor` на `/otel/v1/traces`. - **На production** — загружается автоматически через динамический `import()` - **На localhost** — пропускается, чтобы избежать таймаутов CDN `esm.sh` ```javascript if (!['localhost', '127.0.0.1'].includes(window.location.hostname)) { import('./otel.js').catch(e => console.warn('OTel init skipped:', e.message)); } ``` --- ## Адаптивность Интерфейс адаптирован под мобильные устройства: - Sidebar скрывается на экранах < 768px, выезжает как overlay - Появляется кнопка-гамбургер (`#menu-toggle`) - Кнопка-крестик закрывает sidebar на всех устройствах - Таблицы получают горизонтальный скролл