From e03b9c30d5ee963e21772e32224f5bdba551a6c5 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Sat, 25 Jul 2026 18:43:44 +0300 Subject: [PATCH] Update: 2026-07-25 18:43:44 --- backend/Admin/AdminRide/getRidesPerMonth.php | 7 +- backend/Admin/driver/getBestDriver.php | 62 ++++++----- backend/Admin/driver/getDriverGiftPayment.php | 14 +-- backend/Admin/employee/get.php | 9 +- .../getPassengerDetailsByPassengerID.php | 6 +- backend/Admin/getPassengerbyEmail.php | 12 +-- .../Admin/rides/admin_get_rides_by_phone.php | 4 - backend/Admin/rides/monitorRide.php | 72 ++++++------- backend/Admin/v2/financial/settlements.php | 2 +- .../Admin/v2/quality/blacklist_manager.php | 1 + backend/Admin/v2/quality/driver_scorecard.php | 17 +-- backend/auth/driver/driver_details.php | 2 +- backend/auth/driver/drivers_pending_list.php | 2 +- backend/serviceapp/getPackages.php | 8 +- dashboard/siro-admin/index.html | 32 +++--- dashboard/siro-admin/js/app.js | 100 ++++-------------- 16 files changed, 144 insertions(+), 206 deletions(-) diff --git a/backend/Admin/AdminRide/getRidesPerMonth.php b/backend/Admin/AdminRide/getRidesPerMonth.php index 4c9fa32f..7b8c523d 100644 --- a/backend/Admin/AdminRide/getRidesPerMonth.php +++ b/backend/Admin/AdminRide/getRidesPerMonth.php @@ -43,5 +43,10 @@ foreach ($dailyRides as &$row) { $row['current_month_rides_count'] = $monthRides['current_month_rides_count']; } -jsonSuccess($dailyRides ?: []); +// Return result +if ($dailyRides) { + jsonSuccess($dailyRides); +} else { + jsonError("No records found"); +} ?> \ No newline at end of file diff --git a/backend/Admin/driver/getBestDriver.php b/backend/Admin/driver/getBestDriver.php index 5535a422..3aac1ff8 100644 --- a/backend/Admin/driver/getBestDriver.php +++ b/backend/Admin/driver/getBestDriver.php @@ -3,40 +3,46 @@ require_once __DIR__ . '/../../connect.php'; $sql = "SELECT - COUNT(r.id) AS driver_count, - d.id, - d.phone, - d.first_name, - d.last_name, - d.name_arabic -FROM driver d -LEFT JOIN ride r ON d.id = r.driver_id AND LOWER(r.status) IN ('finished','completed') -GROUP BY d.id, d.phone, d.first_name, d.last_name, d.name_arabic -ORDER BY driver_count DESC -LIMIT 20"; + COUNT(`car_locations`.driver_id) AS driver_count, + driver.id, + driver.phone, + driver.name_arabic, + MAX(dt.token) AS token +FROM + `car_locations` +LEFT JOIN driver ON driver.id = car_locations.driver_id +LEFT JOIN driverToken dt ON dt.captain_id = driver.id +WHERE + `car_locations`.created_at > TIMESTAMP(DATE_SUB(NOW(), INTERVAL 7 DAY)) +GROUP BY + driver.id +ORDER BY + driver_count DESC +LIMIT 19; +"; $stmt = $con->prepare($sql); $stmt->execute(); -$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); +if ($stmt->rowCount() > 0) { + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); -// فك التشفير للحقول الحساسة -foreach ($rows as &$row) { - if (!empty($row['phone'])) { - $row['phone'] = $encryptionHelper->decryptData($row['phone']) ?: $row['phone']; - } - if (!empty($row['first_name'])) { - $row['first_name'] = $encryptionHelper->decryptData($row['first_name']) ?: $row['first_name']; - } - if (!empty($row['last_name'])) { - $row['last_name'] = $encryptionHelper->decryptData($row['last_name']) ?: $row['last_name']; - } - if (!empty($row['name_arabic'])) { - $row['name_arabic'] = $encryptionHelper->decryptData($row['name_arabic']) ?: $row['name_arabic']; + // فك التشفير للحقول الحساسة + foreach ($rows as &$row) { + if (!empty($row['phone'])) { + $row['phone'] = $encryptionHelper->decryptData($row['phone']); + } + if (!empty($row['name_arabic'])) { + $row['name_arabic'] = $encryptionHelper->decryptData($row['name_arabic']); + } + if (!empty($row['token'])) { + $row['token'] = $encryptionHelper->decryptData($row['token']); + } } + + jsonSuccess($rows); +} else { + jsonError($message = "No recent driver location activity found"); } -unset($row); - -jsonSuccess($rows); ?> \ No newline at end of file diff --git a/backend/Admin/driver/getDriverGiftPayment.php b/backend/Admin/driver/getDriverGiftPayment.php index 2af90ccf..48316959 100644 --- a/backend/Admin/driver/getDriverGiftPayment.php +++ b/backend/Admin/driver/getDriverGiftPayment.php @@ -53,18 +53,14 @@ if ($stmt->rowCount() > 0) { $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); // Decrypt sensitive fields - $fieldsToDecrypt = ['phone', 'email', 'first_name', 'last_name', 'name_arabic', 'national_number', 'address', 'gender', 'site', 'birthdate']; foreach ($rows as &$row) { - foreach ($fieldsToDecrypt as $f) { - if (!empty($row[$f])) { - $dec = $encryptionHelper->decryptData($row[$f]); - if ($dec !== false && $dec !== null) { - $row[$f] = $dec; - } - } + if (!empty($row['phone'])) { + $row['phone'] = $encryptionHelper->decryptData($row['phone']); + } + if (!empty($row['name_arabic'])) { + $row['name_arabic'] = $encryptionHelper->decryptData($row['name_arabic']); } } - unset($row); jsonSuccess($rows); diff --git a/backend/Admin/employee/get.php b/backend/Admin/employee/get.php index 0fe835b0..0dd72e9c 100644 --- a/backend/Admin/employee/get.php +++ b/backend/Admin/employee/get.php @@ -18,5 +18,12 @@ $stmt->execute(); // Fetch all records as an associative array $employee_data = $stmt->fetchAll(PDO::FETCH_ASSOC); -jsonSuccess($employee_data ?: []); +// Check if any records were retrieved +if ($employee_data) { + // If records were found, print the data as JSON + jsonSuccess($data = $employee_data); +} else { + // If no records were found, print a failure message + jsonError($message = "No employee records found"); +} ?> \ No newline at end of file diff --git a/backend/Admin/getPassengerDetailsByPassengerID.php b/backend/Admin/getPassengerDetailsByPassengerID.php index 4085850b..9fe8a384 100644 --- a/backend/Admin/getPassengerDetailsByPassengerID.php +++ b/backend/Admin/getPassengerDetailsByPassengerID.php @@ -63,12 +63,14 @@ $sql = "SELECT FROM `passengers` WHERE - passengers.id = :pid + passengers.id = '$passengerID' +GROUP BY + `passengers`.`id` ORDER BY countPassengerRide DESC"; $stmt = $con->prepare($sql); -$stmt->execute([':pid' => $passengerID]); +$stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); // ✅ فك تشفير الحقول الحساسة diff --git a/backend/Admin/getPassengerbyEmail.php b/backend/Admin/getPassengerbyEmail.php index bc6a5f45..7ff59ba0 100644 --- a/backend/Admin/getPassengerbyEmail.php +++ b/backend/Admin/getPassengerbyEmail.php @@ -1,20 +1,18 @@ encryptData($rawEmail) : '___NON_EXISTENT___'; +$passengerEmail = $encryptionHelper->encryptData(filterRequest("passengerEmail")); $passengerId = filterRequest("passengerId"); -$passengerphone = !empty($rawPhone) ? $encryptionHelper->encryptData($rawPhone) : '___NON_EXISTENT___'; +$passengerphone = $encryptionHelper->encryptData(filterRequest("passengerphone")); + /** * الفهرس الأعمى: يسمح بالبحث بعد نقل التخزين إلى AES-GCM العشوائي. * تُبقى المقارنة القديمة في نفس الاستعلام كاحتياط حتى تنتهي تعبئة الفهارس. */ global $blindIndex; -$emailBidx = (!empty($rawEmail) && $blindIndex) ? $blindIndex->index('passengers.phone', $rawEmail) : null; -$phoneBidx = (!empty($rawPhone) && $blindIndex) ? $blindIndex->index('passengers.phone', $rawPhone) : null; +$emailBidx = $blindIndex ? $blindIndex->index('passengers.email', filterRequest("passengerEmail")) : null; +$phoneBidx = $blindIndex ? $blindIndex->index('passengers.phone', filterRequest("passengerphone")) : null; $sql = "SELECT `passengers`.`id`, diff --git a/backend/Admin/rides/admin_get_rides_by_phone.php b/backend/Admin/rides/admin_get_rides_by_phone.php index 0428f443..410318fe 100644 --- a/backend/Admin/rides/admin_get_rides_by_phone.php +++ b/backend/Admin/rides/admin_get_rides_by_phone.php @@ -22,10 +22,6 @@ $raw = normalizePhone($phone); // شَفِّر قبل الاستعلام $enc_raw = $encryptionHelper->encryptData($raw); -global $blindIndex; -$pBidx = $blindIndex ? $blindIndex->index('passengers.phone', $raw) : null; -$dBidx = $blindIndex ? $blindIndex->index('driver.phone', $raw) : null; - try { error_log("[get_last_ride] Searching phone normalized=$raw"); diff --git a/backend/Admin/rides/monitorRide.php b/backend/Admin/rides/monitorRide.php index bfefa32a..f50e164f 100644 --- a/backend/Admin/rides/monitorRide.php +++ b/backend/Admin/rides/monitorRide.php @@ -60,16 +60,16 @@ if ($driver) { } //------------------------------------------------------------------------ -// 2) جلب آخر رحلة حالتها نشطة +// 2) جلب آخر رحلة حالتها نشطة (Apply, Applied, Arrived, Begin) //------------------------------------------------------------------------ -$activeStatuses = "'apply','applied','arrived','begin','accepted','started','claimed','new','nothing','waiting','wait','pending','searching'"; +$activeStatuses = "'Apply','Applied','Arrived','arrived','Begin'"; if ($userType == 'driver') { error_log("[MONITOR_RIDE] 4. Searching for active ride for Driver ID: " . $driverID); $rideQuery = $con->prepare(" SELECT * FROM ride - WHERE driver_id = :driverID AND LOWER(status) IN ($activeStatuses) + WHERE driver_id = :driverID AND status IN ($activeStatuses) ORDER BY id DESC LIMIT 1 "); $rideQuery->execute([':driverID' => $driverID]); @@ -77,7 +77,7 @@ if ($userType == 'driver') { error_log("[MONITOR_RIDE] 4. Searching for active ride for Customer ID: " . $customerID); $rideQuery = $con->prepare(" SELECT * FROM ride - WHERE passenger_id = :customerID AND LOWER(status) IN ($activeStatuses) + WHERE passenger_id = :customerID AND status IN ($activeStatuses) ORDER BY id DESC LIMIT 1 "); $rideQuery->execute([':customerID' => $customerID]); @@ -100,28 +100,25 @@ if (!$ride) { $rideDriverID = $ride['driverID'] ?? $ride['driver_id']; error_log("[MONITOR_RIDE] 5. Fetching info for Driver ID from Ride: " . $rideDriverID); -$driverInfo = null; -if ($rideDriverID) { - $driverInfoQuery = $con->prepare(" - SELECT id, first_name, last_name, phone - FROM driver - WHERE id = :driverID - LIMIT 1 - "); +$driverInfoQuery = $con->prepare(" + SELECT id, first_name, last_name, phone + FROM driver + WHERE id = :driverID + LIMIT 1 +"); - $driverInfoQuery->execute([':driverID' => $rideDriverID]); - $driverInfo = $driverInfoQuery->fetch(PDO::FETCH_ASSOC); +$driverInfoQuery->execute([':driverID' => $rideDriverID]); +$driverInfo = $driverInfoQuery->fetch(PDO::FETCH_ASSOC); - if ($driverInfo) { - $driverInfo['phone'] = $encryptionHelper->decryptData($driverInfo['phone']); - $driverInfo['first_name'] = $encryptionHelper->decryptData($driverInfo['first_name']); - $driverInfo['last_name'] = $encryptionHelper->decryptData($driverInfo['last_name']); - $fullName = trim(($driverInfo['first_name'] ?? '') . " " . ($driverInfo['last_name'] ?? '')); - $driverInfo['fullname'] = $fullName ?: "Unknown Driver"; - error_log("[MONITOR_RIDE] 5. Driver Info Found: " . $fullName); - } else { - error_log("[MONITOR_RIDE] 5. WARNING: Driver info not found for ID " . $rideDriverID); - } +if ($driverInfo) { + $driverInfo['phone'] = $encryptionHelper->decryptData($driverInfo['phone']); + $driverInfo['first_name'] = $encryptionHelper->decryptData($driverInfo['first_name']); + $driverInfo['last_name'] = $encryptionHelper->decryptData($driverInfo['last_name']); + $fullName = $driverInfo['first_name'] . " " . $driverInfo['last_name']; + $driverInfo['fullname'] = $fullName; + error_log("[MONITOR_RIDE] 5. Driver Info Found: " . $fullName); +} else { + error_log("[MONITOR_RIDE] 5. WARNING: Driver info not found for ID " . $rideDriverID); } //------------------------------------------------------------------------ @@ -130,23 +127,14 @@ if ($rideDriverID) { error_log("[MONITOR_RIDE] 6. Querying Tracking DB for Driver ID: " . $rideDriverID); -$location = null; -if ($rideDriverID) { - try { - $trackingDb = null; - try { $trackingDb = Database::get('tracking'); } catch (Throwable $e) { $trackingDb = $con; } - $locationQuery = $trackingDb->prepare(" - SELECT latitude, longitude, speed, heading, updated_at - FROM car_locations - WHERE driver_id = :driverID AND status = 'ON' - ORDER BY updated_at DESC LIMIT 1 - "); - $locationQuery->execute([':driverID' => $rideDriverID]); - $location = $locationQuery->fetch(PDO::FETCH_ASSOC) ?: null; - } catch (Throwable $e) { - error_log("[MONITOR_RIDE] Tracking query exception: " . $e->getMessage()); - } -} +$locationQuery = $con_tracking->prepare(" + SELECT latitude, longitude, speed, heading, updated_at + FROM car_locations + WHERE driver_id = :driverID AND status = 'ON' + ORDER BY updated_at DESC LIMIT 1 +"); +$locationQuery->execute([':driverID' => $rideDriverID]); +$location = $locationQuery->fetch(PDO::FETCH_ASSOC); if ($location) { error_log("[MONITOR_RIDE] 6. Location Found: Lat=" . $location['latitude'] . " Lng=" . $location['longitude']); @@ -164,5 +152,7 @@ $response = [ "driver_location" => $location ?: "No live location" ]; +error_log("[MONITOR_RIDE] 7. Sending Success Response."); +jsonSuccess($response); error_log("[MONITOR_RIDE] 7. Sending Success Response."); jsonSuccess($response); \ No newline at end of file diff --git a/backend/Admin/v2/financial/settlements.php b/backend/Admin/v2/financial/settlements.php index 42028104..9fe905c6 100644 --- a/backend/Admin/v2/financial/settlements.php +++ b/backend/Admin/v2/financial/settlements.php @@ -18,7 +18,7 @@ try { COUNT(r.id) as total_rides FROM driver d LEFT JOIN ride r ON d.id = r.driver_id AND LOWER(r.status) IN ('finished','completed') - GROUP BY d.id, d.first_name, d.last_name, d.phone + GROUP BY d.id HAVING total_earned > 0 ORDER BY total_earned DESC LIMIT 50 diff --git a/backend/Admin/v2/quality/blacklist_manager.php b/backend/Admin/v2/quality/blacklist_manager.php index 8509899b..6b4d706e 100644 --- a/backend/Admin/v2/quality/blacklist_manager.php +++ b/backend/Admin/v2/quality/blacklist_manager.php @@ -2,6 +2,7 @@ // Admin/v2/quality/blacklist_manager.php require_once __DIR__ . '/../../../connect.php'; require_once __DIR__ . '/../../../encrypt_decrypt.php'; +require_once __DIR__ . '/../security/audit_logs_helper.php'; // إذا كان متاحاً، وإلا سننفذ الإدخال مباشرة if ($role !== 'admin' && $role !== 'super_admin') { jsonError("Unauthorized", 403); diff --git a/backend/Admin/v2/quality/driver_scorecard.php b/backend/Admin/v2/quality/driver_scorecard.php index d035d1a2..0a2b0312 100644 --- a/backend/Admin/v2/quality/driver_scorecard.php +++ b/backend/Admin/v2/quality/driver_scorecard.php @@ -10,22 +10,7 @@ if ($role !== 'admin' && $role !== 'super_admin') { $driver_id = filterRequest('driver_id'); if (!$driver_id) { - try { - $stmt = $con->prepare("SELECT id, first_name, last_name, phone, status FROM driver ORDER BY id DESC LIMIT 20"); - $stmt->execute(); - $drivers = $stmt->fetchAll(PDO::FETCH_ASSOC); - foreach ($drivers as &$d) { - if (!empty($d['first_name'])) $d['first_name'] = $encryptionHelper->decryptData($d['first_name']) ?: $d['first_name']; - if (!empty($d['last_name'])) $d['last_name'] = $encryptionHelper->decryptData($d['last_name']) ?: $d['last_name']; - if (!empty($d['phone'])) $d['phone'] = $encryptionHelper->decryptData($d['phone']) ?: $d['phone']; - } - unset($d); - jsonSuccess($drivers); - exit; - } catch (Throwable $e) { - jsonSuccess([]); - exit; - } + jsonError("Missing driver_id", 400); } try { diff --git a/backend/auth/driver/driver_details.php b/backend/auth/driver/driver_details.php index 356c345a..dd172238 100644 --- a/backend/auth/driver/driver_details.php +++ b/backend/auth/driver/driver_details.php @@ -1,5 +1,5 @@ prepare($sql); $stmt->execute(); $passenger_data = $stmt->fetchAll(PDO::FETCH_ASSOC); -jsonSuccess($passenger_data ?: []); +if ($passenger_data) { + // Print the passenger data as JSON + jsonSuccess($data = $passenger_data); +} else { + // Print a failure message + jsonError($message = "No passenger data found"); +} ?> \ No newline at end of file diff --git a/dashboard/siro-admin/index.html b/dashboard/siro-admin/index.html index ab21943e..690f9644 100644 --- a/dashboard/siro-admin/index.html +++ b/dashboard/siro-admin/index.html @@ -360,13 +360,13 @@ ID - Name - Phone - Email - Rating - Trips - Cancellations - Status + Name + Phone + Email + Rating + Trips + Cancellations + Status @@ -398,13 +398,13 @@ ID - Name - Contact - Trips - Rating - Cancellations - Joined - Status + Name + Contact + Trips + Rating + Cancellations + Joined + Status @@ -458,8 +458,8 @@ ID - Name - Phone + Name + Phone Type Requested role Requested at diff --git a/dashboard/siro-admin/js/app.js b/dashboard/siro-admin/js/app.js index 7e2288a6..2b466062 100644 --- a/dashboard/siro-admin/js/app.js +++ b/dashboard/siro-admin/js/app.js @@ -458,59 +458,12 @@ 'This browser is registered as a trusted device:': 'هذا المتصفح مسجّل كجهاز موثوق:', 'The endpoint responded successfully but returned no data yet.': 'استجاب الـ API بنجاح لكنه لم يُرجِع بياناتاً بعد.', 'No records recorded for this yet — the table is empty in the database.': 'لا توجد سجلات بعد — الجدول فارغ في قاعدة البيانات.', - // Database and API Field Translations - 'Total Revenue': 'إجمالي الإيرادات', - 'Company Profit': 'أرباح الشركة', - 'Total Driver Pay': 'إجمالي مستحقات السائقين', - 'Total Platform Commission': 'عمولة المنصة', - 'Cash Payments': 'الدفع النقدي', - 'Digital Payments': 'الدفع الرقمي', - 'Total Earned': 'إجمالي الأرباح', - 'First Name': 'الاسم الأول', - 'Last Name': 'اسم العائلة', - 'Full Name': 'الاسم الكامل', - 'Driver Id': 'معرّف السائق', - 'Passenger Id': 'معرّف الراكب', - 'Created At': 'تاريخ الإنشاء', - 'Updated At': 'تاريخ التحديث', - 'Birthdate': 'تاريخ الميلاد', - 'Gender': 'الجنس', - 'National Number': 'الرقم الوطني', - 'Address': 'العنوان', - 'Site': 'الموقع', - 'Active Routes': 'المسارات النشطة', - 'Active Enrollments': 'التسجيلات النشطة', - 'Average Pci': 'متوسط PCI', - 'Market Share Percent': 'نسبة الحصة السوقية', - 'Total Anomalies': 'حالات الشذوذ', - 'Total Surge Opportunities': 'فرص الفورة', - 'Report Date': 'تاريخ التقرير', - 'Date': 'التاريخ', - 'User Type': 'نوع المستخدم', - 'User': 'المستخدم', - 'Ride Details': 'تفاصيل الرحلة', - 'Driver Details': 'تفاصيل السائق', - 'Driver Location': 'موقع السائق', - 'Price': 'السعر', - 'Price For Driver': 'حصة السائق', - 'Price For Passenger': 'المبلغ من الراكب', - 'Distance': 'المسافة', - 'Payment Method': 'طريقة الدفع', - 'Car Type': 'نوع السيارة', - 'Start Location': 'موقع البداية', - 'End Location': 'موقع النهاية', - 'Cancel Reason': 'سبب الإلغاء', - 'Driver First Name': 'اسم السائق الأول', - 'Driver Last Name': 'اسم عائلة السائق', - 'Passenger First Name': 'اسم الراكب الأول', - 'Passenger Last Name': 'اسم عائلة الراكب', - 'Contact': 'معلومات الاتصال', - 'Click any row to open the full profile': 'اضغط على أي سطر لفتح الملف الشخصي الكامل', - 'Search by passenger ID, phone or email': 'البحث برقم الراكب، الهاتف، أو البريد الإلكتروني', - 'Search by captain ID, phone or email': 'البحث برقم الكابتن، الهاتف، أو البريد الإلكتروني', - 'Search rides by phone number': 'البحث في الرحلات برقم الهاتف', 'Yes': 'نعم', 'No': 'لا', + 'Click any row to open the full profile': 'اضغط على أي سطر لفتح الملف الشخصي الكامل', + 'Search rides by phone number': 'بحث في الرحلات برقم الهاتف', + 'Search by captain ID, phone or email': 'بحث بمعرّف الكابتن أو البريد الإلكتروني أو الهاتف', + 'Search by passenger ID, phone or email': 'بحث بمعرّف الراكب أو البريد الإلكتروني أو الهاتف', // API error messages ' — the endpoint returned HTML, check the API base URL': ' — الـ API أرجع HTML، تحقق من عنوان الخادم', 'Session rejected by the server': 'الخادم رفض الجلسة', @@ -1872,8 +1825,8 @@
${activeDays === 0 - ? `
${t('Nobody signed up in the last 30 days.')}
` - : `
+ ? `
${t('Nobody signed up in the last 30 days.')}
` + : `
${activeDays} / 30 ${lang === 'ar' ? 'يوماً بها تسجيل واحد على الأقل' : 'days had at least one signup'}
`}
`; @@ -2045,7 +1998,7 @@
${Object.entries(counts).map(([k, v]) => - `
${esc(formatValue(v, k))}
${esc(humanize(k))}
`).join('')} + `
${esc(formatValue(v, k))}
${esc(humanize(k))}
`).join('')}
@@ -2227,8 +2180,8 @@ trial_ends_at: $('orgTrialEnds').value, }; if (params.contract_status !== org.contract_status && - !confirm(`Change the contract from "${org.contract_status}" to "${params.contract_status}"? ` + - 'Suspending stops the organisation using the service.')) return; + !confirm(`Change the contract from "${org.contract_status}" to "${params.contract_status}"? ` + + 'Suspending stops the organisation using the service.')) return; await api('/Admin/transit/org/update.php', { params }); toast('Organisation updated.', 'success'); @@ -2728,17 +2681,17 @@ ${documents.map((doc) => `
${doc.link - ? ` + ? ` ${esc(doc.doc_type || 'document')} ` - : `
${lang === 'ar' ? 'لا ملف مرتبط' : 'no file linked'}
`} + : `
${lang === 'ar' ? 'لا ملف مرتبط' : 'no file linked'}
`}
${esc(humanize(doc.doc_type || 'document'))} ${esc(doc.image_name || '—')}
`).join('')}
` - : `
${lang === 'ar' ? 'هذا الكابتن لم يُرسل أي وثائق — الاعتماد الآن يعني تفعيل حساب غير موثّق.' : 'This captain has uploaded no documents — approving now would activate an unverified account.'}
`} + : `
${lang === 'ar' ? 'هذا الكابتن لم يُرسل أي وثائق — الاعتماد الآن يعني تفعيل حساب غير موثّق.' : 'This captain has uploaded no documents — approving now would activate an unverified account.'}
`}
@@ -3386,18 +3339,11 @@ } function humanize(key) { - if (!key) return ''; - const rawKey = String(key).trim(); - if (lang === 'ar' && AR[rawKey]) return AR[rawKey]; - - const s = rawKey + return String(key) .replace(/[_-]+/g, ' ') .replace(/([a-z])([A-Z])/g, '$1 $2') .replace(/\b\w/g, (m) => m.toUpperCase()) .trim(); - - if (lang === 'ar' && AR[s]) return AR[s]; - return s; } function msgNode(text) { @@ -3873,13 +3819,13 @@ // Maps a sidebar entry to the loader that owns its data. const VIEW_LOADERS = { - dashboardView: () => { loadStats().catch(() => {}); loadRidesTrend().catch(() => {}); }, - ridesView: () => loadRides().catch(() => {}), - driversView: () => loadDrivers().catch(() => {}), - passengersView: () => loadPassengers().catch(() => {}), - financialsView: () => loadStats().catch(() => {}), - complaintsView: () => loadStats().catch(() => {}), - approvalsView: () => loadApprovals().catch(() => {}), + dashboardView: () => { loadStats().catch(() => { }); loadRidesTrend().catch(() => { }); }, + ridesView: () => loadRides().catch(() => { }), + driversView: () => loadDrivers().catch(() => { }), + passengersView: () => loadPassengers().catch(() => { }), + financialsView: () => loadStats().catch(() => { }), + complaintsView: () => loadStats().catch(() => { }), + approvalsView: () => loadApprovals().catch(() => { }), systemView: () => renderSessionInfo(), }; @@ -3905,13 +3851,13 @@ else loadEverything(); }); $('langToggle')?.addEventListener('click', () => setLanguage(lang === 'ar' ? 'en' : 'ar')); - el.rideStatusFilter?.addEventListener('change', () => loadRides().catch(() => {})); + el.rideStatusFilter?.addEventListener('change', () => loadRides().catch(() => { })); el.driversPrev?.addEventListener('click', () => { - if (driversPage > 1) { driversPage--; loadDrivers().catch(() => {}); } + if (driversPage > 1) { driversPage--; loadDrivers().catch(() => { }); } }); el.driversNext?.addEventListener('click', () => { - if (driversPage < driversPages) { driversPage++; loadDrivers().catch(() => {}); } + if (driversPage < driversPages) { driversPage++; loadDrivers().catch(() => { }); } }); el.ridesMore?.addEventListener('click', () => {