Розроблення мобільного додатку для недвижимості (PropTech)
Додаток для недвижимості — це агрегація даних об про об'єкти, карта з пошуком в області видимості, фільтри з десятками параметрів, віртуальні тури та форма зв'язку з забудовником або агентом. Технічно найболючіша частина — не UI, а робота з великими обсягами об'єктів на карті та синхронізація стану фільтрів з пошуковими запитами.
Карта як основний UI
Більшість користувачів PropTech-додатків шукають по карті, а не по списку. Значить, карта — перший екран, а не вкладка. Це впливає на архітектуру: неможливо завантажувати всі об'єкти за один запит — їх можуть бути тисячи.
Viewport-based loading — завантажуємо тільки об'єкти в поточній області видимості карти:
GET /properties?bounds=55.70,37.55,55.80,37.70&filters=...
bounds — прямокутник поточного вʻюпорту. При скролі/зуме — новий запит. Дебаунс 500 мс на события onCameraIdle (не onCameraMove) — запитуємо тільки після зупинки камери.
PostGIS на сервері:
SELECT id, lat, lon, price, property_type
FROM properties
WHERE geom && ST_MakeEnvelope(:west, :south, :east, :north, 4326)
AND price BETWEEN :min_price AND :max_price
ORDER BY created_at DESC
LIMIT 200;
Кластеризація. При великій кількості об'єктів в області та низькому зуме — кластери з числом всередину. При зуме > 14 — окремені маркери. На iOS — GMUMarkerClusterer, на Android — ClusterManager, у Flutter — flutter_map_marker_cluster. Пересчитуємо на кожній onCameraIdle.
Фільтри з десятками параметрів
Фільтр недвижимості — один із найскладніших UI-компонентів у мобільній розробці. Кількість кімнат, тип житла, ціновий діапазон (Range Slider), площа, поверх, рік постройки, тип договору, терміновість. Плюс специфічні для країни поля.
Головна проблема: зберігання стану фільтра. Не в локальних змінних екрана — користувач йде на карточку об'єкту та повертається. Стан фільтра повинен жити в ViewModel / StateHolder та переживати рекомпозицію.
На Android — data class FilterState в ViewModel, StateFlow<FilterState> в UI. При зміні будь-якого поля фільтра — copy() + оновлення Flow. Дебаунс 300 мс перед запитом до API — не відправляємо запит при кожному сдвізі слайдера.
filterState
.debounce(300)
.flatMapLatest { filters -> propertyRepository.search(filters) }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
На iOS — @Published var filterState: FilterState в ObservableObject, Combine.debounce(for:scheduler:).
Збереження пошуку. Користувач зберігає поточний набір фільтрів як «пошуковий агент» — отримує push-сповіщення при появі нових підходящих об'єктів. FCM + серверний cron-job, який раз на годину прогоняє збережені запити.
Карточка об'єкту
Фотогалерея з плавним scroll-driven переходом з карти. На iOS — кастомний UIViewControllerTransitioningDelegate для hero-анімації маркера → фото. На Android — Shared Element Transition з ActivityOptionsCompat.makeSceneTransitionAnimation.
Віртуальний тур. 360°-фото через VR Panorama або Matterport embed. На iOS — SceneKit + сферична геометрія для рендеру equirectangular-панорами, або WKWebView з Matterport iframe. На Android — GoogleVR SDK (застарів, але ще працює) або те ж рішення через WebView. Нативний рендер продуктивніше, WebView простіше та підтримує більше форматів.
Іпотечний калькулятор. Проста математика на клієнті — сума, ставка, строк → ежемесячний платіж. Формула аннуітетного платежу:
let monthlyRate = annualRate / 12 / 100
let n = Double(months)
let payment = principal * monthlyRate * pow(1 + monthlyRate, n) / (pow(1 + monthlyRate, n) - 1)
Ніяких API не потрібно, працює офлайн.
Інтеграція з джерелами даних
Об'єкти недвижимості частіше всього беруться з кількох джерел: парсинг Циан/Авіто (сіра зона з точки зору ToS), власна CRM забудовника, CREA/IDX-фіди (для західного ринку), ручне наповнення через CMS.
Для агрегації з зовнішніх порталів — серверна синхронізація через API (якщо доступний) або ETL-пайплайн. В мобільному додатку це не видно — просто нормалізовані дані з власного API.
Для забудовника з власною CRM — інтеграція через REST API з маппінгом полів. Синхронізація по webhook (CRM нотифікує при зміні об'єкту) або по розпису раз в 15 хвилин.
Специфіка iOS vs Android для PropTech
На iOS з iOS 16 з'явився MapKit з MKMapView та SwiftUI integration. Для PropTech з тисячами маркерів — MKMapView на UIKit з dequeueReusableAnnotationView швидше, ніж SwiftUI Map. Кластеризація через MKAnnotationView + MKClusterAnnotation — вбудована в MapKit, не потрібна стороння бібліотека.
На Android — Google Maps SDK з Jetpack Compose через GoogleMap composable із maps-compose — добре інтегрується з Compose-архітектурою, підтримує всі маркери та полілінії.
Процес роботи
Аудит вимог: джерела даних, фільтри, обов'язкові інтеграції (CRM, іпотечний брокер, нотаріуси). Проектування схеми даних та API. Розроблення карти з viewport-loading та кластеризацією. Розроблення системи фільтрів. Карточка об'єкту з галереєю та віртуальним туром. Система пошукових агентів. Інтеграція з джерелами даних. Тестування на навантаження (тисячи маркерів, складні фільтри).
Тривалість: три-шість місяців залежно від кількості платформ, складності фільтрів та набору інтеграцій.







