Update: 2026-07-09 01:55:25
This commit is contained in:
@@ -159,6 +159,9 @@ class FirebaseMessagesController extends GetxController {
|
||||
'DriverList': myList,
|
||||
'body': body,
|
||||
'is_destination_match': message.data['is_destination_match'] ?? '0',
|
||||
// 🆕 "أرباحك أعلى" — يُرسَل فقط عند وجود فرق إيجابي حقيقي
|
||||
'driver_earnings_extra': message.data['driver_earnings_extra'],
|
||||
'driver_earnings_currency': message.data['driver_earnings_currency'],
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -411,6 +411,9 @@ class LocationController extends GetxController with WidgetsBindingObserver {
|
||||
'DriverList': driverList,
|
||||
'body': 'New Trip Request via Socket ⚡',
|
||||
'is_destination_match': rideData['is_destination_match'] ?? '0',
|
||||
// 🆕 "أرباحك أعلى" — نفس الحقل الجاي من FCM، متوفر أيضاً عبر السوكيت
|
||||
'driver_earnings_extra': rideData['driver_earnings_extra'],
|
||||
'driver_earnings_currency': rideData['driver_earnings_currency'],
|
||||
});
|
||||
} else {
|
||||
Log.print(
|
||||
|
||||
@@ -65,6 +65,10 @@ class OrderRequestController extends GetxController
|
||||
String tripPrice = "--";
|
||||
bool isDestinationMatch = false; // 🆕 Destination Match flag
|
||||
|
||||
// 🆕 Driver Earnings Advantage — "أرباحك أعلى" badge
|
||||
double? driverEarningsExtra;
|
||||
String driverEarningsCurrency = 'ل.س';
|
||||
|
||||
String timeToPassenger = "Calculating...".tr;
|
||||
String distanceToPassenger = "--";
|
||||
|
||||
@@ -165,6 +169,7 @@ class OrderRequestController extends GetxController
|
||||
args['is_destination_match'] == true) {
|
||||
isDestinationMatch = true;
|
||||
}
|
||||
_parseEarningsData(args);
|
||||
}
|
||||
// ب) هل هي قادمة من Socket بالمفاتيح الرقمية ("0", "1", ...)؟
|
||||
else {
|
||||
@@ -175,6 +180,7 @@ class OrderRequestController extends GetxController
|
||||
args['is_destination_match'] == true) {
|
||||
isDestinationMatch = true;
|
||||
}
|
||||
_parseEarningsData(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,6 +195,21 @@ class OrderRequestController extends GetxController
|
||||
"📍 Parsed Coordinates: Pax($latPassenger, $lngPassenger) -> Dest($latDestination, $lngDestination)");
|
||||
}
|
||||
|
||||
/// 🆕 يقرأ حقل "أرباحك أعلى" من بيانات الطلب (FCM أو Socket) إن وُجد
|
||||
void _parseEarningsData(Map args) {
|
||||
final rawExtra = args['driver_earnings_extra'];
|
||||
if (rawExtra != null) {
|
||||
final parsed = double.tryParse(rawExtra.toString());
|
||||
if (parsed != null && parsed > 0) {
|
||||
driverEarningsExtra = parsed;
|
||||
}
|
||||
}
|
||||
final rawCurrency = args['driver_earnings_currency'];
|
||||
if (rawCurrency != null && rawCurrency.toString().isNotEmpty) {
|
||||
driverEarningsCurrency = rawCurrency.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/// 🔥 دالة ذكية تجلب القيمة سواء كانت البيانات في List أو Map
|
||||
dynamic _getValueAt(int index) {
|
||||
// الأولوية للقائمة
|
||||
|
||||
@@ -24,6 +24,10 @@ class OrderData {
|
||||
final String? rawStartCoordinates;
|
||||
final String? rawEndCoordinates;
|
||||
|
||||
// 🆕 "أرباحك أعلى" — الفرق الإيجابي بأجرة السائق مقارنة بالمنافس (إن وُجد)
|
||||
final double? driverEarningsExtra;
|
||||
final String? driverEarningsCurrency;
|
||||
|
||||
OrderData({
|
||||
required this.customerName,
|
||||
required this.customerToken,
|
||||
@@ -40,6 +44,8 @@ class OrderData {
|
||||
required this.passengerRate,
|
||||
this.rawStartCoordinates,
|
||||
this.rawEndCoordinates,
|
||||
this.driverEarningsExtra,
|
||||
this.driverEarningsCurrency,
|
||||
});
|
||||
|
||||
// --- NEW: Factory constructor to create an instance from a Map ---
|
||||
@@ -74,6 +80,8 @@ class OrderData {
|
||||
// For nullable strings, direct access is fine as it returns null if the key doesn't exist
|
||||
rawStartCoordinates: map['rawStartCoordinates'],
|
||||
rawEndCoordinates: map['rawEndCoordinates'],
|
||||
driverEarningsExtra: (map['driverEarningsExtra'] as num?)?.toDouble(),
|
||||
driverEarningsCurrency: map['driverEarningsCurrency']?.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,6 +126,15 @@ class OrderData {
|
||||
|
||||
rawStartCoordinates: list.isNotEmpty ? list[0].toString() : null,
|
||||
rawEndCoordinates: list.length > 1 ? list[1].toString() : null,
|
||||
|
||||
// 🆕 Index 35/36: "أرباحك أعلى"
|
||||
driverEarningsExtra: list.length > 35 && list[35].toString().isNotEmpty
|
||||
? double.tryParse(list[35].toString())
|
||||
: null,
|
||||
driverEarningsCurrency:
|
||||
list.length > 36 && list[36].toString().isNotEmpty
|
||||
? list[36].toString()
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -182,6 +199,8 @@ class OrderData {
|
||||
'passengerRate': passengerRate,
|
||||
'rawStartCoordinates': rawStartCoordinates,
|
||||
'rawEndCoordinates': rawEndCoordinates,
|
||||
'driverEarningsExtra': driverEarningsExtra,
|
||||
'driverEarningsCurrency': driverEarningsCurrency,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,6 +529,40 @@ class _OrderOverlayState extends State<OrderOverlay>
|
||||
),
|
||||
],
|
||||
),
|
||||
// 🆕 "أرباحك أعلى" — يظهر فقط إذا في فرق إيجابي حقيقي من الباك اند
|
||||
if (order.driverEarningsExtra != null &&
|
||||
order.driverEarningsExtra! > 0) ...[
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.priceHighlight.withOpacity(0.12),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: AppColors.priceHighlight.withOpacity(0.35),
|
||||
width: 1),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.trending_up_rounded,
|
||||
color: AppColors.priceHighlight, size: 16),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
"أرباحك أعلى بـ ${order.driverEarningsExtra!.toStringAsFixed(2)} ${order.driverEarningsCurrency ?? ''} من التطبيقات الثانية"
|
||||
.tr,
|
||||
style: const TextStyle(
|
||||
color: AppColors.priceHighlight,
|
||||
fontSize: 11.5,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
Divider(color: AppColors.gray.withOpacity(0.2), thickness: 1),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
@@ -238,14 +238,16 @@ class OrderRequestPage extends StatelessWidget {
|
||||
),
|
||||
|
||||
// ── Earnings Compare Badge ──────────────────
|
||||
// يتم جلبه من API مشابه أو يمكن ربطه ببيانات الكنترولر لاحقاً.
|
||||
// نتركه متاحاً للتحديث عبر الكنترولر (controller.driverBadgeText, controller.extraEarnings).
|
||||
// سنستخدم قيم افتراضية للتأكد من الريندر (UI render) الآن
|
||||
// سيتم تفعيله من الباك إند
|
||||
// مصدر البيانات: driver_earnings_extra/currency القادمة من add_ride.php
|
||||
// (عبر FCM أو Socket) — controller.driverEarningsExtra يبقى null إذا
|
||||
// ما في فرق إيجابي حقيقي، فالويدجت نفسه بيختفي تلقائياً.
|
||||
const SizedBox(height: 5),
|
||||
const DriverEarningsBadge(
|
||||
earningsLabel: "أرباحك أعلى هنا مقارنة بـ المنافسين",
|
||||
extraAmount: 2.50, // القيمة هنا ستُسحب من الـ Socket / API قريباً
|
||||
DriverEarningsBadge(
|
||||
earningsLabel: controller.driverEarningsExtra != null
|
||||
? "أرباحك أعلى هنا مقارنة بـ المنافسين"
|
||||
: null,
|
||||
extraAmount: controller.driverEarningsExtra,
|
||||
currency: controller.driverEarningsCurrency,
|
||||
),
|
||||
|
||||
const SizedBox(height: 15),
|
||||
|
||||
@@ -110,6 +110,13 @@ class RideAvailableCard extends StatelessWidget {
|
||||
|
||||
const RideAvailableCard({Key? key, required this.rideInfo}) : super(key: key);
|
||||
|
||||
/// يحوّل driver_earnings_extra (نص من الـ Socket) إلى double، أو null إن لم يوجد
|
||||
double? get _earningsExtra {
|
||||
final raw = rideInfo['driver_earnings_extra'];
|
||||
if (raw == null) return null;
|
||||
return double.tryParse(raw.toString());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
@@ -128,10 +135,16 @@ class RideAvailableCard extends StatelessWidget {
|
||||
const Divider(height: 24, thickness: 0.5),
|
||||
_buildRideDetails(),
|
||||
const SizedBox(height: 12),
|
||||
// ── إضافة شارة الأرباح هنا ──
|
||||
const DriverEarningsBadge(
|
||||
earningsLabel: "أرباحك أعلى هنا مقارنة بـ المنافسين",
|
||||
extraAmount: 2.50, // القيمة هنا ستُسحب من الـ Socket / API قريباً
|
||||
// ── شارة الأرباح — مصدرها rideInfo['driver_earnings_extra'] القادم
|
||||
// من add_ride.php (broadcastRideToMarket عبر Socket). ملاحظة: الرحلات
|
||||
// المجلوبة من الجلب الأولي (getRideWaiting.php) ما زالت لا تحمل هذا
|
||||
// الحقل، فالشارة بتختفي تلقائياً لحد ما تُحدَّث تلك النقطة لاحقاً.
|
||||
DriverEarningsBadge(
|
||||
earningsLabel: _earningsExtra != null
|
||||
? "أرباحك أعلى هنا مقارنة بـ المنافسين"
|
||||
: null,
|
||||
extraAmount: _earningsExtra,
|
||||
currency: rideInfo['driver_earnings_currency']?.toString() ?? 'ل.س',
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_buildAcceptButton(),
|
||||
|
||||
Reference in New Issue
Block a user