بناء من الصفر على باك إند 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>
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 → [تسجيل] → الرئيسية
بوابتان قبل أي حقل إدخال، وكل واحدة شاشة كاملة لا حوار:
- صفحة الموافقة (
_buildAgreementPage): نصّ الاتفاقية بـHTML من الخادم، مربّع اختيار، وزر متابعة معطّل حتى يُؤشَّر. تُحفظ (BoxName.agreeTerms == 'agreed') ولا تتكرر. - صفحة إذن الموقع: تطلب الإذن، ومعها زر
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/.
البنية: خريطة ثابتة + ورقة سفلية بثلاث حالات
- مطوية (
_Collapsed) — بطاقة «إلى أين؟» فقط. - موسّعة (
_Expanded) — المخطّط الكامل. - اختيار من الخريطة (
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) —
تفكيك جيد يُحتذى.
⚠️ مصيدتان:
- سيرو يخلط محفظة الراكب والسائق في تصميم واحد. تريبز يفصلهما (التزام مقابل إيراد) — لا تُوحَّد الشاشة.
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_widget871 ·order_over_lay847 ·home_captin840) — تفكّك. GetBuilderيلفّ الشاشة كاملة → إعادة بناء الشجرة كلها عند أي تحديث. البديل:BlocSelector/buildWhenعلى أصغر جزء.- منطق داخل الويدجت. النمط الصحيح موجود في سيرو نفسه
(
searching_captain_window«غبي» والمؤقّت في الكنترولر) — يُعمَّم.
قائمة الممنوعات النهائية تُستكمل في م2 بعد تشخيص
*-archive-cubitنفسه — فسبب الأداء المرفوض هناك، لا هنا.