Files
magistr/docs/FRONTEND.md

14 KiB
Raw Blame History

🎨 Frontend

Общая информация

Параметр Значение
Фреймворк Нет (Vanilla JavaScript)
Модульная система ES6 Modules (import/export)
Стили CSS (модульный подход)
Шрифт Inter на странице входа, системный шрифт в кабинетах расписания
Веб-сервер 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      # Модальные окна
│   │   └── 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     # Управление тенантами
│   │       └── departments-data.js # Создание кафедры/специальности
│   ├── views/              # HTML-шаблоны представлений
│   │   ├── users.html
│   │   ├── groups.html
│   │   ├── classrooms.html
│   │   ├── subjects.html
│   │   ├── equipments.html
│   │   ├── edu-forms.html
│   │   ├── schedule.html
│   │   ├── database.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          # Недельный просмотр динамического расписания группы

Система маршрутизации (Admin SPA)

Админ-панель работает как Single Page Application без фреймворка.

Навигация реализована через data-tab атрибуты на элементах sidebar:

<a href="#" class="nav-item" data-tab="users">Пользователи</a>
<a href="#" class="nav-item" data-tab="groups">Группы</a>
<a href="#" class="nav-item" data-tab="schedule">Расписание занятий</a>

При клике на пункт меню 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/admin/schedule-rules, /api/admin/time-slots, /api/admin/calendar, /api/lesson-types
database Тенанты /api/database
departments-data Создание, редактирование и удаление кафедр/специальностей /api/departments, /api/specialties

Особенности админских вкладок

  • Вкладка groups загружает кафедры и специальности из справочников и при создании группы отправляет yearStartStudy; поле specialityCode содержит ID выбранной специальности.
  • Вкладка schedule не обращается к старым lessons API. Создание и редактирование расписания выполняется через правила /api/admin/schedule-rules, где каждое правило содержит группы и набор слотов.
  • Вкладка departments-data использует модальные формы редактирования и маршруты PUT/DELETE /api/departments/{id} и PUT/DELETE /api/specialties/{id}.

Страница настроек (/admin/settings/)

Настройки — это отдельный SPA со своей боковой панелью и вкладками, не связанными с основной админ-панелью.

  • Доступ: через dropdown «Настройки» в footer боковой панели админки
  • Кнопка «Назад в панель» для возврата в /admin/
  • Текущие вкладки:
    • Общие настройки — заглушка (в разработке)

API-клиент (api.js)

Все HTTP-запросы проходят через обёртку apiFetch():

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 — роль пользователя
    • departmentId — кафедра пользователя
    • userId — ID пользователя для личного расписания преподавателя
  4. Перенаправляет на соответствующий интерфейс:
    • ADMIN/admin/
    • TEACHER/teacher/
    • STUDENT/student/

Проверка авторизации

На каждой странице проверяется наличие токена и роли:

export function isAuthenticatedAsAdmin() {
    const role = localStorage.getItem('role');
    return token && role === 'ADMIN';
}

Выход

Кнопка «Выйти» находится в dropdown-меню «Настройки» в footer боковой панели. Очищает localStorage и перенаправляет на /.


Кабинеты расписания

Преподаватель (/teacher/)

Страница показывает недельную сетку занятий преподавателя. ID преподавателя берётся из localStorage.userId, который сохраняется после POST /api/auth/login.

Основные элементы:

  • навигация по неделям: предыдущая, текущая, следующая;
  • выбор даты через input[type="date"];
  • запрос GET /api/schedule?teacherId={userId}&startDate={YYYY-MM-DD}&endDate={YYYY-MM-DD};
  • отображение дисциплины, времени, типа занятия, аудитории и всех групп правила.

Если пользователь вошёл до появления поля userId, страница попросит выполнить вход заново.

Студент (/student/)

В текущей модели студент не связан с конкретной группой, поэтому страница использует выбор группы из /api/groups.

Основные элементы:

  • селект группы с сохранением выбора в localStorage.studentGroupId;
  • недельная сетка по дням;
  • запрос GET /api/schedule?groupId={groupId}&startDate={YYYY-MM-DD}&endDate={YYYY-MM-DD};
  • отображение дисциплины, времени, преподавателя, аудитории, формата и типа занятия.

CSS-архитектура

Модульный подход

Стили разделены на модульные файлы (порядок подключения важен):

  1. main.css — CSS-переменные (цвета, шрифты, отступы), глобальные стили, тёмная тема
  2. layout.css — Sidebar, topbar, content area, dropdown настроек, responsive
  3. components.css — Кнопки, таблицы, карточки, badge, формы, theme-toggle
  4. modals.css — Модальные окна
  5. departments-data.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
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 на всех устройствах
  • Таблицы получают горизонтальный скролл