Files
tripz-llc/docs/39-siro-screens.md
Hamza-AyedandClaude Opus 5 69da4abc01 feat(apps): سقالة rider_new و driver_new على Cubit — المرحلة 1
بناء من الصفر على باك إند NestJS، بقرار المالك 2026-08-04 الذي يعكس قرارَي
نقل GetX (2026-07-21) واعتماد باك إند PHP (2026-07-27). لا يُورَّث سطر دارت
من apps/*-archive-cubit، وسيرو مرجع بصري وسلوكي لا مصدر نسخ.

الوثائق:
- docs/37: الخطة الكاملة بستّ مراحل وبواباتها
- docs/38: عقد الـAPI من 37 controller، معظمه متحقَّق حيّاً من السيرفر المنشور
- docs/39: جرد 202 شاشة في تطبيقَي سيرو، مصنّفة داخل/خارج النطاق

الطبقة الأصلية منقولة من *-archive-cubit وحدها لأنها هوية النشر:
- rider_new  → com.mobileapp.store.ride · shorebird 496cb3ac
- driver_new → com.sefer_driver (أندرويد) · com.sefer.driver (iOS) · 68cc9345
- أُصلح تعارض: هدف RunnerTests في driver_new كان يحمل bundle الراكب

الأصول مصدرها *-archive-cubit لا سيرو: أصول الأرشيف مجموعة أشمل (كل صور
سيرو + صور تريبز) وخطوطها هي خطوط docs/26. استُكمل السائق بعشرة ملفات
ناقصة من سيرو (شعارات مزوّدي الدفع + صوتان).

lib/ مكتوب من الصفر (11 ملف لكل تطبيق):
- AppConfig بأعلام const — أساس نموذج lite/pro/max
- TokenStore على التخزين الآمن، يقرأ exp محليّاً بلا حزمة خارجية
- AuthInterceptor بتجديد استباقي وطلقة واحدة — عمر التوكن 15 دقيقة فقط
- ApiClient و ApiException يفهم مصفوفة message في NestJS

flutter analyze نظيف في التطبيقين. البناء الفعلي لم يُجرَّب بعد: بوابة
المرحلة 1 تتطلّب البناء على السيرفر، والوصول إليه غير متاح حالياً.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 21:21:26 +03:00

12 KiB

39 — جرد شاشات سيرو: المرجع البصري والسلوكي

الغرض: هذا ما نبني عليه الشكل والترتيب في rider_new وdriver_new (م0.3 من docs/37). المصدر: ~/development/App/Siro/siro_rider وsiro_driver.

قاعدة الاستخدام: هذا الملف يجيب على «ما هي الشاشة، وما ترتيب خطواتها، وأي حالة حافة عولجت ميدانياً». لا يُنسخ ملف دارت واحد من سيرو. شكل الواجهة يُعاد بناؤه على docs/26 بجودة أعلى، والعقد من docs/38.


1. المخزون — الحجم الحقيقي

شاشات/ويدجت ملاحظة
siro_rider/lib/views 89 ملف يشمل الطعام والنقل العام
siro_driver/lib/views 113 ملف يشمل التوصيل والتلعيب والإحصاءات

ليس كله في النطاق. خارج نطاق docs/37 تماماً: food/, food_delivery/, transit/, gamification/, assurance_health_page, siro_prime_page, android_bot. هذي تُقرأ لاحقاً عند وحدات docs/33 المدفوعة، لا الآن.

داخل النطاق (م1–م6): المصادقة · الخريطة وطلب الرحلة · مسار الرحلة · المحفظة · الدراور والملف · الإشعارات · التقييم.


2. المصادقة — مرجع م3

التسلسل في سيرو (متطابق في التطبيقين)

موافقة الشروط  →  إذن الموقع  →  رقم الهاتف  →  OTP  →  [تسجيل]  →  الرئيسية

بوابتان قبل أي حقل إدخال، وكل واحدة شاشة كاملة لا حوار:

  1. صفحة الموافقة (_buildAgreementPage): نصّ الاتفاقية بـHTML من الخادم، مربّع اختيار، وزر متابعة معطّل حتى يُؤشَّر. تُحفظ (BoxName.agreeTerms == 'agreed') ولا تتكرر.
  2. صفحة إذن الموقع: تطلب الإذن، ومعها زر openAppSettings() للحالة التي يرفض فيها المستخدم نهائياً. تطبيق السائق يراقب دورة حياة التطبيق (WidgetsBindingObserver + didChangeAppLifecycleState) ليعيد الفحص عند العودة من إعدادات النظام — بلا هذا تبقى الشاشة عالقة. حالة حافة حقيقية لازم تُنقل.

شاشة الهاتف

  • IntlPhoneField مع مفتاح دولة افتراضي من BoxName.countryCode.
  • تحقّقات مطبّقة: فارغ · يبدأ بصفر → رفض («أدخل بلا الصفر») · أقصر من 10.
  • الرقم يُرسل بلا +.

شاشة الـOTP

  • 3 خانات في سيرو، حقل واحد بتباعد حروف كبير + ثلاث نقاط تقدّم متحرّكة.
  • ⚠️ تريبز يستخدم 4 خانات (docs/38). الشكل يُقلَّد، الطول لا.
  • ⚠️ لا يوجد عدّاد إعادة إرسال ولا زر «إعادة الإرسال» في سيرو. هذه فجوة، لا مرجع: تريبز يحدّ send-otp بـ3 طلبات/5 دقائق، فبلا عدّاد تنازلي يُحظر المستخدم بثلاث ضغطات. لازم نضيفها.

شاشة التسجيل

الاسم الأول · الأخير · البريد. ⚠️ عقد تريبز يقبل { name, language } فقط (PATCH /users/me) — حقل اسم واحد. لا تُنقل الحقول كما هي.

فروق تطبيق السائق

مسار إضافي بعد الدخول: registration_view (تسجيل السائق) → pending_driver_page (شاشة «قيد المراجعة») → camera_lisence_page / text_scanner / passportimage (تصوير الوثائق) → cars_inserting_page. يقابلها في تريبز: /drivers/apply → /drivers/profile → /drivers/documents → /vehicles، ثم إعادة دخول إجبارية لأن الدور يتغيّر بعد الاعتماد (مصيدة docs/38 §5).

ما لا يُنقل من طبقة مصادقة سيرو

login_controller.dart فيه JWT مزدوج (توكن عام + walletJwt منفصل)، وقفل تزامن ساكن، وعدّاد إخفاقات، وفكّ base64 يدوي للـpayload. هذا تعقيد مفروض من باك إند PHP، وتريبز عنده access_token/refresh_token واحد. لا يُنقل. المُنقَل هو الفكرة الصالحة: تجديد واحد متزامن لا يتضاعف عند تعدد الطلبات.


3. الخريطة وطلب الرحلة — مرجع م4

أنضج جزء في سيرو، وأدقّ ما نأخذه منه. الوحدة: views/home/route_planner/ (10 ملفات، 1,928 سطراً) + views/home/map_widget.dart/.

البنية: خريطة ثابتة + ورقة سفلية بثلاث حالات

  1. مطوية (_Collapsed) — بطاقة «إلى أين؟» فقط.
  2. موسّعة (_Expanded) — المخطّط الكامل.
  3. اختيار من الخريطة (RpMapPickOverlay) — الورقة تنزوي، ودبّوس ثابت في المنتصف (rp_center_pin) والخريطة تتحرك تحته. النمط الصحيح: المستخدم يحرّك الخريطة لا الدبّوس.

ترتيب المخطّط الموسّع (من أعلى لأسفل)

ترويسة → مبدّل نوع الطلب (لنفسي ⇄ لشخص آخر) → الخط الزمني للمسار (المصدر · محطات وسيطة · الوجهة) → وصول سريع (المنزل/العمل) → متقدّم.

  • المصدر افتراضياً = الموقع الحالي، وقابل للتغيير من الخريطة.
  • عند «لشخص آخر» يتبدّل حقل المصدر فوراً (rp_sheet.dart:509).
  • المحطات الوسيطة صفوف قابلة للإضافة/الحذف — يقابلها stops[] في POST /trips (docs/38 §4). موجودة في الطرفين.
  • المفضّلات (rp_favorites) والبحث (rp_search_dialog + rp_search_results).

نافذة البحث عن سائق (searching_captain_window)

  • أنيميشن رادار (دورة ثانيتين) + نصّ الحالة من الكنترولر + مؤشّر دوّار.
  • لا مقبض سحب — لا تُغلق بالسحب، فقط بزر «إلغاء البحث». قرار تصميمي صحيح يُنقل: المستخدم لا يزيح شاشة البحث بالخطأ.
  • الويدجت «غبي» بلا منطق؛ المؤقّت في الكنترولر هو من يقرر متى يعرض حوار زيادة الأجرة. يقابل مباشرةً مصيدة docs/38 §4: expired/no_drivers قد لا يصلان من الخادم → المهلة المحليّة إلزامية. سيرو عالجها؛ نكرّرها.

بطاقة الرحلة الجارية (apply_order_widget, 871 سطراً)

ترويسة مضغوطة · بطاقة معلومات · شارة السائق · لوحة مركبة مرسومة · أيقونة سيارة متحرّكة · صف أزرار · حقل رسالة مخصّصة · مؤشّرا «وصل السائق وينتظر ن دقيقة» و«الوقت المتبقّي للوصول». هذي المكوّنات هي ما يجعل الشاشة تبدو احترافية — تُعاد بناؤها في packages/tripz_ui، لا تُنسخ.

شاشات مساندة

payment_method_page · cash_confirm_bottom_page · cancel_raide_page (أسباب الإلغاء) · ride_begin_passenger · car_details_widget_to_go · trip_monitor + trip_link_monitor (مشاركة رابط تتبّع) · voice_call_bottom_sheet (WebRTC — يقابل call:* في docs/38 §9).

شاشة السائق (order_request_page, 468 سطراً)

خريطة → كبسولة «الوصول للراكب» → بطاقة سفلية: الراكب + السعر → شريط معلومات (المسافة/المدة) → العناوين → الأزرار.

  • حالة تحميل صريحة إن وصل العرض بلا بيانات كاملة — لا شاشة فارغة.
  • order_over_lay.dart (847 سطراً) = العرض المنبثق فوق أي شاشة. يقابل trip:offer وtrip:offer_taken في docs/38 §9.
  • ⚠️ شارة driverEarningsExtra تعتمد حقولاً من add_ride.php (باك إند PHP) غير موجودة في عقد NestJS — تُسقط أو يُضاف لها حقل في الخادم. مثال حيّ على أن سيرو ليس مطابقاً للعقد.

4. المحفظة — مرجع م5

الراكب السائق
passenger_wallet · payment_history_passenger_page · cliq_payment_sheet · payment_screen_cliq/mtn/sham walet_captain · pay_out_screen · weekly_payment_page · transfer_budget_page · points_captain · ecash · bank_account_egypt

محفظة السائق مقسّمة لويدجت جاهزة (balance_card · financial_summary_card · quick_actions · transaction_preview_item) — تفكيك جيد يُحتذى.

⚠️ مصيدتان:

  1. سيرو يخلط محفظة الراكب والسائق في تصميم واحد. تريبز يفصلهما (التزام مقابل إيراد) — لا تُوحَّد الشاشة.
  2. pay_out_screen في سيرو خطوة واحدة؛ تريبز خطوتان مع OTP (docs/38 §6). الشاشة تُعاد تصميمها لا تُقلَّد.

5. الدراور والملف والإشعارات — مرجع م6

الراكب: drawer_menu_page · passenger_profile_page · order_history · setting_page · languages · about_page · contact_us · frequentlyQuestionsPage · share_app_page · complaint_page · promos_passenger_page · taarif_page · notification_page · rate_captain + rating_driver_bottom.

السائق: drawer_captain · bottom_bar (تنقّل سفلي — الراكب بلا) · profile_captain · captains_cars · history_captain + history_details_page · settings_captain · behavior_page · feed_back_page · help_captain + help_details_replay_page · available_rides_page · statistics_dashboard (+6 ويدجت رسوم) · rate_passenger · ride_calculate_driver · sos_connect (استغاثة).

شاشة التقييم مهمة معمارياً: تُفرض عند فتح التطبيق عبر GET /trips/rating/pending (docs/38 §7) — تُبنى في م5 لا م6.


6. الويدجت المشتركة — مدخل packages/tripz_ui

الملفات نفسها مكرّرة حرفياً في التطبيقين: circle_container · elevated_btn · error_snakbar · icon_widget_menu · my_circular_indicator_timer · my_scafold · my_textField · mycircular · mydialoug · voice_call_bottom_sheet.

هذا بالضبط ما تحلّه packages/tripz_ui (م2.11): ازدواج مؤكَّد في سيرو، لا يتكرر عندنا.


7. ملاحظات أداء — مادة قائمة الممنوعات (م2.12)

من قراءة سيرو، هذي أنماط تُتجنّب في *_new:

  • Get.put() داخل build() (login_page.dart:27) — حقن عند كل إعادة بناء.
  • ملفات ويدجت تتجاوز 800 سطر (apply_order_widget 871 · order_over_lay 847 · home_captin 840) — تفكّك.
  • GetBuilder يلفّ الشاشة كاملة → إعادة بناء الشجرة كلها عند أي تحديث. البديل: BlocSelector/buildWhen على أصغر جزء.
  • منطق داخل الويدجت. النمط الصحيح موجود في سيرو نفسه (searching_captain_window «غبي» والمؤقّت في الكنترولر) — يُعمَّم.

قائمة الممنوعات النهائية تُستكمل في م2 بعد تشخيص *-archive-cubit نفسه — فسبب الأداء المرفوض هناك، لا هنا.