26 KiB
تحليل نظام متابعة الرحلات في لوحة تحكم المشرف (Siro Admin)
دراسة شاملة للبحث، التتبع، التعديل، والتعامل مع الرحلات المعلقة
📋 فهرس المحتويات
- النظام الحالي لمتابعة الرحلات
- تحليل شاشات وأدوات متابعة الرحلات
- حالات الرحلة الفعلية من قاعدة البيانات
- مشكلة رقم الهاتف والدولة
- الـ Endpoints المستخدمة واستجاباتها
- ما هو موجود وما هو مفقود
- التوصيات والتحسينات المطلوبة مع الإصلاحات
النظام الحالي
الملفات المشاركة في متابعة الرحلات
| الملف | الدور |
|---|---|
siro_admin/lib/views/admin/rides/ride_lookup_page.dart |
لوحة إدارة الرحلات (Dashboard) - الأحدث |
siro_admin/lib/views/admin/rides/rides.dart |
إحصائيات الرحلات الشهرية (قديم) |
siro_admin/lib/views/admin/drivers/monitor_ride.dart |
شاشة مراقبة رحلة محددة بالخريطة |
siro_admin/lib/controller/rides/ride_lookup_controller.dart |
تحكم البحث عن رحلة وتحديث حالتها |
siro_admin/lib/controller/admin/ride_admin_controller.dart |
تحكم إحصائيات الرحلات |
ملفات الباك إند
| الملف | الوظيفة |
|---|---|
backend/Admin/rides/get_rides_by_status.php |
جلب الرحلات حسب الحالة (Begin, New, Finished, Canceled) |
backend/Admin/rides/admin_get_rides_by_phone.php |
البحث عن رحلة برقم هاتف الراكب (مشفر) |
backend/Admin/rides/admin_update_ride_status.php |
تحديث حالة الرحلة (Pending→Completed...) |
backend/Admin/rides/monitorRide.php |
مراقبة رحلة نشطة برقم الهاتف (يبحث في السائق والراكب) |
backend/Admin/rides/get_driver_live_pos.php |
جلب الموقع اللحظي للسائق من car_locations |
حالات الرحلة الفعلية في قاعدة البيانات
📌 هيكل الجدول
CREATE TABLE `ride` (
`id` int NOT NULL AUTO_INCREMENT,
`status` varchar(200) NOT NULL DEFAULT 'nothing', -- ❌ NOT ENUM! نص عادي
...
) ENGINE=InnoDB;
CREATE TABLE `waitingRides` (
`id` varchar(100) NOT NULL,
`status` varchar(200) NOT NULL DEFAULT 'nothing', -- ❌ NOT ENUM! نص عادي
...
) ENGINE=InnoDB;
🗺️ جميع حالات الرحلة المستخدمة فعلياً في الكود
| الحالة في DB | المعنى | أين تستخدم |
|---|---|---|
nothing |
القيمة الافتراضية | عند إنشاء الرحلة في add.php و addWaitingRide.php |
New |
رحلة جديدة (لم يتم تعيين سائق بعد) | في Admin/rides/get_rides_by_status.php للـ Admin Dashboard |
waiting |
الرحلة قيد البحث عن سائق | في retry_search_drivers.php عند إعادة البحث |
wait |
في انتظار (مستخدم في بعض السيرفرات) | في getRideStatusFromStartApp.php و cancelRideByPassenger.php |
Apply |
سائق قبل الرحلة (قيد التوجه) | في acceptRide.php, overLay/get.php, driver_statistic.php |
Applied |
تم قبول التطبيق | في get_rides_by_status.php (مع Begin) |
arrived |
السائق وصل إلى موقع الراكب (lowercase) | في arrive_ride.php |
Arrived |
السائق وصل (uppercase) | في get_rides_by_status.php (مستخدم أيضاً) |
Begin |
الرحلة قيد التشغيل 🚗 | في start_ride.php, monitorRide.php, finish_ride_updates.php |
started |
بدأت الرحلة (مرادف لـ Begin) | في start_ride.php (رد API) |
Finished |
الرحلة اكتملت ✅ | في معظم التقارير والإحصائيات |
Cancel |
ملغاة (عام) | في cancelRideFromDriver.php, cancel_ride_by_passenger.php |
CancelFromDriver |
ألغى السائق | في get_rides_by_status.php |
CancelFromDriverAfterApply |
ألغى السائق بعد القبول | في get_rides_by_status.php |
CancelFromPassenger |
ألغى الراكب | في get_rides_by_status.php |
TimeOut |
انتهت المهلة الزمنية | في get_rides_by_status.php |
🔄 تسلسل حالة الرحلة الطبيعي:
nothing / New
│
├──→ waiting ──→ Apply ──→ Applied ──→ Arrived ──→ Begin ──→ Finished
│ │ │ │ │ │
│ │ │ │ │ └── ✅ مكتملة
│ │ │ │ │
│ │ │ │ └── CancelFromDriverAfterApply
│ │ │ │
│ │ │ └── CancelFromPassenger
│ │ │
│ │ └── TimeOut (انتهاء المهلة)
│ │
│ └── CancelFromDriver
│
└── Cancel (إلغاء مباشر)
❌ المشكلة في Admin Dashboard الحالي:
في get_rides_by_status.php، التصنيف خاطئ:
case 'Begin':
$whereClause = "WHERE r.status IN ('Begin','Apply','Applied')"; // ✅ Begin + Apply + Applied
break;
case 'New':
$whereClause = "WHERE r.status = 'New'"; // ✅ جديد
break;
case 'Completed':
$whereClause = "WHERE r.status = 'Finished'"; // ✅ مكتملة
break;
case 'Canceled':
$whereClause = "WHERE r.status IN ('Cancel', 'CancelFromDriverAfterApply', 'TimeOut')"; // ❌ ناقص!
break;
🔴 ملاحظات على التصنيف:
CancelFromDriverوCancelFromPassengerوCancelوarrived(lowercase) غير مشمولة في أي تصنيفApplyوAppliedمصنفين معBegin(جارية) — هذا صحيح جزئياً لأن السائق في طريقهTimeOutمصنف معCanceled— صحيح- الرحلة التي حالتها
waitأوwaitingغير معروضة إطلاقاً في أي تبويب
تحليل الشاشات
1️⃣ شاشة إدارة الرحلات (RidesDashboardScreen)
الملف: ride_lookup_page.dart
الوظائف الحالية:
- ✅ عرض الرحلات مصنفة حسب الحالة (جارية، جديدة، مكتملة، ملغاة)
- ✅ إحصائيات فورية (عدد الرحلات لكل حالة + الإيرادات + المسافة)
- ✅ شريط بحث ديناميكي يصفّي النتائج مباشرة
- ✅ الضغط على رحلة → يفتح خريطة التتبع (RideMapMonitorScreen)
- ✅ إظهار معلومات السائق والراكب مع أيقونة اتصال (للمشرف العام)
منطق البحث الحالي:
void filterRides(String query) {
displayedRides.value = allRidesList.where((ride) {
return ride.driverPhone.contains(query) ||
ride.passengerPhone.contains(query) ||
ride.driverName.toLowerCase().contains(query.toLowerCase()) ||
ride.passengerName.toLowerCase().contains(query.toLowerCase()) ||
ride.rideId.contains(query);
}).toList();
}
🔴 مشكلة: البحث يتم محلياً (في الذاكرة) بعد جلب كل الرحلات من API. إذا كانت الرحلات كثيرة (100+ رحلة)، البحث لا يشمل الرحلات الغير محملة.
🔴 مشكلة: الـ API يجلب فقط آخر 100 رحلة (LIMIT 100) ولا يوجد Pagination.
الـ API المستخدم:
POST $server/Admin/rides/get_rides_by_status.php
payload: { "status": "Begin" }
← { "status": "success", "message": [ {...}, {...} ] }
خريطة التتبع (RideMapMonitorScreen):
- ✅ يعرض مسار الرحلة (نقطة بداية → نقطة نهاية)
- ✅ يتابع موقع السائق اللحظي (Polling كل 10 ثوانٍ)
- ✅ زر اتصال بالسائق أو الراكب
- 🔴 لا يوجد تحديث لحالة الرحلة من هذه الشاشة
2️⃣ شاشة مراقبة رحلة (RideMonitorScreen)
الملف: monitor_ride.dart
الوظائف الحالية:
- ✅ إدخال رقم هاتف للبحث عن رحلة نشطة
- ✅ عرض خريطة كاملة مع مسار الرحلة وموقع السائق
- ✅ تحديث تلقائي (Polling كل 10 ثوانٍ)
- ✅ إظهار اسم السائق، حالة الرحلة، السرعة، آخر تحديث
الـ API المستخدم:
POST $server/Admin/rides/monitorRide.php
payload: { "phone": "963$phone" }
← { "status": "success", "message": {
"ride_details": { ... },
"driver_details": { ... },
"driver_location": { "latitude": ..., "longitude": ..., "speed": ..., "heading": ... }
}}
منطق البحث الحالي:
final response = await CRUD().post(
link: apiUrl,
payload: {"phone": "963$phone"}, // ⚠️ Hardcoded Syria prefix!
);
🔴 مشكلة حرجة: 963$phone ثابت (سوريا فقط). الأردن يحتاج 962 ومصر تحتاج 20.
منطق الباك إند (monitorRide.php):
$encPhone = $encryptionHelper->encryptData($phone);
// يبحث أولاً في جدول driver
$driverQuery = $con->prepare("SELECT id FROM driver WHERE phone = :phone LIMIT 1");
// ثم في جدول passengers
$customerQuery = $con->prepare("SELECT id FROM passengers WHERE phone = :phone LIMIT 1");
// ثم يجلب آخر رحلة status='Begin'
🔴 ملاحظة: monitorRide.php يبحث فقط عن الرحلات التي حالتها Begin. إذا كانت الرحلة بحالة Apply أو Arrived لن يجدها.
3️⃣ شاشة البحث عن رحلة وتحديث حالتها (RideLookupController)
الملف: ride_lookup_controller.dart
الوظائف الحالية:
- ✅ البحث برقم هاتف الراكب (مشفر) عبر
admin_get_rides_by_phone.php - ✅ عرض بيانات الراكب + آخر رحلة له
- ✅ تحديث حالة الرحلة عبر
admin_update_ride_status.php - ✅ قائمة منسدلة للحالات المسموحة:
Pending, Accepted, EnRoute, Arrived, Started, Completed, Canceled
🔴 هذه القائمة لا تطابق حالات الرحلة الفعلية في النظام!
| القيمة في التطبيق | هل تستخدم في DB؟ | الحالة الصحيحة |
|---|---|---|
Pending |
❌ لا | waiting أو New أو nothing |
Accepted |
❌ لا | Apply أو Applied |
EnRoute |
❌ لا | Apply أو Applied (السائق في الطريق) |
Arrived |
✅ نعم | arrived أو Arrived |
Started |
❌ لا | Begin |
Completed |
✅ نعم | Finished |
Canceled |
✅ نعم | Cancel أو CancelFrom* |
الـ API المستخدم للبحث:
POST $server/Admin/rides/admin_get_rides_by_phone.php
payload: { "phone": "...", "status": "..." }
← { "status": "success", "message": {
"passenger": { "id", "first_name", "last_name", "phone" },
"ride": { "id", "status", "start_location", ... }
}}
🔴 مشكلة: هذا الـ API يبحث فقط في جدول passengers. إذا كان الرقم تابعاً لسائق، لن يعثر على شيء.
مشكلة رقم الهاتف والدولة
كيف يتم تخزين أرقام الهواتف؟
في قاعدة البيانات، جميع الأرقام مشفرة باستخدام encryptData():
$encryptedPhone = $encryptionHelper->encryptData($raw);
الأرقام تخزن مع كود الدولة:
- الأردن:
9627XXXXXXXX - مصر:
2010XXXXXXXX - سوريا:
9639XXXXXXXX
كيف يتم البحث في تطبيق المشرف حالياً؟
1️⃣ في monitor_ride.dart:
payload: {"phone": "963$phone"}
// المستخدم يدخل: 0992952235
// التطبيق يرسل: 9630992952235 ← غلط! الصحيح: 963992952235
2️⃣ في admin_get_rides_by_phone.php:
$phone = filterRequest('phone');
$enc_raw = $encryptionHelper->encryptData($raw);
// يبحث فقط في passengers
جدول مقارنة تنسيق الأرقام:
| الدولة | كود الدولة | تنسيق الإدخال | التخزين في DB | ما يرسله monitor_ride.dart |
هل يتطابق؟ |
|---|---|---|---|---|---|
| 🇯🇴 الأردن | 962 |
079XXXXXXX |
96279XXXXXXX |
963079XXXXXXX ❌ |
لا |
| 🇪🇬 مصر | 20 |
010XXXXXXXX |
2010XXXXXXXX |
963010XXXXXXXX ❌ |
لا |
| 🇸🇾 سوريا | 963 |
0992952235 |
963992952235 |
9630992952235 ❌ |
لا (0 زائد) |
تحليل المشكلة:
- المشرف يدخل:
0992952235(سوريا) أو079XXXXXXX(أردن) - التطبيق يضيف:
963ثابت (سوريا فقط) - الباك إند يبحث: عن الرقم
9630992952235أو963079XXXXXXX - الرقم المخزن:
963992952235(بدون 0 بعد كود الدولة) أو96279XXXXXXX - النتيجة: فشل في البحث عن أي رقم غير سوري، وحتى السوري يفشل إذا كان المدخل بـ
0
الـ Endpoints
الحالية في backend/Admin/rides/:
| الإند بوينت | الطريقة | المدخلات | الاستجابة | المشاكل |
|---|---|---|---|---|
get_rides_by_status.php |
POST | status (Begin/New/Completed/Canceled) |
قائمة رحلات (100) مع تفاصيل السائق والراكب | لا يوجد Pagination + بعض الحالات غير مشمولة (wait, CancelFromDriver, arrived) |
admin_get_rides_by_phone.php |
POST | phone |
بيانات الراكب + آخر رحلة | يبحث فقط في passengers |
admin_update_ride_status.php |
POST | id, status, reason (optional) |
الرحلة المحدّثة | Whitelist لا يطابق حالات DB الفعلية |
monitorRide.php |
POST | phone |
تفاصيل الرحلة + السائق + الموقع | يبحث فقط عن Begin + كود الدولة ثابت 963 |
get_driver_live_pos.php |
POST | driver_id |
آخر موقع للسائق | يعمل بشكل صحيح |
التوصيات والإصلاحات
🔴 الإصلاح 1: تصحيح حالات الرحلة في Admin Dashboard
المشكلة: get_rides_by_status.php يستخدم حالات غير دقيقة.
الحل: تعديل mapping الحالات ليطابق الواقع:
// backend/Admin/rides/get_rides_by_status.php - تصحيح
switch ($statusFilter) {
case 'Begin':
// الرحلات الجارية: من Apply إلى Begin
$whereClause = "WHERE r.status IN ('Apply','Applied','Arrived','arrived','Begin')";
break;
case 'New':
// الرحلات الجديدة: بانتظار سائق
$whereClause = "WHERE r.status IN ('New','nothing','waiting','wait')";
break;
case 'Completed':
$whereClause = "WHERE r.status = 'Finished'";
break;
case 'Canceled':
// جميع أنواع الإلغاء
$whereClause = "WHERE r.status IN ('Cancel','CancelFromDriver','CancelFromDriverAfterApply','CancelFromPassenger','TimeOut')";
break;
default:
$whereClause = "WHERE r.status = ?";
$params[] = $statusFilter;
break;
}
🔴 الإصلاح 2: تصحيح قائمة الحالات المسموحة في RideLookupController
المشكلة: statusOptions في ride_lookup_controller.dart لا تطابق حالات DB.
الحل: تعديل القائمة:
// في ride_lookup_controller.dart
final List<String> statusOptions = const [
'New', // جديد (بدلاً من Pending)
'waiting', // في انتظار سائق
'Apply', // سائق قبل (بدلاً من Accepted)
'Arrived', // وصل السائق
'Begin', // الرحلة بدأت (بدلاً من Started)
'Finished', // مكتملة (بدلاً من Completed)
'Cancel', // إلغاء (بدلاً من Canceled)
];
وتحديث admin_update_ride_status.php:
// backend/Admin/rides/admin_update_ride_status.php
$allowed = [
'New', 'waiting', 'wait', 'Apply', 'Applied',
'Arrived', 'arrived', 'Begin', 'Finished',
'Cancel', 'CancelFromDriver', 'CancelFromPassenger', 'TimeOut'
];
🔴 الإصلاح 3: معالجة أرقام الهواتف حسب الدولة
المشكلة: monitor_ride.dart يستخدم 963 ثابت.
الحل: إضافة دالة لتوحيد تنسيق الرقم:
// في monitor_ride.dart
String normalizePhone(String input) {
final clean = input.replaceAll(RegExp(r'\D+'), '');
// Syria: 099XXXXXXX or 9639XXXXXXX
if (clean.length == 10 && clean.startsWith('09'))
return '963${clean.substring(1)}';
if (clean.length == 12 && clean.startsWith('963'))
return clean;
if (clean.length == 9 && clean.startsWith('9'))
return '963$clean';
// Jordan: 079XXXXXXX or 9627XXXXXXX
if (clean.length == 10 && clean.startsWith('07'))
return '962${clean.substring(1)}';
if (clean.length == 12 && clean.startsWith('962'))
return clean;
if (clean.length == 9 && clean.startsWith('7'))
return '962$clean';
// Egypt: 010XXXXXXXX or 2010XXXXXXXX
if (clean.length == 11 && clean.startsWith('01'))
return '20${clean.substring(1)}';
if (clean.length == 13 && clean.startsWith('20'))
return clean;
return clean;
}
// عند البحث:
final normalizedPhone = normalizePhone(phoneInputController.text.trim());
final response = await CRUD().post(
link: apiUrl,
payload: {"phone": normalizedPhone},
);
وفي الباك إند (monitorRide.php و admin_get_rides_by_phone.php):
function normalizePhone($phone) {
$clean = preg_replace('/\D+/', '', $phone);
// Syria: remove leading 0 after country code
if (strlen($clean) === 10 && strpos($clean, '09') === 0) return '963' . substr($clean, 1);
if (strlen($clean) === 12 && strpos($clean, '963') === 0) return $clean;
if (strlen($clean) === 9 && strpos($clean, '9') === 0) return '963' . $clean;
// Jordan
if (strlen($clean) === 10 && strpos($clean, '07') === 0) return '962' . substr($clean, 1);
if (strlen($clean) === 12 && strpos($clean, '962') === 0) return $clean;
if (strlen($clean) === 9 && strpos($clean, '7') === 0) return '962' . $clean;
// Egypt
if (strlen($clean) === 11 && strpos($clean, '01') === 0) return '20' . substr($clean, 1);
if (strlen($clean) === 13 && strpos($clean, '20') === 0) return $clean;
return $clean;
}
🔴 الإصلاح 4: البحث في السائق والراكب معاً (مع جميع حالات الرحلة)
المشكلة: admin_get_rides_by_phone.php يبحث فقط في passengers وحالة Begin فقط.
الحل: تعديل admin_get_rides_by_phone.php و monitorRide.php ليشمل driver + passenger + جميع الحالات النشطة:
// backend/Admin/rides/admin_get_rides_by_phone.php - معدل
$phone = filterRequest('phone');
if (!$phone) { jsonError("Phone is required"); exit; }
$normalizedPhone = normalizePhone($phone);
$encPhone = $encryptionHelper->encryptData($normalizedPhone);
// 1) ابحث في driver
$driverStmt = $con->prepare("SELECT id FROM driver WHERE phone = :phone LIMIT 1");
$driverStmt->execute([':phone' => $encPhone]);
$driver = $driverStmt->fetch();
// 2) ابحث في passengers
$passengerStmt = $con->prepare("SELECT id FROM passengers WHERE phone = :phone LIMIT 1");
$passengerStmt->execute([':phone' => $encPhone]);
$passenger = $passengerStmt->fetch();
if (!$driver && !$passenger) {
jsonError('Phone number not found in system');
exit;
}
// 3) اجلب الرحلة حسب النوع
$userId = $driver ? $driver['id'] : $passenger['id'];
$userField = $driver ? 'r.driver_id' : 'r.passenger_id';
$filterStatus = filterRequest('status') ?: 'all';
$whereExtra = '';
if ($filterStatus !== 'all') {
$whereExtra = "AND r.status = :filter_status";
}
$rideStmt = $con->prepare("
SELECT r.*, d.first_name as d_fname, d.last_name as d_lname, d.phone as d_phone,
p.first_name as p_fname, p.last_name as p_lname, p.phone as p_phone
FROM ride r
LEFT JOIN driver d ON r.driver_id = d.id
LEFT JOIN passengers p ON r.passenger_id = p.id
WHERE $userField = :uid $whereExtra
ORDER BY r.id DESC
LIMIT 20
");
$params = [':uid' => $userId];
if ($filterStatus !== 'all') $params[':filter_status'] = $filterStatus;
$rideStmt->execute($params);
$rides = $rideStmt->fetchAll(PDO::FETCH_ASSOC);
🟡 الإصلاح 5: إضافة شاشة للرحلات المعلقة (Pending/Waiting)
المشكلة: لا توجد واجهة لعرض الرحلات العالقة (waiting, New, nothing).
الحل المقترح:
- إضافة تبويب خامس باسم "معلقة" في RidesDashboardScreen
- يعرض الرحلات ذات الحالة:
New,waiting,wait,nothing - إضافة زر "إلغاء الرحلة" مع إدخال سبب
- تحديث
admin_update_ride_status.phpليدعم الإلغاء مع إشعار
// إضافة في ride_lookup_page.dart (RidesListController)
void changeTab(String status) {
currentStatus = status;
searchController.clear();
fetchRides();
}
// إضافة في RidesDashboardScreen
Tab(text: 'معلقة', icon: Icon(Icons.hourglass_empty_rounded)),
// عند اختيار هذا التبويب، يرسل status='Pending'
// الـ API يتعامل معها كـ: IN ('New','waiting','wait','nothing')
🟢 الإصلاح 6: إضافة البحث برقم الرحلة (Ride ID) + Pagination
لماذا Ride ID هو الأفضل؟
- المعرف الوحيد الفريد (Primary Key)
- لا توجد مشاكل تشفير (الأرقام المعرفية غير مشفرة)
- لا توجد مشاكل تنسيق دولة
- دقيق 100%
مثال الإند بوينت الجديد:
// backend/Admin/rides/admin_get_ride_by_id.php
$rideId = filterRequest('id');
$stmt = $con->prepare("
SELECT r.*,
d.first_name as d_fname, d.last_name as d_lname, d.phone as d_phone,
p.first_name as p_fname, p.last_name as p_lname, p.phone as p_phone
FROM ride r
LEFT JOIN driver d ON r.driver_id = d.id
LEFT JOIN passengers p ON r.passenger_id = p.id
WHERE r.id = :id
LIMIT 1
");
$stmt->execute([':id' => $rideId]);
jsonSuccess($stmt->fetch());
Pagination في get_rides_by_status.php:
$page = (int)(filterRequest('page') ?? 1);
$limit = 50;
$offset = ($page - 1) * $limit;
$sql .= " ORDER BY r.id DESC LIMIT $limit OFFSET $offset";
الملخص النهائي
جدول حالات الرحلة - ما هو صحيح وما هو خاطئ:
| ما في النظام (DB) | ما في التطبيق (Admin) | التصحيح |
|---|---|---|
nothing / New |
New ✅ |
✅ صحيح (جديد) |
waiting / wait |
غير موجود ❌ | 🟡 يجب إضافته (معلق) |
Apply / Applied |
Begin (مصنف مع الجارية) ✅ |
✅ صحيح (جاري التوصيل) |
arrived / Arrived |
غير موجود ❌ | 🟡 يجب إضافته مع الجارية |
Begin |
Begin ✅ |
✅ صحيح (قيد التشغيل) |
Finished |
Completed ✅ |
✅ صحيح (مكتملة) |
Cancel / CancelFrom* / TimeOut |
Canceled (ناقص) ❌ |
🔴 يجب إضافة CancelFromDriver و CancelFromPassenger |
قائمة الإصلاحات:
| # | الإصلاح | الملف | الأولوية |
|---|---|---|---|
| 1 | تصحيح حالات الرحلة في get_rides_by_status.php |
backend/Admin/rides/get_rides_by_status.php |
🔴 عاجل |
| 2 | تصحيح statusOptions في ride_lookup_controller.dart |
siro_admin/lib/controller/rides/ride_lookup_controller.dart |
🔴 عاجل |
| 3 | تصحيح whitelist في admin_update_ride_status.php |
backend/Admin/rides/admin_update_ride_status.php |
🔴 عاجل |
| 4 | إضافة normalizePhone() في monitor_ride.dart |
siro_admin/lib/views/admin/drivers/monitor_ride.dart |
🔴 عاجل |
| 5 | إضافة normalizePhone() في admin_get_rides_by_phone.php |
backend/Admin/rides/admin_get_rides_by_phone.php |
🔴 عاجل |
| 6 | إضافة normalizePhone() في monitorRide.php |
backend/Admin/rides/monitorRide.php |
🔴 عاجل |
| 7 | إضافة البحث في driver + passenger في admin_get_rides_by_phone.php |
backend/Admin/rides/admin_get_rides_by_phone.php |
🟡 ضروري |
| 8 | إضافة شاشة للرحلات المعلقة (Pending/Waiting) | siro_admin/lib/views/admin/rides/ride_lookup_page.dart |
🟡 ضروري |
| 9 | إضافة البحث برقم الرحلة (Ride ID) | Endpoint + Flutter جديد | 🟡 ضروري |
| 10 | إضافة Pagination | backend/Admin/rides/get_rides_by_status.php |
🟢 مفيد |
أفضل طرق البحث (مرتبة حسب الأولوية):
- رقم الرحلة (Ride ID) — الأدق، بدون مشاكل تشفير أو دولة
- رقم هاتف الراكب/السائق — مع معالجة الدولة (normalizePhone)
- بحث بنطاق تاريخي — لاستعراض الرحلات حسب الفترة الزمنية