Актуализация на основе текущего состояния

This commit is contained in:
2026-05-24 10:27:28 +03:00
parent 5245cf7b0b
commit e77fe8ef05
+160 -133
View File
@@ -1,183 +1,210 @@
# **EventHub Admin UI — Техническое задание** (MVP)
# EventHub Admin UI — Техническое задание (актуальная версия)
## 1. Роли и права доступа
| Роль | Идентификатор | Права |
|------|---------------|-------|
| **Суперадмин** | `superadmin` | Полный доступ ко всем модулям, включая изменение ролей других админов, просмотр аудита, системные настройки. |
| **Модератор** | `moderator` | Модерация событий и жалоб, блокировка/разблокировка пользователей, работа с баг-трекером. |
| **Поддержка** | `support` | Просмотр пользователей и событий (read-only), обработка жалоб, создание и обновление багов. |
| Роль | Идентификатор | Права |
|---------------|---------------|---------------------------------------------------------------------------------------------------------|
| Суперадмин | `superadmin` | Полный доступ ко всем модулям, включая изменение ролей других админов, просмотр аудита, системные настройки, управление администраторами. |
| Администратор | `admin` | Управление пользователями, событиями, жалобами, отзывами, бан-словами, тикетами, подписками. Нет доступа к аудиту и управлению администраторами. |
| Модератор | `moderator` | Работа с жалобами и отзывами. Остальные разделы недоступны. |
| Поддержка | `support` | Работа с тикетами (баг-трекер). Остальные разделы недоступны. |
**Примечание:** До реализации backend-эндпоинтов для управления ролями подразумевается одна роль `admin` (синоним `superadmin`).
Права проверяются на уровне фронтенда: пункты меню и маршруты отображаются или скрываются в зависимости от роли, полученной из `GET /v1/admin/me`.
---
## 2. Аутентификация и авторизация
## 2. Модули панели
Эндпоинты:
- `POST /v1/admin/login` — вход (email, пароль). Возвращает `{ token, refresh_token, user }`.
- `POST /v1/refresh` — обновление access-токена по refresh-токену.
- `GET /v1/admin/me` — данные текущего администратора, включая роль.
### 2.1. Дашборд (Dashboard)
Реализация:
- JWT-токены сохраняются в `localStorage`.
- Axios-интерсептор добавляет `Authorization: Bearer <token>` ко всем запросам.
- При получении 401 автоматически пытается обновить токен через `/v1/refresh`. Если обновление не удалось — редирект на страницу входа.
- При перезагрузке страницы токен проверяется через `GET /v1/admin/me`. Если токен валиден, сессия восстанавливается без повторного входа.
**Виджеты:**
- Статистика по пользователям: всего, новых за сегодня, активных за неделю.
- Статистика по событиям: всего, ожидают модерации, опубликовано, отклонено.
- Статистика по жалобам: новых, в обработке.
- График регистраций/событий по дням (за последние 30 дней) — если API предоставляет агрегации; иначе заглушка.
- Последние действия модераторов (аудит) — последние 10 записей.
## 3. Технологический стек
**Источник данных:** `GET /api/stats/*` (приоритетный) или агрегация из списков ресурсов через `X-Total-Count`.
- Язык: TypeScript
- Сборщик: Vite
- UI-фреймворк: React 18 + Ant Design 5
- Управление состоянием: Zustand (аутентификация), TanStack React Query v5 (серверное состояние)
- HTTP-клиент: Axios с интерсепторами
- Формы и валидация: React Hook Form + Zod
- Графики: Recharts
- Дата и время: dayjs с русской локалью
- Интернационализация: react-i18next (русский, английский)
- Роутинг: React Router v6
- WebSocket: нативное WebSocket API с автоматическим переподключением
- Контейнеризация: Docker, Nginx, Traefik
### 2.2. Управление пользователями
## 4. Модули панели
**Эндпоинты:** `GET /api/users`, `GET /api/users/:id`, `PUT /api/users/:id`, `DELETE /api/users/:id`
### 4.1. Дашборд (Dashboard)
**Функциональность:**
- Список пользователей (ID, username, email, роль, дата регистрации, статус, рейтинг).
- Фильтрация: по роли, статусу, поиск по username/email.
- Детальная карточка:
- Основная информация, аватар.
- Список событий пользователя.
- История жалоб на пользователя.
- Блокировка/разблокировка, смена роли (только суперадмин).
- Причина блокировки (поле ввода).
- Массовые действия: блокировка/удаление выбранных пользователей.
Эндпоинт: `GET /v1/admin/stats`
**Особые требования:** Подтверждение деструктивных действий через модальное окно.
Виджеты:
- Карточки с метриками: пользователи, события, отзывы, календари, жалобы, тикеты (всего и открытых), среднее время решения.
- Мини-графики (спарклайны) в карточках «Пользователи» и «События» — динамика по дням с плавной заливкой.
- Графики «События по дням» и «Регистрации по дням» на основе данных `events_by_day` и `registrations_by_day`.
- Таблица «Активность администраторов» с сортировкой по убыванию числа действий, раскрашенными ролями, форматированной датой последнего входа, заменой пустых значений на прочерк.
### 2.3. Управление событиями
### 4.2. Управление пользователями
**Эндпоинты:** `GET /api/events`, `GET /api/events/:id`, `PUT /api/events/:id`, `DELETE /api/events/:id`, а также эндпоинт модерации (например, `PATCH /api/events/:id/approve`)
Эндпоинты: `GET /v1/admin/users`, `GET /v1/admin/users/:id`, `PUT /v1/admin/users/:id`, `DELETE /v1/admin/users/:id`
**Функциональность:**
- Список событий (название, организатор, календарь, статус, количество записей).
- Фильтрация: по статусу, календарю, дате.
- Детальный просмотр:
- Полная информация о событии (описание, дата-время, локация, тип).
- Список записей участников с возможностью ручного подтверждения/отклонения.
- Кнопки «Одобрить» / «Отклонить» (изменение статуса с `pending` на `approved`/`rejected`).
- При отклонении — обязательное указание причины.
- Редактирование любого поля события.
- Удаление с подтверждением.
Функциональность:
- Список с серверной пагинацией и сортировкой по всем столбцам.
- Первая колонка — иконка для перехода на детальную страницу.
- Роли и статусы раскрашены (user — синий, bot — фиолетовый; active — зелёный, frozen — оранжевый, deleted — красный).
- Модальное окно редактирования: email, ник, роль, статус, причина. Обязательные поля подсвечиваются, кнопка «Сохранить» неактивна при пустых обязательных полях. Пустые строки не отправляются на сервер.
- Кнопка «Заморозить/Разморозить» открывает модальное окно с обязательной причиной при заморозке. Подгружается текущая причина, если она была.
- Кнопка «Удалить» открывает диалог подтверждения.
- Для удалённых пользователей (status=deleted) кнопки «Заморозить/Разморозить» и «Удалить» неактивны, кнопка «Редактировать» активна.
- Детальная страница пользователя: все поля из API, включая телефон, язык, часовой пояс, аватар URL, соцсети, настройки, даты создания/обновления. Пустые значения заменены на прочерк. Даты отформатированы.
### 2.4. Управление календарями
### 4.3. Управление событиями
**Эндпоинты:** `GET /api/calendars`, `POST /api/calendars`, `PUT /api/calendars/:id`, `DELETE /api/calendars/:id`
Эндпоинты: `GET /v1/admin/events`, `GET /v1/admin/events/:id`, `PUT /v1/admin/events/:id`, `DELETE /v1/admin/events/:id`
**Функциональность:**
- Список календарей (название, владелец, тип, количество подписчиков).
- Детальный просмотр: информация, возможность деактивации календаря.
- Создание коммерческого календаря (опционально, если требуется админам).
- Просмотр списка подписчиков (только чтение).
Функциональность:
- Список с серверной пагинацией и сортировкой.
- Первая колонка — иконка для перехода на детальную страницу.
- Типы событий раскрашены (single — синий, recurring — фиолетовый).
- Статусы раскрашены (active — зелёный, cancelled — красный, completed — серый).
- Модальное окно редактирования: название, описание, тип, статус, дата и время начала (DatePicker), продолжительность, вместимость, специалист ID, календарь ID, ссылка онлайн, теги. Валидация обязательных полей.
- Кнопки «Редактировать» и «Удалить» с иконками.
- Детальная страница события: все поля из API (название, описание, тип, статус, причина, дата начала, продолжительность, вместимость, специалист, календарь, мастер-событие, онлайн-ссылка, теги, рейтинг, вложения, история изменений, повторение, локация, является экземпляром, даты создания/обновления). ID-поля (специалист → пользователь, мастер → событие) оформлены как кликабельные ссылки. Статус и тип раскрашены.
### 2.5. Модерация жалоб
### 4.4. Жалобы (Reports)
**Эндпоинты:** `GET /api/complaints`, `GET /api/complaints/:id`, `PUT /api/complaints/:id`
Эндпоинты: `GET /v1/admin/reports`, `GET /v1/admin/reports/:id`, `PUT /v1/admin/reports/:id`
**Функциональность:**
- Список жалоб (ID, тип, подавший, объект жалобы, статус).
- Фильтрация: по статусу, типу.
- Детальный просмотр:
- Текст жалобы, прикреплённые файлы/ссылки.
- Информация о нарушителе/событии.
- Кнопки «Рассмотрено» и «Отклонить».
- Возможность перехода к блокировке пользователя/события прямо из карточки жалобы.
Функциональность:
- Список с серверной пагинацией и сортировкой.
- Первая колонка — иконка для перехода на детальную страницу.
- Резолвинг отправителя: если нет ника — показывается email (ссылка на профиль пользователя).
- Колонка «Тип» раскрашена (event — синий, calendar — зелёный, review — фиолетовый).
- Колонка «Цель» — кликабельная ссылка с названием (для событий) или ID.
- Быстрый просмотр в модальном окне: ID, отправитель (ссылка с ником/email), тип цели, цель (ссылка с названием для событий), причина, статус, дата создания, дата решения, кем решено (ссылка на админа с ником/email). В модалке кнопки «Рассмотрено» и «Отклонено» для жалоб в статусе pending.
- Детальная страница жалобы: все поля с возможностью принять решение (кнопки «Рассмотрено» и «Отклонено»).
### 2.6. Баг-трекер
### 4.5. Отзывы (Reviews)
**Эндпоинты:** `GET /api/bugs`, `POST /api/bugs`, `PUT /api/bugs/:id`, `DELETE /api/bugs/:id`
Эндпоинты: `GET /v1/admin/reviews`, `GET /v1/admin/reviews/:id`, `PUT /v1/admin/reviews/:id`, `PATCH /v1/admin/reviews`
**Функциональность:**
- Список багов (ID, заголовок, статус, приоритет, назначенный, дата создания).
- Детальный просмотр: описание, шаги воспроизведения, скриншоты.
- Смена статуса, назначение ответственного из числа админов.
- Комментарии к багу (если поддержано API).
- Создание новых багов (только внутренние, не от пользователей).
Функциональность:
- Список с серверной пагинацией и сортировкой.
- Возможность выбора нескольких отзывов для массового изменения статуса (скрыть, показать, удалить) с обязательной причиной при скрытии/удалении.
- Первая колонка — иконка для перехода на детальную страницу.
- Резолвинг пользователя (никнейм → email → ID) и цели (название события).
- Оценка отображается звёздами.
- Статусы раскрашены (visible — зелёный, hidden — оранжевый, deleted — красный).
- Тип цели раскрашен (event — синий, calendar — зелёный).
- Модальное окно редактирования: оценка, комментарий, статус, причина (обязательна при скрытии/удалении).
- Детальная страница отзыва: все поля, кнопки изменения статуса с причиной.
---
### 4.6. Бан-слова (Banned Words)
## 3. Интеграция с API и аутентификация
Эндпоинты: `GET /v1/admin/banned-words`, `POST /v1/admin/banned-words`, `DELETE /v1/admin/banned-words/:word`
- JWT-аутентификация, аналогичная основному приложению.
- Эндпоинт входа: `/api/auth/login` (или `/api/admin/login`).
- Токен сохраняется в `localStorage` и добавляется ко всем запросам (`Authorization: Bearer ...`).
- При получении HTTP 401 — редирект на страницу входа.
- Для дашборда использовать специальные эндпоинты `/api/stats/*`; если их нет — собирать статистику через заголовок `X-Total-Count` и множественные запросы (временно).
Функциональность:
- Список с серверной пагинацией, сортировкой и поиском.
- Резолвинг поля «Кем добавлено» (ссылка на администратора с ником/email).
- Дата добавления отформатирована.
- Форма добавления нового слова и кнопка удаления с подтверждением.
---
### 4.7. Тикеты (баг-трекер)
## 4. Требования к UX/UI
Эндпоинты: `GET /v1/admin/tickets`, `GET /v1/admin/tickets/stats`, `GET /v1/admin/tickets/:id`, `PUT /v1/admin/tickets/:id`, `DELETE /v1/admin/tickets/:id`
- Material Design (React-Admin + MUI).
- Адаптивная верстка (планшеты).
- Пагинация (серверная предпочтительна, клиентская допустима для малых объемов).
- Сортировка по любому полю.
- Поиск с debounce 300 мс.
- Подтверждение деструктивных действий (удаление, блокировка).
- Уведомления об успехе/ошибке через Snackbar.
- Тёмная тема (опционально, переключатель).
Функциональность:
- Статистика вверху: открыто, в работе, решено, закрыто.
- Список с серверной пагинацией и сортировкой.
- Первая колонка — иконка для перехода на детальную страницу.
- Резолвинг назначенного администратора (ссылка с ником/email).
- Статусы раскрашены (open — красный, in_progress — синий, resolved — зелёный, closed — серый).
- Детальная страница: все поля тикета, отправитель как ссылка на пользователя, назначенный администратор как ссылка, форма изменения статуса с выбором администратора из списка (email — ник).
- Кнопка удаления с подтверждением.
---
### 4.8. Подписки (Subscriptions)
## 5. Технологический стек
Эндпоинты: `GET /v1/admin/subscriptions`, `GET /v1/admin/subscriptions/:id`, `PUT /v1/admin/subscriptions/:id`, `DELETE /v1/admin/subscriptions/:id`
- **Язык:** TypeScript
- **Сборщик:** Vite
- **UI-фреймворк:** React-Admin v5 + Material UI v5
- **Провайдер данных:** `ra-data-simple-rest` с кастомизацией для JWT
- **Аутентификация:** кастомный `authProvider`
- **Контейнеризация:** Docker, Nginx
Функциональность:
- Список с серверной пагинацией и сортировкой.
- Резолвинг пользователя (никнейм → email → ID) со ссылкой.
- Планы раскрашены (trial — голубой, monthly — синий, quarterly — зелёный, biannual — фиолетовый, annual — оранжевый).
- Статусы раскрашены (active — зелёный, expired — оранжевый, cancelled — красный).
- Даты отформатированы.
- Модальное окно редактирования: план, статус, пробный период, дата окончания (DatePicker). Данные подгружаются с сервера.
---
### 4.9. Управление администраторами
## 6. Этапы реализации (MVP)
Эндпоинты: `GET /v1/admin/admins`, `GET /v1/admin/admins/:id`, `POST /v1/admin/admins`, `PUT /v1/admin/admins/:id`, `DELETE /v1/admin/admins/:id`
1. **Неделя 1:** Инициализация проекта (Vite + React-Admin), простой dataProvider, страница входа.
2. **Неделя 2:** Модуль пользователей (список, детали, блокировка).
3. **Неделя 3:** Модуль событий (список, модерация).
4. **Неделя 4:** Модули жалоб, баг-трекера, календарей (базовый просмотр/изменение статусов).
5. **Неделя 5:** Дашборд (если API готово), финальные штрихи, тестирование, деплой в staging.
Функциональность:
- Список с серверной пагинацией и сортировкой.
- Первая колонка — иконка для перехода на детальную страницу.
- Роли раскрашены (superadmin — красный, admin — синий, moderator — фиолетовый, support — голубой).
- Статусы раскрашены (active — зелёный, blocked — красный).
- Модальное окно создания: email, пароль, роль.
- Модальное окно редактирования: ник, email, роль, статус, часовой пояс (выпадающий список), язык (русский/английский), телефон.
- Кнопки «Редактировать» и «Удалить» с иконками.
- Детальная страница администратора: все поля с раскрашенными ролью и статусом.
---
### 4.10. Аудит (Audit)
## 7. Что потребуется от бэкенда (EventHubBack)
Эндпоинт: `GET /v1/admin/audit`
### 7.1 Роли и права доступа
Функциональность:
- Список с серверной пагинацией и сортировкой.
- Резолвинг администратора (ссылка с ником/email).
- Роль раскрашена.
- Действие раскрашено (create, update, delete, freeze, unfreeze, block, unblock, hide, unhide, login, logout и др.).
- Тип сущности раскрашен (user, event, calendar, review, report, ticket, subscription, admin).
- Наименование сущности: для user — ник/email (ссылка), для event — название (ссылка), для review — ссылка на отзыв, для остальных — ID.
- Фильтры: администратор (выпадающий список с поиском), действие (выпадающий список уникальных действий), диапазон дат.
- Дата отформатирована.
Описать три административные роли: `superadmin`, `moderator`, `support`.
### 4.11. Профиль текущего администратора
В JWT-токене после аутентификации передавать поле `role` с одним из этих значений. Оставить поддержку `"role": "admin"` как синоним `superadmin` для обратной совместимости.
Эндпоинты: использует данные из `useAuthStore().user`, редактирование через `PUT /v1/admin/admins/:id`
Middleware авторизации для админских эндпоинтов (`/admin/*` или порты 8445/8446) должен:
- Проверять валидность JWT.
- Извлекать роль.
- Сопоставлять с требуемыми правами для каждого действия.
Функциональность:
- Просмотр всех полей профиля: email, ник, роль, статус, часовой пояс, язык, телефон, аватар URL, настройки (JSON), последний вход.
- Пустые значения заменены на прочерк, дата отформатирована.
- Кнопка «Редактировать» доступна только для superadmin. При редактировании можно изменить ник, часовой пояс, язык, телефон, URL аватара, настройки (с валидацией JSON).
- Доступен всем ролям, страница открывается из виджета профиля в боковом меню.
Эндпоинт получения текущей роли:
- `GET /admin/me` (или `GET /api/auth/me`) — возвращает `{ id, username, role, permissions }`.
## 5. Real-time уведомления (WebSocket)
Эндпоинты управления ролями (только для `superadmin`):
- `GET /admin/admins` — список администраторов.
- `PUT /admin/admins/:id` — изменить роль.
- `POST /admin/admins` — пригласить нового администратора.
Эндпоинт: `wss://<домен>/admin/ws?token=<jwt>`
Логирование действий (аудит):
- Таблица `admin_audit` (admin_id, username, роль, действие, тип объекта, ID объекта, timestamp, IP, причина).
- Эндпоинт `GET /admin/audit` с фильтрами (доступен только `superadmin`).
Функциональность:
- При входе устанавливается WebSocket-соединение.
- Подписка на каналы `reports` и `tickets`.
- При получении сообщения `{ type: "report_created" }` или `{ type: "ticket_created" }` показывается уведомление со ссылкой на соответствующую страницу.
- Автоматическое переподключение при разрыве соединения.
- Защита от дубликатов по `timestamp`.
При блокировке пользователя / отклонении события обязательно принимать поле `reason` в теле запроса и сохранять в БД.
## 6. Интерфейс
Разграничение прав на уровне API:
- `support`: read-only пользователи и события; может обновлять статусы жалоб и багов, создавать баги.
- `moderator`: всё, кроме управления админами и просмотра аудита.
- `superadmin`: полный доступ.
- Боковое меню (сайдбар) с пунктами, доступными в соответствии с ролью.
- В нижней части сайдбара — виджет профиля текущего администратора с аватаром и именем (ник или email). При клике открывается меню «Мой профиль» и «Выйти». Кнопка сворачивания сайдбара находится в этой же панели.
- Верхняя панель содержит моки оперативной статистики (онлайн, заказов сегодня, тикетов) — в будущем будут заменены на реальные данные.
- Все даты в интерфейсе русифицированы (dayjs с русской локалью, Ant Design ConfigProvider с русской локалью).
- Единая нормализация данных: пустые значения (`null`, `undefined`, `"undefined"`, `"-"`) заменяются на прочерк, даты приводятся к читаемому формату. Нормализация применяется централизованно в хуках списков; для форм редактирования используются сырые данные.
- Все таблицы имеют серверную пагинацию и сортировку через заголовок `X-Total-Count`.
Ответ при недостаточности прав: `403 Forbidden`, тело:
```json
{ "error": "insufficient_permissions", "message": "Требуется роль moderator или выше" }
## 7.2 Статистика для дашборда с учётом ролей
## 7. Развёртывание
| Роль | Предоставляемые метрики |
|------|--------------------------|
| `superadmin` | Системные метрики (все пользователи, события, жалобы, баги за период, графики регистраций/событий по дням, активность администраторов). |
| `moderator` | Собственные обработанные жалобы/события (количество, статусы, время реакции), общая статистика по модерации. |
| `support` | Количество открытых багов и жалоб, назначенных на текущего сотрудника, персональные задачи. |
Эндпоинт `GET /api/stats` должен возвращать JSON с секциями, доступными согласно роли вызывающего.
- Production-сборка: `npm run build` → папка `dist/`.
- Docker-образ на основе Nginx Alpine.
- Контейнер подключается к сети `eventhub_network`.
- Traefik маршрутизирует домен `admin-ui.eventhub.local` на контейнер.
- Nginx внутри контейнера раздаёт статику и проксирует API-запросы (`/v1/``http://eventhub:8445`, `/admin/ws``http://eventhub:8446`), что позволяет избежать проблем с CORS и самоподписанными сертификатами.
- WebSocket также проксируется через Nginx.
- Makefile автоматизирует установку, сборку, запуск и очистку проекта.