120 lines
9.3 KiB
Markdown
120 lines
9.3 KiB
Markdown
# Frontend
|
||
|
||
SPA на **React 19 + Vite + TypeScript**. Общается с бэком по REST (JWT Bearer) и получает
|
||
живые обновления по SignalR. Типы API генерируются из OpenAPI-схемы бэкенда.
|
||
|
||
> **Раздача из единого контейнера.** В проде собранный фронт (`dist/`) кладётся в `wwwroot`
|
||
> ASP.NET Core и раздаётся тем же приложением (SPA-fallback на `index.html`). Фронт и бек — один
|
||
> origin, база API — относительный `/api`, SignalR — `/hubs/panel`. В dev Vite-сервер проксирует
|
||
> `/api` и `/hubs` на бэкенд. Детали упаковки — [architecture.md](architecture.md#развёртывание-единый-контейнер-приложения).
|
||
|
||
## Стек
|
||
|
||
| Задача | Выбор |
|
||
| ----------------- | --------------------------------------- |
|
||
| Сборка/dev | Vite |
|
||
| Язык | TypeScript (strict) |
|
||
| Данные с сервера | TanStack Query |
|
||
| Роутинг | TanStack Router (типобезопасный) |
|
||
| UI-компоненты | shadcn/ui + Tailwind CSS v4 |
|
||
| Иконки | lucide-react |
|
||
| Клиентский стейт | Zustand (auth, тема) |
|
||
| Формы | react-hook-form + zod |
|
||
| Realtime | @microsoft/signalr |
|
||
| Графики | Recharts |
|
||
| QR-коды | qrcode.react |
|
||
| Типы API | openapi-typescript / orval (codegen) |
|
||
| i18n | react-i18next (RU + EN) |
|
||
| Пакетный менеджер | pnpm |
|
||
|
||
## Структура
|
||
|
||
```
|
||
frontend/
|
||
src/
|
||
app/ # провайдеры (Query, Router, Auth, Theme), корневой layout
|
||
routes/ # маршруты TanStack Router (login, dashboard, configs, instructions, admin/*)
|
||
features/
|
||
auth/ # формы, хуки useLogin/useRegister, стор авторизации
|
||
configs/ # список/создание/редактирование/детали конфигов, QR, подписка
|
||
instructions/ # страница инструкций + каталог приложений по ОС
|
||
nodes/ # (admin) управление нодами
|
||
apps/ # (admin) CRUD каталога приложений
|
||
admin/ # пользователи, роли, аудит, статистика
|
||
theme/ # провайдер темы (light/dark/system) + переключатель
|
||
shared/
|
||
api/ # http-клиент (fetch + JWT/refresh), сгенерированные типы, query-хуки
|
||
realtime/ # инициализация SignalR, подписки → инвалидация Query-кэша
|
||
ui/ # обёртки над shadcn/ui, общие компоненты
|
||
lib/ # утилиты, форматирование (байты, даты)
|
||
config/ # env, константы
|
||
styles/ # tailwind, темы
|
||
index.html
|
||
vite.config.ts
|
||
package.json
|
||
```
|
||
|
||
## Дизайн / UX
|
||
|
||
- **Тема оформления**: светлая и тёмная (переключатель в шапке; вариант «системная»). Реализация —
|
||
Tailwind `dark` (класс на `html`) + shadcn/ui; выбор сохраняется (localStorage).
|
||
- **Современный и чистый вид**: shadcn/ui + Tailwind, адаптивность, аккуратная типографика.
|
||
- **Дашборд пользователя**: карточки конфигов (протокол, локация, трафик прогресс-баром, срок, статус),
|
||
быстрые действия (копировать ссылку, показать QR, перевыпустить, отозвать) + карточка «Общая подписка»
|
||
(агрегированная ссылка/QR со всеми конфигами). Для неактивированного — экран «запросить активацию».
|
||
- **Создание конфига**: выбор локации/inbound (по `DisplayName`) + метка + лимит устройств →
|
||
мгновенная выдача ссылки + QR + ссылка на страницу инструкций.
|
||
- **Страница инструкций** (`/instructions`): общие шаги «как импортировать ссылку/QR» + каталог
|
||
приложений (`GET /api/apps`), **сгруппированный по ОС**; клик по приложению открывает ссылку на
|
||
скачивание. Данные ведёт админ (каталог `ClientApp`).
|
||
- **Редактирование конфига**: изменить метку и лимит устройств.
|
||
- **Настройки аккаунта**: смена пароля, привязка/отвязка Telegram, **удаление аккаунта** (с подтверждением).
|
||
- **Админка**: таблицы (TanStack Table) с пагинацией/фильтрами для нод, пользователей, конфигов, ролей,
|
||
каталога приложений, журнала аудита; очередь запросов активации; графики трафика (Recharts).
|
||
Блокировка пользователя — с подтверждением (гасит VPN). Управление приложениями (название, ссылка, ОС, вкл/выкл).
|
||
- **Состояния**: скелетоны при загрузке, аккуратные пустые состояния и toasts на ошибки/успех.
|
||
|
||
## Работа с API
|
||
|
||
- HTTP-клиент оборачивает `fetch`: подставляет access-token, при 401 — прозрачно обновляет через
|
||
refresh-cookie и повторяет запрос; при неуспехе — разлогин.
|
||
- Все запросы/мутации — через TanStack Query (ключи по фичам, инвалидация после мутаций).
|
||
- Типы ответов/запросов — из codegen по OpenAPI (никакого ручного дублирования DTO).
|
||
|
||
## Авторизация на клиенте
|
||
|
||
- **Access-token** — в памяти (не в localStorage), кладётся в `Authorization: Bearer`.
|
||
- **Refresh-token** — httpOnly Secure cookie (JS не читает), ротация на сервере.
|
||
- Стор авторизации (Zustand) хранит профиль/роли/`isActivated`; guard-маршруты по роли (`admin` vs обычный)
|
||
и по активации (неактивированного ведём на экран «запросить активацию»).
|
||
|
||
- **Вход — по username** (email не используется). «Забыли пароль?» ведёт: при привязанном
|
||
Telegram — восстановление через бота; иначе — подсказка обратиться к админу.
|
||
- **Баннер привязки Telegram**: пока Telegram не привязан, показываем настойчивый, но не блокирующий
|
||
баннер/напоминание — это единственный self-service способ восстановить доступ. Настройки: смена пароля.
|
||
|
||
### Вход и привязка через Telegram
|
||
- **«Войти через Telegram»**: `POST /api/auth/telegram/login-request` → показать deep-link/QR на
|
||
бота, затем ждать подтверждения (поллинг `GET …/login-request/{id}` или событие SignalR). При
|
||
`Approved` — сохранить access, refresh уже в cookie, редирект в панель.
|
||
- **«Привязать Telegram»** (в настройках, для вошедшего): `POST /api/auth/telegram/link-token` →
|
||
показать deep-link/QR; статус привязки обновить по факту (поллинг/SignalR). Отвязка — `unlink`.
|
||
- QR для deep-link — `qrcode.react`.
|
||
|
||
## Realtime
|
||
|
||
- Одно SignalR-подключение к `/hubs/panel` с JWT; реконнект с бэкоффом.
|
||
- Обработчики событий (`configTrafficUpdated`, `configStatusChanged`, `nodeStatusChanged`) точечно
|
||
обновляют/инвалидируют кэш TanStack Query — UI обновляется без перезагрузки.
|
||
|
||
## Скрипты (ожидаемые)
|
||
|
||
```bash
|
||
pnpm dev # dev-сервер Vite
|
||
pnpm build # прод-сборка
|
||
pnpm preview # предпросмотр сборки
|
||
pnpm lint # ESLint
|
||
pnpm typecheck # tsc --noEmit
|
||
pnpm gen:api # генерация типов из OpenAPI-схемы бэкенда
|
||
```
|