Kotlin Multiplatform Android-приложение каталога товаров и отдельный BFF/backend на Node.js + TypeScript.
Проект больше не работает напрямую с DummyJSON: мобильный клиент ходит в собственный backend, который:
- синхронизирует source-каталог из
DummyJSON; - хранит данные в
PostgreSQL; - отдает локализованный каталог и карточку товара;
- конвертирует цены в выбранную валюту;
- возвращает отзывы для страницы товара.
app— Android host-модуль:Application,MainActivity, Android-specific wiring.feature— shared UI и логика каталога: экран списка, карточка товара,ViewModel, repository, mappers.model— общие domain-модели и контракты.backend— BFF-сервис наFastify + PostgreSQL.docs— скриншоты и вспомогательные материалы.
- каталог товаров с загрузкой с backend;
- поиск с
debounce 300ms; - фильтрация по категориям;
- сортировка по цене и рейтингу;
- серверная пагинация с UX в формате
load more; - переключение языка интерфейса и языка данных каталога;
- переключение валюты с пересчетом цены на backend;
- карточка товара с кнопкой назад;
- отдельный экран товара с ценой, рейтингом, описанием и отзывами;
- состояния
loading,empty,error,retry; - загрузка изображений через
Coil 3.
- полная синхронизация source-каталога из
DummyJSONпри каждом старте; - хранение source-данных, переводов, отзывов и валютных курсов в
PostgreSQL; - демо-локализация названий, описаний, категорий и отзывов через curated static translations;
- серверные поиск, фильтрация, сортировка и пагинация;
- конвертация цен по курсам
Frankfurter; Swagger UIиhealthendpoint;- unit- и integration-тесты на
Jest.
Зависимости между мобильными модулями:
app -> feature -> model
Почему структура такая:
appотвечает только за Android host-слой;featureсодержит всю конкретную фичу каталога;modelхранит переиспользуемые domain-сущности и repository-контракты.
Поток данных выглядит так:
Android app -> backend -> DummyJSON
-> Frankfurter
-> PostgreSQL
Роли backend:
- скрывает внешние API от мобильного клиента;
- отдает один стабильный контракт для приложения;
- хранит локализованные данные и отзывы;
- конвертирует цены на сервере;
- берет на себя серверную пагинацию и фильтрацию.
enrudefresitpttrukzh
USDEURRUBGBPUAHTRYCNYJPYCADCHF
Рекомендуемый сценарий для локального запуска:
- Скопировать root env-файл:
Copy-Item .env.example .env- Поднять
PostgreSQLи backend:
docker compose up -d --build postgres backend- Дождаться, пока backend станет доступен:
http://localhost:8080/health
- Запустить Android-приложение.
backend на старте выполняет полную синхронизацию каталога из DummyJSON, поэтому первый запуск может занять немного больше времени, чем обычный hot restart.
- Открыть корень проекта
internassignment03. - Дождаться
Gradle Sync. - Убедиться, что выбран JDK из Android Studio или любой совместимый
JDK 17+. - Поднять backend.
- Запустить конфигурацию
appна эмуляторе или устройстве.
Сборка debug APK:
$env:JAVA_HOME='D:\android-studio\jbr'
$env:Path="$env:JAVA_HOME\bin;$env:Path"
.\gradlew.bat :app:assembleDebugСборка release APK:
$env:JAVA_HOME='D:\android-studio\jbr'
$env:Path="$env:JAVA_HOME\bin;$env:Path"
.\gradlew.bat :app:assembleReleaseПо умолчанию Android-приложение собирается с:
http://10.0.2.2:8080/
Это подходит для Android Emulator, когда backend запущен на хост-машине.
Если приложение запускается на физическом устройстве, базовый URL можно переопределить через Gradle property:
$env:JAVA_HOME='D:\android-studio\jbr'
$env:Path="$env:JAVA_HOME\bin;$env:Path"
.\gradlew.bat :app:assembleDebug -Pbackend.baseUrl=http://<LAN-IP>:8080/Дополнительные документы по проекту:
- backend/README.md
- docs/product-details-feature-spec.md — спецификация фичи detail-экрана товара и backend-контракта для него
- docs/testing-spec.md — подробная QA-спецификация
Коротко:
- Docker Compose использует root
.env; - backend слушает
http://localhost:8080; - Swagger доступен на
http://localhost:8080/docs; PostgreSQLпубликуется на хосте какlocalhost:5433.
Прогон shared/mobile-тестов:
$env:GRADLE_USER_HOME='D:\internassignment03\.gradle-user-mobile-tests'
$env:JAVA_HOME='D:\android-studio\jbr'
$env:Path="$env:JAVA_HOME\bin;$env:Path"
.\gradlew.bat :feature:allTests --no-daemonПрогон detekt:
$env:JAVA_HOME='D:\android-studio\jbr'
$env:Path="$env:JAVA_HOME\bin;$env:Path"
.\gradlew.bat :app:detekt :feature:detekt :model:detektИз папки backend:
npm run test:unit
npm run test:integration
npm run test:allIntegration-тесты backend ожидают доступную PostgreSQL-базу. По умолчанию используется:
postgresql://catalog:catalog@127.0.0.1:5433/catalog
При необходимости можно переопределить TEST_DATABASE_URL.
- Kotlin Multiplatform
- Jetpack Compose
- Koin
- Kotlinx Coroutines
- Kotlinx Serialization
- Ktor Client
- Coil 3
- Detekt
- Node.js 20+
- TypeScript
- Fastify
- PostgreSQL
- Jest
- Docker Compose
- DummyJSON
- Frankfurter
- Codex






