# 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_.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)