Ngôn ngữ: English | Tiếng Việt | 日本語
FoodFlow có hai ứng dụng mobile native độc lập cho Khách hàng và Tài xế, không phải chỉ có dashboard Admin. Tài liệu này đối chiếu trực tiếp với router và màn hình Flutter hiện có. Đây là hướng dẫn theo source, không phải xác nhận app đã được phát hành hay production provider đã sẵn sàng.
| Ứng dụng | Người dùng | Android package/flavor | Entrypoint |
|---|---|---|---|
| Customer | Khách đặt món | vn.foodflow.customer / customer |
main_customer.dart |
| Driver | Tài xế đã xác minh | vn.foodflow.driver / driver |
main_driver.dart |
Cả hai gọi NestJS API đã xác thực. Ở managed production, app nhận event được allow-list qua credential Supabase Realtime có scope; Socket.IO chỉ là lựa chọn local/self-hosted được chỉ định rõ. Customer và Driver không có URL web để mở bằng trình duyệt.
Xem hướng dẫn Khách hàng độc lập để thao tác đặt món từng bước, quyền, giới hạn địa chỉ, checkout, theo dõi và trợ giúp. Xem hướng dẫn Tài xế cho đăng nhập, Online/GPS, dispatch, thu nhập và hồ sơ. Tài liệu này vẫn là tổng quan mobile/runtime dùng chung.
- Mở app và đăng nhập. App bắt đầu ở splash, sau đó dùng các route Customer đã xác thực. Người mới có thể đăng ký; route auth hiện tại đưa cả đăng nhập và đăng ký thẳng tới Trang chủ. Hộp thoại quyền vị trí/thông báo do tính năng và thiết bị liên quan xử lý, không phải chuỗi onboarding bắt buộc sau auth. Có thể từ chối quyền; app phải hiển thị trạng thái giới hạn thực tế, không được bịa vị trí hay push thành công.
- Tìm món. Home, search, danh sách/lọc nhà hàng, chi tiết nhà hàng và món dẫn tới giỏ hàng. Favorite và voucher là các route Customer đã xác thực.
- Kiểm tra giỏ và thanh toán. Checkout bắt buộc chọn địa chỉ giao. App gửi địa chỉ, phương thức thanh toán, ghi chú tùy chọn và mã khuyến mãi trong giỏ cho API. UI hiện có tiền mặt và ví; server là nguồn quyết định cuối cùng về khả dụng, giá, khuyến mãi và kết quả thanh toán.
- Theo dõi đơn. Checkout thành công mở theo dõi đơn. App tải chi tiết đơn, bắt đầu tracking đã xác thực cho đúng đơn và dừng khi rời màn hình. Camera/ route map chỉ dùng điểm hợp lệ; client không tự vẽ đường thẳng hay ETA giả.
- Hoàn tất hoặc cần hỗ trợ. Lịch sử đơn dẫn tới tracking và đánh giá. Hủy đơn gửi lý do và ghi chú tùy chọn; việc hủy/hoàn tiền có được chấp nhận hay không do server quyết định. Profile có địa chỉ, ví, loyalty, referral, favorite, thông báo và help center/chat.
Sau khi có session Customer hợp lệ, app có thể xin quyền thông báo và đăng ký FCM token nếu build có metadata Firebase công khai. Push tap chỉ nhận deep link nội bộ tới thông báo hoặc đơn; link không hỗ trợ rơi về inbox trong app. Thiếu cấu hình Firebase chỉ tắt đăng ký FCM, không được giả vờ push đã gửi thành công.
- Đăng nhập và onboarding. Driver chưa chấp nhận điều khoản hiện hành sẽ tới màn agreement. Driver chưa xác minh đi theo vehicle, documents, KYC. KYC dùng dữ liệu typed và private upload grant; không dán signed upload URL hoặc credential vào app.
- Bật Online bằng GPS thật. Trang chủ Driver có control Online. Khi bật, app lấy mẫu vị trí còn mới rồi API chấp nhận hoặc từ chối availability. GPS stale/lỗi phải giữ UI đúng trạng thái; không được hiện Online chỉ vì đã bấm công tắc.
- Nhận và xử lý cuốc. Offer được cấp quyền mở dialog accept/reject không thể dismiss. Đơn được nhận đi qua delivery flow, xác nhận lấy hàng và hoàn tất giao. Geometry/ETA route lấy từ backend đã chấp nhận; thiếu dữ liệu phải hiển thị unavailable.
- Vận hành tài khoản. Route Driver có lịch sử/chi tiết chuyến, earnings, incentives, heatmap, ratings, bank account, hỗ trợ, cài đặt và offline status. Đây là route đã xác thực dành riêng cho Driver, không thay thế quyền Admin hay Restaurant.
Inbox Driver là route đã xác thực và khi đang mở còn nhận stream realtime được phép, khử trùng lặp theo notification ID. Push tap chỉ có thể tới notifications, earnings hoặc profile sau khi trạng thái đăng nhập Driver cho phép; tap tới lúc đang restore session sẽ đợi xác thực xong. Đích lạ luôn rơi về notification inbox.
Với API local trên máy phát triển, Android emulator dùng 10.0.2.2. Thiết bị
thật phải dùng địa chỉ LAN truy cập được của máy đó.
cd mobile
flutter pub get --enforce-lockfile
flutter run --flavor customer -t lib/main_customer.dart `
--dart-define=API_BASE_URL=http://10.0.2.2:3001/api `
--dart-define=REALTIME_PROVIDER=socketio
flutter run --flavor driver -t lib/main_driver.dart `
--dart-define=API_BASE_URL=http://10.0.2.2:3001/api `
--dart-define=REALTIME_PROVIDER=socketioManaged production phải dùng provider alias đã xác minh cùng
REALTIME_PROVIDER=supabase; test Firebase cũng cần đủ bốn FIREBASE_* công
khai khớp flavor. Không đưa FCM service account, Supabase service-role,
database URL hoặc signing secret vào Dart define. Cài đặt đầy đủ, build Android
và xử lý sự cố nằm trong mobile README.
| Luồng Customer đã xác thực | Trang chủ Driver khi đang giao |
|---|---|
![]() |
![]() |
Ảnh role, GIF Customer/Driver và các capture GPS/quyền local trước đó được tạo trên Android AVD với các stack FoodFlow local, seed identity synthetic, mật khẩu che, working tree dirty, GPS mô phỏng cố định và không dùng Google Maps API key. Customer hiện có evidence Trang chủ, Đơn hàng và Cá nhân đã xác thực, không hiện tọa độ chính xác hay thông tin liên hệ tài khoản. Đây vẫn là evidence regression/product local đã review riêng tư, không chứng nhận mobile release, payment, dispatch, routing, provider hay production.
Một WebP recovery Driver được gắn nhãn riêng đến từ smoke production-emulator Android API 35 có phạm vi với Railway và Supabase. Lượt đó ghi nhận foreground tracking, cập nhật khi tắt màn hình, offline flush, process recovery, PostGIS và private Broadcast được cấp quyền cho fixture synthetic; không chứng nhận thiết bị vật lý, iOS, FCM, payout, routing, app-store hay production rộng hơn. Manifest ghi source head và cleanup. Xem quy trình capture để tạo visual clean-head mới.
Liên quan: yêu cầu sản phẩm, hướng dẫn test, product gallery.

