feat(apps): الخريطة وطلب الرحلة ودورة السائق — المرحلة 4

## حسم تعارض الخرائط (docs/38 §7)
لصالح القرار الأحدث 2026-07-20: كل الخرائط — البلاطات والبحث والعكسي
والمسار — مباشرة إلى map-saas بترويسة x-api-key، بلا مرور بباك إند تريبز.
نقاط /maps/* في الباك إند لا تُستعمل، وإحداها (geocode) معطوبة على المنشور.
العقد تُحقّق حيّاً بـcurl قبل كتابة سطر.

## النواة المشتركة
- core/api/antlaq_api.dart: عميل منفصل بلا AuthInterceptor — توكن تريبز لا
  شأن لخادم الخرائط به، وإرساله إليه تسريب بلا مقابل
- core/realtime: Socket.IO واحد (trip:update · driver:location · trip:offer
  · trip:offer_taken)
- core/location: نقطة الموقع الوحيدة بمرشّح 25 متراً
- features/trip/data: سبعة نماذج + MapsRepository + TripRepository متطابق
  حرفياً بين التوأمين

## الراكب
RideCubit بستّ مراحل + RidePage وثمانية ويدجت: الخريطة · دبّوس المنتصف ·
المخطّط · الخط الزمني · اختيار النوع · التأكيد · البحث عن سائق · الرحلة.

## السائق
DutyCubit بأربع مراحل + DutyPage: مفتاح الاتصال · العرض بمؤقّت · الرحلة.

## قرارات تحمي الأداء والصحّة
- GeoPoint مستقلّ عن حزمة الخريطة؛ intaleq_maps مستوردة في ملف واحد فقط
  لكل تطبيق. تبديل محرّك الخريطة لا يلمس منطقاً
- الخريطة خارج BlocBuilder الورقة ولها BlocSelector خاص: نبضة موقع كل 25م
  لا تعيد بناء الشاشة
- مهلة بحث محليّة 90ث + استطلاع كل 5ث: الخادم قد لا يُطلق expired/no_drivers
  أبداً (ثغرة R1)، وانتظار حدث قد لا يصل = شاشة بحث أبدية
- offeredDrivers == 0 جواب نهائي فوري بلا انتظار المهلة
- الأجرة لا تُعرض إلا إن كانت صالحة: /tariff/quote يرجّع 200 بقيم null صامتة
- موقع السائق بمسارين عمداً: REST لمطابقة Redis والسوكت لخريطة الراكب

flutter analyze نظيف · الراكب 70 ملف/5,294 سطر · السائق 67 ملف/4,771 سطر.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-08-04 23:33:56 +03:00
co-authored by Claude Opus 5
parent c52338f3bb
commit 1156299d09
59 changed files with 4652 additions and 181 deletions
+39 -1
View File
@@ -200,7 +200,45 @@
16. **بوابة**: دخول حقيقي من التطبيقين على NestJS المشتغل + لقطات شاشة تُقارن
بمرجع سيرو، ولا تُقبل إن كانت أدنى منه.
### المرحلة 4 — الخريطة وطلب الرحلة
### المرحلة 4 — الخريطة وطلب الرحلة — **نُفّذت 2026-08-04، البوابة معلّقة**
**حُسم تعارض الخرائط المسجّل في `docs/38 §7`** لصالح القرار الأحدث
(2026-07-20): كل الخرائط — البلاطات والبحث والعكسي والمسار — **مباشرة إلى
`map-saas.intaleqapp.com`** بترويسة `x-api-key`، بلا مرور بباك إند تريبز.
نقاط `/maps/*` في الباك إند **لا تُستعمل**، وإحداها (`geocode`) معطوبة على
المنشور أصلاً. تُحقّق العقد حيّاً بـcurl قبل الكتابة.
المنجز:
- `core/api/antlaq_api.dart` — عميل منفصل **بلا** `AuthInterceptor`: توكن
تريبز لا شأن لخادم الخرائط به، وإرساله إليه تسريبٌ بلا مقابل.
- `core/realtime/realtime_service.dart` — Socket.IO واحد للتطبيق:
`trip:update` · `driver:location` · `trip:offer` · `trip:offer_taken`.
- `core/location/location_service.dart` — نقطة الموقع الوحيدة، بمرشّح 25م.
- `features/trip/data/` — سبعة نماذج + `MapsRepository` + `TripRepository`
(متطابق حرفياً بين التوأمين).
- **الراكب**: `RideCubit` بستّ مراحل + `RidePage` وثمانية ويدجت
(الخريطة · دبّوس المنتصف · المخطّط · الخط الزمني · اختيار النوع · التأكيد ·
البحث عن سائق · الرحلة الجارية).
- **السائق**: `DutyCubit` بأربع مراحل + `DutyPage` وأربعة ويدجت
(مفتاح الاتصال · العرض بمؤقّت · الرحلة الجارية · بطاقة الراكب).
قرارات تصميمية مقصودة:
1. **`GeoPoint` مستقلّ عن حزمة الخريطة**؛ `intaleq_maps` مستوردة في **ملف
واحد فقط** لكل تطبيق (`ride_map.dart`). تبديل محرّك الخريطة لا يلمس منطقاً.
2. **الخريطة خارج الـ`BlocBuilder`** الذي يبني الورقة، ولها `BlocSelector`
بما تحتاجه وحدها — نبضة موقع كل 25م لا تعيد بناء الشاشة. هذا تطبيق مباشر
لميزانية الأداء (م2.12).
3. **مهلة بحث محليّة 90 ثانية + استطلاع كل 5ث**: الخادم قد لا يُطلق
`expired`/`no_drivers` أبداً (ثغرة R1)، وانتظار حدثٍ قد لا يصل = شاشة
بحث أبدية. و`offeredDrivers == 0` يُعالَج فوراً بلا انتظار المهلة.
4. **الأجرة لا تُعرض إلا إن كانت صالحة**: `/tariff/quote` يرجّع 200 بقيم
`null` صامتة عند المدخلات الخطأ (`docs/38 §7`).
5. موقع السائق يُرسَل بمسارين عمداً: REST يغذّي مطابقة Redis، والسوكت يغذّي
خريطة الراكب — سقوط أحدهما لا يُعمي الآخر.
`flutter analyze` نظيف · الراكب 70 ملف/5,294 سطر · السائق 67 ملف/4,771 سطر.
### (الأصل المعتمد للمرحلة 4)
17. الخريطة مباشرة لـ map-saas بمفتاح `x-api-key` مقيّد ببصمة التطبيق
(قرار `maps-direct-decision`) — لا تمرير عبر الباك إند.
18. الراكب: اختيار المصدر/الوجهة · التسعير المسبق · تأكيد الطلب · انتظار سائق.