Перейти до змісту

Driver App — мобільний застосунок водія

Офлайн-перший мобільний додаток для водіїв Fleet-модуля. Водій приймає завдання, веде рейс, фіксує паливо / одометр / статуси, синхронізується з backend при появі мережі.


1. Призначення

  • Прийом завдань (Waybill) від диспетчера
  • 5-етапний потік доставки: accept → loading → in_transit → unloading → done
  • Фіксація одометра на початку/кінці рейсу
  • Заправки з додаванням фото чеку
  • Офлайн-робота у зоні без 4G (поширено у перевезеннях між містами)
  • Синхронізація при появі мережі (WatermelonDB)

2. Tech Stack

  • React Native (Expo SDK 51, managed → EAS Build)
  • WatermelonDB 0.28 — офлайн-перша локальна БД (SQLite / JSI)
  • @nozbe/with-observables — реактивні компоненти
  • React Navigation 6 — bottom tabs + native stack
  • expo-secure-store — JWT tokens
  • @react-native-community/netinfo — моніторинг мережі
  • Axios + JWT refresh interceptor
  • i18next (en / ua)

3. Backend API

backend/mobile_api/ — окремий Django app для мобільних клієнтів:

Endpoint Метод Опис
/api/v1/mobile/sync/pull GET WatermelonDB pull — зміни з last_pulled_at
/api/v1/mobile/sync/push POST Push локальних змін (одометр, паливо, статуси)
/api/v1/mobile/me/ GET Профіль водія
/api/v1/mobile/delivery-action/ POST 5-step delivery: accept → done

Sync працює за протоколом WatermelonDB: пуш — у тому ж форматі, що synchronize() очікує.


4. Екрани

src/screens/
├── LoginScreen         # Вхід (username + password)
├── DashboardScreen     # Поточний статус (waybill + next task)
├── WaybillsScreen      # Список подорожніх листів
├── WaybillDetailScreen # Деталь ПЛ + дії (accept, start, finish)
├── OrdersScreen        # Замовлення у межах ПЛ
├── OrderDetailScreen   # Деталь замовлення + 5 кроків доставки
└── ProfileScreen       # Профіль водія

5. 5-step delivery workflow

accept     → Водій прийняв замовлення
loading    → Завантаження на адресі відправника
in_transit → У дорозі (запускається GPS-трекінг)
unloading  → Розвантаження у клієнта
done       → Завершено (фото / підпис / акт)

Кожен етап — POST до /api/v1/mobile/delivery-action/ з payload (action, timestamp, gps_coords, photo_urls).


6. Офлайн-робота

WatermelonDB зберігає: - waybills — подорожні листи (pulled at login) - orders — замовлення в межах ПЛ - vehicles — ТЗ, прив'язаний до водія - routes — маршрути

Локальні зміни накопичуються у _changes таблицях. При появі мережі: 1. Pull оновлень з сервера 2. Resolve conflicts (server wins) 3. Push локальних змін 4. Оновлення last_pulled_at


7. Інтеграції

  • GPS Wialon — backend tracking паралельно (не через застосунок, якщо ТЗ має Wialon-терміна). Див. gps-wialon
  • Push notifications (FCM) — сповіщення про нове замовлення
  • Чат з диспетчером — планується інтеграція з DOP Chat

8. Запуск

cd c:\eswf\mobile
npm install
npx expo prebuild            # генерує native проекти
npx expo run:android         # або run:ios

Важливо: WatermelonDB потребує expo prebuild — Expo Go не підтримується.

Android emulator — API URL

У src/api/client.ts для emulator використовується 10.0.2.2:8000. Для iOS simulator — localhost:8000.


🔮 Deferred / Ideas

Voice commands for hands-free operation

Мотивація: водій за кермом — незручно тикати екран Чому відкладено: voice API (Google / Apple) + UX тестування Trigger: запит від великого автопарку

Offline maps & route display

Мотивація: зона без мережі — водій не бачить де він на маршруті Чому відкладено: потрібно завантажувати tiles (OSM offline) Trigger: маршрути у регіонах зі слабким покриттям

ePOD (electronic proof of delivery)

Мотивація: фото + підпис клієнта + OCR накладної Чому відкладено: реалізовано базово (sales-mobile); розширити для Driver App Trigger: запит логістичних клієнтів

Fuel auto-capture (OCR чеку з АЗС)

Мотивація: ручне введення л/грн — помилки Чому відкладено: OCR API + обробка шаблонів чеків Trigger: клієнт з >5 заправок/день на водія

Driver scorecard (KPI у додатку)

Мотивація: гейміфікація — водій бачить свій рейтинг (час, паливо) Чому відкладено: логіка KPI на backend + UI Trigger: запит HR-департаменту


Пов'язане