Update: 2026-07-25 18:43:44
This commit is contained in:
@@ -360,13 +360,13 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-i18n="ID">ID</th>
|
||||
<th data-i18n="Name">Name</th>
|
||||
<th data-i18n="Phone">Phone</th>
|
||||
<th data-i18n="Email">Email</th>
|
||||
<th data-i18n="Rating">Rating</th>
|
||||
<th data-i18n="Trips">Trips</th>
|
||||
<th data-i18n="Cancellations">Cancellations</th>
|
||||
<th data-i18n="Status">Status</th>
|
||||
<th>Name</th>
|
||||
<th>Phone</th>
|
||||
<th>Email</th>
|
||||
<th>Rating</th>
|
||||
<th>Trips</th>
|
||||
<th>Cancellations</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="driversTableBody"></tbody>
|
||||
@@ -398,13 +398,13 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-i18n="ID">ID</th>
|
||||
<th data-i18n="Name">Name</th>
|
||||
<th data-i18n="Contact">Contact</th>
|
||||
<th data-i18n="Trips">Trips</th>
|
||||
<th data-i18n="Rating">Rating</th>
|
||||
<th data-i18n="Cancellations">Cancellations</th>
|
||||
<th data-i18n="Joined">Joined</th>
|
||||
<th data-i18n="Status">Status</th>
|
||||
<th>Name</th>
|
||||
<th>Contact</th>
|
||||
<th>Trips</th>
|
||||
<th>Rating</th>
|
||||
<th>Cancellations</th>
|
||||
<th>Joined</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="passengersTableBody"></tbody>
|
||||
@@ -458,8 +458,8 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-i18n="ID">ID</th>
|
||||
<th data-i18n="Name">Name</th>
|
||||
<th data-i18n="Phone">Phone</th>
|
||||
<th>Name</th>
|
||||
<th>Phone</th>
|
||||
<th data-i18n="Type">Type</th>
|
||||
<th data-i18n="Requested role">Requested role</th>
|
||||
<th data-i18n="Requested at">Requested at</th>
|
||||
|
||||
@@ -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 @@
|
||||
</div>
|
||||
<div class="chart-container"><canvas id="growthChart"></canvas></div>
|
||||
${activeDays === 0
|
||||
? `<div class="table-msg">${t('Nobody signed up in the last 30 days.')}</div>`
|
||||
: `<div class="stamp" style="display:block;text-align:center;margin-top:0.5rem;">
|
||||
? `<div class="table-msg">${t('Nobody signed up in the last 30 days.')}</div>`
|
||||
: `<div class="stamp" style="display:block;text-align:center;margin-top:0.5rem;">
|
||||
${activeDays} / 30 ${lang === 'ar' ? 'يوماً بها تسجيل واحد على الأقل' : 'days had at least one signup'}
|
||||
</div>`}
|
||||
</div>`;
|
||||
@@ -2045,7 +1998,7 @@
|
||||
|
||||
<div class="kpi-tiles">
|
||||
${Object.entries(counts).map(([k, v]) =>
|
||||
`<div class="kpi-tile"><div class="kpi-tile-value">${esc(formatValue(v, k))}</div><div class="kpi-tile-label">${esc(humanize(k))}</div></div>`).join('')}
|
||||
`<div class="kpi-tile"><div class="kpi-tile-value">${esc(formatValue(v, k))}</div><div class="kpi-tile-label">${esc(humanize(k))}</div></div>`).join('')}
|
||||
</div>
|
||||
|
||||
<div class="sub-panel">
|
||||
@@ -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) => `
|
||||
<figure class="doc-card">
|
||||
${doc.link
|
||||
? `<a href="${esc(doc.link)}" target="_blank" rel="noopener">
|
||||
? `<a href="${esc(doc.link)}" target="_blank" rel="noopener">
|
||||
<img src="${esc(doc.link)}" alt="${esc(doc.doc_type || 'document')}" loading="lazy">
|
||||
</a>`
|
||||
: `<div class="doc-missing"><i class="ph ph-file-x"></i> ${lang === 'ar' ? 'لا ملف مرتبط' : 'no file linked'}</div>`}
|
||||
: `<div class="doc-missing"><i class="ph ph-file-x"></i> ${lang === 'ar' ? 'لا ملف مرتبط' : 'no file linked'}</div>`}
|
||||
<figcaption>
|
||||
<strong>${esc(humanize(doc.doc_type || 'document'))}</strong>
|
||||
<span class="stamp">${esc(doc.image_name || '—')}</span>
|
||||
</figcaption>
|
||||
</figure>`).join('')}
|
||||
</div>`
|
||||
: `<div class="table-msg">${lang === 'ar' ? 'هذا الكابتن لم يُرسل أي وثائق — الاعتماد الآن يعني تفعيل حساب غير موثّق.' : 'This captain has uploaded no documents — approving now would activate an unverified account.'}</div>`}
|
||||
: `<div class="table-msg">${lang === 'ar' ? 'هذا الكابتن لم يُرسل أي وثائق — الاعتماد الآن يعني تفعيل حساب غير موثّق.' : 'This captain has uploaded no documents — approving now would activate an unverified account.'}</div>`}
|
||||
</div>
|
||||
|
||||
<div class="sub-panel">
|
||||
@@ -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', () => {
|
||||
|
||||
Reference in New Issue
Block a user