No description
  • TypeScript 85.5%
  • CSS 14%
  • HTML 0.4%
  • Dockerfile 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Anton Babichev 0653beb277
All checks were successful
frontend-ci / build (push) Successful in 1m4s
Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	README.md
2026-10-16 23:17:54 +03:00
.github feat: implement Lab 3 fishing application interface 2026-10-16 19:52:24 +03:00
src fix: add dark map tiles and improve index badge readability 2026-10-16 22:44:45 +03:00
.dockerignore feat: adopt VKUI design system across frontend 2026-10-16 21:19:45 +03:00
.gitignore feat: implement Lab 3 fishing application interface 2026-10-16 19:52:24 +03:00
.prettierrc.json feat: implement Lab 3 fishing application interface 2026-10-16 19:52:24 +03:00
Dockerfile feat: implement Lab 3 fishing application interface 2026-10-16 19:52:24 +03:00
index.html Split screens into typed TSX components and add theme switching 2026-10-16 22:15:08 +03:00
nginx.conf feat: implement Lab 3 fishing application interface 2026-10-16 19:52:24 +03:00
package-lock.json Split screens into typed TSX components and add theme switching 2026-10-16 22:15:08 +03:00
package.json Split screens into typed TSX components and add theme switching 2026-10-16 22:15:08 +03:00
README.md Merge remote-tracking branch 'origin/develop' 2026-10-16 23:17:54 +03:00
tsconfig.json Split screens into typed TSX components and add theme switching 2026-10-16 22:15:08 +03:00
vite.config.ts Split screens into typed TSX components and add theme switching 2026-10-16 22:15:08 +03:00

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-чата.