web-react/: SPA Vite+React+TS, nginx раздаёт статику и проксирует /api на api:8000 по локалке. docker-compose: web(Flet)->web-react на :80. transfer_crud.backup_restore: чистим содержимое data/radar вместо rmtree точки монтирования (EBUSY).
web-react — фронтенд на React (Vite + TypeScript)
Замена Flet-интерфейса (../web). Обычный SPA: грузится в браузер один раз и работает
локально, обращаясь к API по HTTP. Нет WebSocket и серверного UI-стейта — это убирает
зависания, которые были у Flet (он рендерил UI на сервере и держал WS на каждого юзера).
Flet-сервис web намеренно оставлен в docker-compose.yml как запасной. Этот новый
фронтенд публикуется на порту 3000.
Архитектура
Браузер ──▶ [ nginx :80 (контейнер web-react) ]
├── / → статика React (SPA, fallback на index.html)
└── /api/* → proxy_pass http://api:8000/ (включая SVG-диаграммы)
API-контейнер доступен только внутри Docker-сети, поэтому браузер ходит к нему через
nginx-прокси на том же origin (/api/...). SVG-диаграмма тянется напрямую <img>/<a download>.
Разработка (локально)
# 1. Поднять API + БД (из корня репозитория)
docker compose up -d api postgres redis # postgres/redis — из docker-compose_db.yml
# 2. Dev-сервер фронтенда
cd web-react
npm install
npm run dev # http://localhost:5173, /api проксируется на http://localhost:8000
Адрес API для dev-прокси переопределяется переменной API_URL (см. vite.config.ts).
Сборка / прод
# из корня репозитория
docker compose up -d --build web-react # http://localhost:3000
Либо вручную: npm run build → статика в dist/, раздаётся nginx (см. Dockerfile, nginx.conf).
Структура
| Путь | Назначение |
|---|---|
src/api/client.ts |
все запросы к API (порт web/api_client.py) |
src/auth/ |
AuthContext — токен в localStorage + /users/me |
src/theme/ |
5 тем + слайдер масштаба через CSS-переменные |
src/components/ |
переиспользуемые компоненты (Button, TextField, SearchableDropdown, Layout, Modal, RadarBlock…) |
src/pages/ |
экраны: Login, Register, Home, TestList, Poll, MyTests, Response, Profile |
src/styles/global.css |
стили на CSS-переменных |
Маршруты
/login, /register, / (домашняя), /tests, /poll/:pollId, /my-tests,
/response/:responseId, /profile. Защищённые маршруты требуют токен (ProtectedRoute).