- TypeScript 85.5%
- CSS 14%
- HTML 0.4%
- Dockerfile 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
frontend-ci / build (push) Successful in 1m4s
# Conflicts: # README.md |
||
| .github | ||
| src | ||
| .dockerignore | ||
| .gitignore | ||
| .prettierrc.json | ||
| Dockerfile | ||
| index.html | ||
| nginx.conf | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vite.config.ts | ||
LigmaBa LLs Frontend — Lab 3 MVP
TypeScript + React 19 + Vite 8 + VKUI 8.4.2 + Leaflet. Клиент API проекта LigmaBa LLs,
«Находка для рыбака».
Продуктовые требования, пользовательские сценарии и контракты находятся в соседнем
репозитории ligmaba-docs.
Визуальный стандарт
Интерфейс использует VKUI и стандартные
светлую и тёмную темы vkCom. В корне приложения ConfigProvider задаёт
platform="vkcom", динамический colorScheme, locale="ru"; приложение
обёрнуто в AdaptivityProvider и AppRoot.
Кнопка луны/солнца в шапке работает на desktop и mobile. По умолчанию тема
светлая; выбор сохраняется в localStorage под ключом ligmaba.color-scheme.
Модальные окна через портал и все компоненты VKUI меняют тему вместе с
приложением. CSS color-scheme и браузерный meta theme-color обновляются.
Маркеры, рамки, контролы и подсказки Leaflet используют токены темы.
Светлая подложка — стандартные тайлы OpenStreetMap, тёмная —
Stadia Maps Alidade Smooth Dark
на данных OpenMapTiles/OpenStreetMap. Это настоящие тёмные тайлы, без CSS-фильтров.
При переключении темы заменяется только базовый слой Leaflet: положение, масштаб,
маркеры и выбранный водоём сохраняются. Атрибуция каждого источника видна на карте.
Для localhost и 127.0.0.1 ключ не нужен; для публикации на внешнем домене
Stadia Maps требует доменную авторизацию.
Используется оптимизированная сборка VKUI с CSS Modules. В vite.config.ts
импорты @vkontakte/vkui направлены на @vkontakte/vkui/dist/cssm,
в src/main.tsx подключён @vkontakte/vkui/dist/cssm/styles/themes.css.
Карта с Leaflet загружается отдельным чанком через React.lazy и Suspense.
Кнопки, поля, формы, вкладки, выбор сценария AI, карточки и общие состояния
собраны из компонентов библиотеки. Собственный CSS задаёт компоновку карты,
панелей и графиков, используя токены --vkui--; внутренние стили VKUI
не переопределяются. Leaflet сохраняет управление картой и маркерами.
Модальные формы размещаются через AppRootPortal и ModalCard,
уведомления используют Snackbar.
Подключение описано в официальной инструкции VKUI,
экраны и результаты проверок — в ligmaba-docs/VERIFICATION.md.
Структура интерфейса
App.tsx координирует состояние, авторизацию и сетевые запросы.
Представления вынесены в components/auth, discovery, layout и profile.
WaterDetail.tsx собирает вкладки из components/water и чат
из components/chat. AdminPanel.tsx использует редактор,
таблицу и карточку импорта из components/admin.
components/map/clusterAppearance.ts вычисляет палитру и описание состава группы.
Весь прикладной код использует .ts / .tsx с strict: true,
isolatedModules и verbatimModuleSyntax. Props, состояния, ссылки и события
типизированы. Общие модели находятся в src/types.ts; административные
и AI-модели — в src/types/admin.ts и src/types/ai.ts. src/api.ts
содержит api<T> с типизированными ответами и getError(unknown) для
ошибок из API и браузера. any, @ts-ignore и @ts-nocheck не используются.
styles.css импортирует 13 файлов styles/ с сохранением прежнего порядка:
base, layout, discovery, shared, map, water, chat, modals,
ai, admin, profile, responsive, overrides. Порядок сохраняет
приоритет адаптивных правил и заключительных переопределений.
Запуск
Нужны Node.js 22.12+ и работающий backend на http://localhost:8080.
npm ci
npm run dev
Открыть http://localhost:5173. Vite проксирует /api и /uploads на backend;
поэтому браузеру не нужны отдельные CORS-настройки. При необходимости базовый
адрес API задаётся VITE_API_BASE во время сборки (по умолчанию /api/v1).
Весь проект запускается из родительской папки командой docker compose up --build.
В production Nginx отдаёт сборку на порту 80 и проксирует API и фотографии в
backend:8080. Не запускайте production-контейнер отдельно от backend.
Обычная конфигурация использует DEMO_ENABLED=false: реальный OSM-каталог
Москвы и Московской области и прогноз Open-Meteo. Backend содержит снимок
от 15.10.2026 с 1617 именованными полигонами, дополненный четырьмя полными
пограничными объектами OSM API от 16.10.2026: всего 1621 водоём. Наполнение
каталога не зависит от доступности Overpass. Точки маркеров вычисляются
внутри водной поверхности с учётом островов; реки и неопределённые типы
не включены. Старые учебные объекты и прогнозы скрыты в live-режиме.
Детали сетевого обновления — в ligmaba-docs/deploy/README.md.
Реализованные сценарии
- Настоящая карта OpenStreetMap с перемещением, масштабированием, числовыми
маркерами индекса и группировкой близких объектов при небольшом масштабе.
Каталог запрашивается только для текущего
bbox, с отменой устаревших запросов. В открытой вкладке карта и сохранённые места обновляются раз в 60 секунд, чтобы показать индексы после фонового получения прогноза. Кластер показывает количество мест и мягкий линейный градиент их категорий: good/fair/low используют тона отдельных VKUI-маркеров, отсутствующий индекс — нейтральный серый. Доли цветов соответствуют числу объектов; состав раскрывается в подсказке. Средний индекс кластера не рассчитывается, серверная формула индекса сохраняется. Маркеры используют непрозрачную подложку темы под цветным оттенком, поэтому карта не просвечивает через число, в том числе в диапазоне 50–69. - Гостю доступны карта и список. Карточка, избранное, поиск, фильтры, геолокация и другие содержательные действия вызывают вход/регистрацию. После входа исходное действие продолжается.
- Поиск по названию, фильтры по типу, рыбе, диапазону индекса и радиусу. Геолокация запрашивается только явным нажатием; точку отсчёта можно выбрать вручную на карте. Координаты точки видны в фильтрах и помощнике.
- Карточка с вкладками «Обзор / Индекс / Погода / Чат»: текущий индекс, объяснение, вклад семи факторов, график на 24 часа, лучшее время, погодные показатели и почасовой прогноз. Время показывается в часовом поясе Москвы.
- Избранное хранится на сервере. Профиль показывает аккаунт и сохранённые места.
- Общий чат с опросом каждые 8 секунд, отправкой, удалением своих публикаций и жалобами на чужие. Отчёты об улове выделяются отдельными карточками.
- Форма улова: вид рыбы, количество, оценка клёва 1–5; вес, снасть, комментарий и фото необязательны. Фото JPEG/PNG/WebP до 5 МБ сначала загружается на backend через multipart, затем связывается с отчётом.
- «Рыбак AI» использует только кнопки: четыре намерения, радиус, выбор рыбы, явный выбор двух водоёмов для сравнения, до трёх рекомендаций с объяснением и переходом на карту. При пустом результате предлагает расширить радиус или сменить условия. Свободного LLM-ввода нет.
- Администратору доступны редактирование водоёмов и списков рыб, добавление, редактирование и удаление видов рыб, запуск/статус/история импорта OSM, рассмотрение жалоб, удаление публикаций, блокировка и разблокировка пользователей.
Отказоустойчивость и доступность
При недоступности API показана ошибка с повтором, при пустом каталоге — понятное состояние. Пока первоначальный импорт работает, каталог автоматически обновляется. Если не загружаются внешние тайлы, маркеры, управление картой и список остаются доступны; приложение явно сообщает об отсутствии подложки. Демонстрационный каталог и сохранённые погодные данные помечаются в интерфейсе и не выдаются за актуальный прогноз.
Bearer-сессия сохраняется в localStorage, проверяется через /me; выход отзывает
сессию на сервере через /auth/logout, а истёкшая
авторизация очищается при 401. Модальные окна поддерживают Escape и удержание
фокуса, интерактивные элементы имеют подписи, цвета индекса дублируются числами.
На узких экранах карта располагается над списком, навигация становится нижней,
а карточка водоёма открывается отдельной панелью.
Проверки
npm run format:check
npm run typecheck
npm run build
typecheck выполняет tsc --noEmit; build запускает
tsc --noEmit && vite build, поэтому ошибки типов останавливают сборку.
CI выполняет чистую установку npm ci, проверку форматирования и production-сборку
на Node.js 22. Библиотеки зафиксированы в package-lock.json.
Для ручной проверки: открыть карту гостем → выбрать водоём → зарегистрироваться →
проверить четыре вкладки → сохранить место → отправить сообщение и отчёт с фото →
открыть избранное → получить рекомендации и сравнить две точки → выйти/войти →
проверить админку под отдельной ролью Admin. Сценарий защиты и результаты API-проверок
описаны в ligmaba-docs.
Ограничения MVP
Тайлы карты требуют доступа к OpenStreetMap и Stadia Maps. Клиент отображает внутренние точки водной поверхности, без полигонов и речных сегментов. Чат использует REST polling. Сравнение выбирает водоёмы текущей видимой карты. Приложение не содержит подписок, платежей или свободного текстового AI-чата.