- docs/00-15: دراسة، بنية، محرك تعرفة، تسعير، نموذج استئجار، تكاملات، بيانات، realtime، خطة، devops، لاندنج، مخاطر، اصطلاحات سيرفر، تدفق نشر - backend/: NestJS 11 على Docker (health + tenants + عزل tenant_id + بادئة tripz_ + Redis DB 3) - apps/rider, apps/driver, dashboards/admin-web, dashboards/superadmin-web (هياكل) - sync-to-server.sh + .gitignore Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
65 lines
4.6 KiB
Markdown
65 lines
4.6 KiB
Markdown
# 03 — خطة تطبيقات الموبايل (Flutter)
|
|
|
|
## الحزمة التقنية
|
|
- **Flutter** (أحدث مستقر) + **Dart 3**.
|
|
- إدارة الحالة: **flutter_bloc** — **Cubit** افتراضياً، **Bloc كامل** لآلتَي حالة فقط.
|
|
- التوجيه: **go_router** · الحقن: **get_it** (+ injectable اختياري).
|
|
- الشبكة: **dio** + interceptors (tenant header, auth, retry).
|
|
- الخرائط: عميل انطلق (بلاطات vector عبر `maplibre_gl` أو ما يعادله فوق Martin).
|
|
- الترجمة: **flutter_localizations** + ARB، RTL أول درجة.
|
|
|
|
## لماذا Cubit افتراضياً؟
|
|
الانتقال من GetX Controller شبه مباشر: `Controller` → `Cubit`، `update()` → `emit(state)`. نكسب قابلية الاختبار (`bloc_test`) والقبول الصناعي لمنتج يُرخّص ويُدقّق، دون كلفة أحداث Bloc الكاملة في الشاشات الاعتيادية.
|
|
|
|
## أين نستخدم Bloc الكامل (حصراً)
|
|
| آلة الحالة | لماذا Bloc |
|
|
|-----------|-----------|
|
|
| **دورة حياة الرحلة (راكب)** | سلسلة انتقالات مسماة تأتيها أحداث من 3 جهات (المستخدم، socket، مؤقتات) — الأحداث الصريحة تمنع أخطاء التزامن وتعطي سجل انتقالات للتشخيص |
|
|
| **تدفق العروض/الطلبات (سائق)** | نفس السبب: عروض تصل وتنتهي صلاحيتها بتزامن حسّاس |
|
|
|
|
## بنية الحزمة (packages / flavors)
|
|
كود موحّد + نكهة لكل مستأجر:
|
|
```
|
|
mobile/
|
|
├── packages/
|
|
│ └── tripz_core/ # مشترك: نماذج، شبكة، تعرفة، خرائط، ثيم، l10n
|
|
├── apps/
|
|
│ ├── rider/ # تطبيق الراكب
|
|
│ └── driver/ # تطبيق السائق
|
|
└── flavors/ # إعداد لكل مستأجر (bundle id, ألوان, أيقونة, مفاتيح)
|
|
```
|
|
- **ما يتغير بالبناء فقط:** bundle id، الأيقونة، اسم التطبيق، مفاتيح FCM → في الـ flavor.
|
|
- **ما يمكن جعله ديناميكياً:** النصوص، الميزات المفعّلة، طرق الدفع، التعرفة، الألوان → يُجلب من `GET /tenant/config` عند الإقلاع.
|
|
- **درء رفض آبل (بند 4.3):** كل نكهة بأصول ومحتوى متجر مميّز؛ خيار «التطبيق الجامع» (راكب واحد يضم مشغّلين) للباقة المجانية.
|
|
|
|
## طبقات كل تطبيق
|
|
```
|
|
lib/
|
|
├── main_<flavor>.dart # نقطة دخول لكل نكهة
|
|
├── app.dart # MaterialApp.router + ثيم + l10n
|
|
├── core/ # DI, router, dio client, config bootstrap
|
|
├── data/ # repositories, data sources, models (DTO↔domain)
|
|
├── domain/ # entities, use cases (نقية)
|
|
└── features/
|
|
├── auth/ # cubit + screens
|
|
├── home/ # الخريطة + طلب رحلة
|
|
├── trip/ # ★ TripBloc (Bloc كامل) + شاشات دورة الرحلة
|
|
├── offers/ (سائق) # ★ OffersBloc (Bloc كامل)
|
|
├── earnings/ (سائق) # cubit
|
|
├── wallet/ # cubit (P3)
|
|
├── chat/ rating/ profile/ settings/ # cubits
|
|
```
|
|
|
|
## الشاشات الأساسية (P1)
|
|
**الراكب:** onboarding/OTP → الخريطة والطلب → اختيار الوجهة والسعر المقفول → انتظار الإسناد → تتبع حي → دردشة → إنهاء ودفع كاش → تقييم · العناوين المفضلة · السجل.
|
|
**السائق:** OTP → تسجيل بالوثائق → الحالة (متصل/مشغول) → استقبال العرض → التوجّه/الوصول → بدء/إنهاء الرحلة → الأرباح.
|
|
|
|
## قواعد الهندسة
|
|
- **لا منطق عمل في الـ Widgets** — في الـ Cubit/Bloc والـ use cases.
|
|
- **الثيم والنصوص من config** حيث أمكن — لا قيم مبعثرة.
|
|
- **RTL افتراضي**، اختبار كل شاشة بالعربية أولاً.
|
|
- **اختبار:** `bloc_test` لكل Cubit/Bloc حرج + golden tests للشاشات الرئيسية.
|
|
- تجريد الخرائط في `tripz_core/maps` لتبديل المزوّد لأي مستأجر خارج تغطية انطلق.
|
|
|
|
← السابق: [02-backend-plan](02-backend-plan.md) · التالي: [04-tariff-engine](04-tariff-engine.md)
|