26-1-20/1
This commit is contained in:
@@ -1,97 +1,108 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'dart:math';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart'; // لتحديد الأنواع إذا لزم
|
||||
|
||||
import '../../constant/box_name.dart';
|
||||
import '../../constant/colors.dart';
|
||||
import '../../constant/links.dart';
|
||||
import '../../constant/style.dart';
|
||||
import '../../controller/firebase/firbase_messge.dart';
|
||||
import '../../controller/firebase/notification_service.dart';
|
||||
import '../../controller/functions/crud.dart';
|
||||
import '../../controller/home/captin/home_captain_controller.dart';
|
||||
import '../../controller/notification/ride_available_controller.dart';
|
||||
import '../../main.dart';
|
||||
import '../../main.dart'; // للوصول للـ box
|
||||
import '../home/Captin/driver_map_page.dart';
|
||||
import '../widgets/my_scafold.dart';
|
||||
import '../widgets/mycircular.dart';
|
||||
import '../widgets/mydialoug.dart';
|
||||
|
||||
// --- Placeholder Classes and Variables (for demonstration) ---
|
||||
// These are dummy implementations to make the code runnable.
|
||||
// You should use your actual project files.
|
||||
|
||||
// --- End of Placeholder Classes ---
|
||||
|
||||
class AvailableRidesPage extends StatelessWidget {
|
||||
const AvailableRidesPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Use findOrPut to avoid re-creating the controller on rebuilds
|
||||
// حقن الكنترولر (تأكد أنك تستخدم الكود الجديد الذي أعطيتك إياه للكنترولر)
|
||||
Get.lazyPut(() => RideAvailableController());
|
||||
Get.lazyPut(() => HomeCaptainController());
|
||||
|
||||
return GetBuilder<RideAvailableController>(
|
||||
builder: (rideAvailableController) {
|
||||
// rideAvailableController.sortRidesByDistance(); // Original logic
|
||||
return MyScafolld(
|
||||
builder: (controller) {
|
||||
return MyScafolld(
|
||||
title: 'Available for rides'.tr,
|
||||
isleading: true,
|
||||
body: [
|
||||
rideAvailableController.isLoading
|
||||
? const MyCircularProgressIndicator()
|
||||
controller.isLoading
|
||||
? const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 50.0),
|
||||
child: MyCircularProgressIndicator(),
|
||||
))
|
||||
: Builder(
|
||||
builder: (context) {
|
||||
// Filtering logic remains the same
|
||||
final filteredRides = rideAvailableController
|
||||
.rideAvailableMap['message']
|
||||
.where((rideInfo) {
|
||||
var driverType =
|
||||
box.read(BoxName.carTypeOfDriver).toString();
|
||||
switch (driverType) {
|
||||
case 'Comfort':
|
||||
return ['Speed', 'Comfort']
|
||||
.contains(rideInfo['carType']);
|
||||
case 'Speed':
|
||||
case 'Scooter':
|
||||
case 'Awfar Car':
|
||||
return rideInfo['carType'] == driverType;
|
||||
case 'Lady':
|
||||
return ['Comfort', 'Speed', 'Lady']
|
||||
.contains(rideInfo['carType']);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}).toList();
|
||||
// 1. الفلترة حسب نوع السيارة (تم نقل المنطق للكنترولر، لكن هنا للعرض فقط)
|
||||
// الكنترولر الجديد يفلتر عند الإضافة، لكن لا ضرر من التأكيد هنا
|
||||
final ridesList = controller.availableRides;
|
||||
|
||||
if (filteredRides.isEmpty) {
|
||||
if (ridesList.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
"No rides available for your vehicle type.".tr,
|
||||
style: AppStyle.subtitle,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 100),
|
||||
Icon(CupertinoIcons.car_detailed,
|
||||
size: 60,
|
||||
color:
|
||||
AppColor.primaryColor.withOpacity(0.5)),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
"No rides available right now.".tr,
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => controller.getRideAvailable(
|
||||
forceRefresh: true),
|
||||
icon: const Icon(Icons.refresh),
|
||||
label: Text("Refresh Market".tr),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColor.primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 16),
|
||||
itemCount: filteredRides.length,
|
||||
itemBuilder: (context, index) {
|
||||
return RideAvailableCard(
|
||||
rideInfo: filteredRides[index],
|
||||
);
|
||||
// 2. عرض القائمة
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await controller.getRideAvailable(forceRefresh: true);
|
||||
},
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 16),
|
||||
itemCount: ridesList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return RideAvailableCard(
|
||||
rideInfo: ridesList[index],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
isleading: true);
|
||||
});
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// بطاقة الرحلة (The Card)
|
||||
// =============================================================================
|
||||
class RideAvailableCard extends StatelessWidget {
|
||||
final Map<String, dynamic> rideInfo;
|
||||
|
||||
@@ -99,50 +110,45 @@ class RideAvailableCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// The main card with improved styling
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 16.0),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
elevation: 5,
|
||||
elevation: 4,
|
||||
shadowColor: Colors.black.withOpacity(0.1),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () {
|
||||
// You can add an action here, e.g., show ride details on a map
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildHeader(),
|
||||
const SizedBox(height: 16),
|
||||
_buildRouteInfo(),
|
||||
const Divider(height: 32),
|
||||
_buildRideDetails(),
|
||||
const SizedBox(height: 20),
|
||||
_buildAcceptButton(),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildHeader(),
|
||||
const SizedBox(height: 16),
|
||||
_buildRouteInfo(),
|
||||
const Divider(height: 24, thickness: 0.5),
|
||||
_buildRideDetails(),
|
||||
const SizedBox(height: 20),
|
||||
_buildAcceptButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Header section with Price and Car Type
|
||||
// ---------------------------------------------------------------------------
|
||||
// تصميم البطاقة (Header, Route, Details)
|
||||
// ---------------------------------------------------------------------------
|
||||
Widget _buildHeader() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Fare'.tr, style: AppStyle.subtitle.copyWith(fontSize: 12)),
|
||||
const SizedBox(height: 4),
|
||||
Text('${rideInfo['price']} \$',
|
||||
style: AppStyle.title
|
||||
.copyWith(fontSize: 24, color: AppColor.primaryColor)),
|
||||
Text('Price'.tr, style: AppStyle.subtitle.copyWith(fontSize: 12)),
|
||||
Text(
|
||||
'${rideInfo['price']} ${'SYP'.tr}', // العملة
|
||||
style: AppStyle.title.copyWith(
|
||||
fontSize: 20, color: AppColor.primaryColor, height: 1.2),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
@@ -150,48 +156,49 @@ class RideAvailableCard extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.greenColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(color: AppColor.greenColor.withOpacity(0.3)),
|
||||
),
|
||||
child: Text(
|
||||
rideInfo['carType'],
|
||||
rideInfo['carType'] ?? 'Fixed Price'.tr,
|
||||
style: AppStyle.title
|
||||
.copyWith(color: AppColor.greenColor, fontSize: 12),
|
||||
.copyWith(color: AppColor.greenColor, fontSize: 13),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Visual representation of the pickup and dropoff route
|
||||
Widget _buildRouteInfo() {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Dotted line and icons column
|
||||
Column(
|
||||
children: [
|
||||
const Icon(CupertinoIcons.circle_fill,
|
||||
color: AppColor.greenColor, size: 20),
|
||||
...List.generate(
|
||||
4,
|
||||
(index) => Container(
|
||||
height: 4,
|
||||
width: 2,
|
||||
color: AppColor.writeColor,
|
||||
margin: const EdgeInsets.symmetric(vertical: 2),
|
||||
)),
|
||||
const Icon(CupertinoIcons.location_solid,
|
||||
color: Colors.red, size: 20),
|
||||
const Icon(Icons.my_location,
|
||||
color: AppColor.primaryColor, size: 18),
|
||||
Container(
|
||||
height: 30,
|
||||
width: 1,
|
||||
color: Colors.grey.shade300,
|
||||
margin: const EdgeInsets.symmetric(vertical: 4),
|
||||
),
|
||||
const Icon(Icons.location_on, color: Colors.red, size: 18),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
// Location text column
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildLocationText(rideInfo['startName'], 'Pickup'.tr),
|
||||
const SizedBox(height: 20),
|
||||
_buildLocationText(rideInfo['endName'], 'Dropoff'.tr),
|
||||
Text(rideInfo['startName'] ?? 'Unknown Location'.tr,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: AppStyle.title.copyWith(fontSize: 14)),
|
||||
const SizedBox(height: 22),
|
||||
Text(rideInfo['endName'] ?? 'Destination'.tr,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: AppStyle.title.copyWith(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -199,172 +206,164 @@ class RideAvailableCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// Helper for location text
|
||||
Widget _buildLocationText(String location, String label) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(label, style: AppStyle.subtitle.copyWith(fontSize: 12)),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
location,
|
||||
style: AppStyle.title.copyWith(fontWeight: FontWeight.normal),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Ride details section with Distance and Passenger Rating
|
||||
Widget _buildRideDetails() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
_buildInfoChip(
|
||||
icon: CupertinoIcons.map_pin_ellipse,
|
||||
value: '${rideInfo['distance']} ${'KM'.tr}',
|
||||
label: 'Distance'.tr,
|
||||
color: AppColor.primaryColor,
|
||||
),
|
||||
_buildInfoChip(
|
||||
icon: CupertinoIcons.star_fill,
|
||||
value: '${rideInfo['passengerRate']}',
|
||||
label: 'Rating'.tr,
|
||||
color: Colors.amber,
|
||||
),
|
||||
_infoItem(Icons.social_distance, '${rideInfo['distance']} KM'),
|
||||
_infoItem(Icons.access_time, '${rideInfo['duration']} Min'),
|
||||
_infoItem(Icons.star, '${rideInfo['passengerRate'] ?? 5.0}',
|
||||
iconColor: Colors.amber),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// A reusable chip for displaying info with an icon
|
||||
Widget _buildInfoChip(
|
||||
{required IconData icon,
|
||||
required String value,
|
||||
required String label,
|
||||
required Color color}) {
|
||||
return Column(
|
||||
Widget _infoItem(IconData icon, String text,
|
||||
{Color iconColor = Colors.grey}) {
|
||||
return Row(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(icon, color: color, size: 16),
|
||||
const SizedBox(width: 8),
|
||||
Text(value, style: AppStyle.title),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(label, style: AppStyle.subtitle.copyWith(fontSize: 12)),
|
||||
Icon(icon, size: 16, color: iconColor),
|
||||
const SizedBox(width: 4),
|
||||
Text(text, style: AppStyle.subtitle.copyWith(fontSize: 13)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// The accept button with improved styling
|
||||
// ---------------------------------------------------------------------------
|
||||
// زر القبول والمنطق الكامل (Accept Logic) 🔥
|
||||
// ---------------------------------------------------------------------------
|
||||
Widget _buildAcceptButton() {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton.icon(
|
||||
icon: const Icon(Icons.check_circle_outline, color: Colors.white),
|
||||
label: Text('Accept'.tr,
|
||||
style: const TextStyle(
|
||||
color: Colors.white, fontWeight: FontWeight.bold)),
|
||||
onPressed: _acceptRide,
|
||||
height: 50,
|
||||
child: ElevatedButton(
|
||||
onPressed: _acceptRideNewLogic,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColor.greenColor,
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
shape:
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
elevation: 2,
|
||||
),
|
||||
child: Text(
|
||||
'Accept Ride'.tr,
|
||||
style: const TextStyle(
|
||||
color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// --- Ride Acceptance Logic ---
|
||||
// This logic is copied exactly from your original code.
|
||||
void _acceptRide() async {
|
||||
var res = await CRUD().post(
|
||||
link: '${AppLink.endPoint}rides/updateStausFromSpeed.php',
|
||||
// 🔥🔥🔥 الوظيفة الأهم: قبول الرحلة وتجهيز البيانات 🔥🔥🔥
|
||||
void _acceptRideNewLogic() async {
|
||||
// 1. إظهار Loading
|
||||
Get.dialog(
|
||||
const Center(child: MyCircularProgressIndicator()),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
|
||||
try {
|
||||
String driverId = box.read(BoxName.driverID).toString();
|
||||
|
||||
// 2. إرسال الطلب للسيرفر (acceptRide.php الجديد)
|
||||
var response = await CRUD().post(
|
||||
link: "${AppLink.ride}/rides/acceptRide.php",
|
||||
payload: {
|
||||
'id': rideInfo['id'],
|
||||
'rideTimeStart': DateTime.now().toString(),
|
||||
'status': 'Apply',
|
||||
'driver_id': box.read(BoxName.driverID),
|
||||
});
|
||||
|
||||
if (res != "failure") {
|
||||
List<String> bodyToPassenger = [
|
||||
box.read(BoxName.driverID).toString(),
|
||||
box.read(BoxName.nameDriver).toString(),
|
||||
box.read(BoxName.tokenDriver).toString(),
|
||||
];
|
||||
box.write(BoxName.statusDriverLocation, 'on');
|
||||
await CRUD().postFromDialogue(link: AppLink.addDriverOrder, payload: {
|
||||
'driver_id': box.read(BoxName.driverID),
|
||||
'order_id': rideInfo['id'],
|
||||
'status': 'Apply'
|
||||
});
|
||||
// await CRUD().post(link: AppLink.updateRides, payload: {
|
||||
// 'id': rideInfo['id'],
|
||||
// 'DriverIsGoingToPassenger': DateTime.now().toString(),
|
||||
// 'status': 'Applied'
|
||||
// });
|
||||
await CRUD().post(
|
||||
link: AppLink.updateWaitingRide,
|
||||
payload: {'id': rideInfo['id'], 'status': 'Applied'});
|
||||
// if (AppLink.endPoint.toString() != AppLink.seferCairoServer) {
|
||||
|
||||
NotificationService.sendNotification(
|
||||
target: rideInfo['passengerToken'].toString(),
|
||||
title: 'Accepted Ride'.tr,
|
||||
body: 'your ride is Accepted'.tr,
|
||||
isTopic: false, // Important: this is a token
|
||||
tone: 'start',
|
||||
driverList: bodyToPassenger, category: 'Accepted Ride',
|
||||
'id': rideInfo['id'].toString(),
|
||||
'driver_id': driverId,
|
||||
'status': 'Apply', // الحالة المتفق عليها
|
||||
'passengerToken': rideInfo['passengerToken'].toString(),
|
||||
},
|
||||
);
|
||||
Get.back();
|
||||
Get.to(() => PassengerLocationMapPage(), arguments: {
|
||||
'passengerLocation': rideInfo['start_location'].toString(),
|
||||
'passengerDestination': rideInfo['end_location'].toString(),
|
||||
'Duration': rideInfo['duration'].toString(),
|
||||
'totalCost': rideInfo['price'].toString(),
|
||||
'Distance': rideInfo['distance'].toString(),
|
||||
'name': rideInfo['first_name'].toString(),
|
||||
'phone': rideInfo['phone'].toString(),
|
||||
'email': rideInfo['email'].toString(),
|
||||
'WalletChecked': rideInfo['payment_method'].toString(),
|
||||
'tokenPassenger': rideInfo['passengerToken'].toString(),
|
||||
'direction':
|
||||
'https://www.google.com/maps/dir/${rideInfo['start_location']}/${rideInfo['end_location']}/',
|
||||
'DurationToPassenger': rideInfo['duration'].toString(),
|
||||
'rideId': rideInfo['id'].toString(),
|
||||
'passengerId': rideInfo['passenger_id'].toString(),
|
||||
'driverId': box.read(BoxName.driverID).toString(),
|
||||
'durationOfRideValue': rideInfo['duration'].toString(),
|
||||
'paymentAmount': rideInfo['price'].toString(),
|
||||
'paymentMethod': 'cash'.toString() == 'true' ? 'visa' : 'cash',
|
||||
'isHaveSteps': 'startEnd'.toString(),
|
||||
'step0': ''.toString(),
|
||||
'step1': ''.toString(),
|
||||
'step2': ''.toString(),
|
||||
'step3': ''.toString(),
|
||||
'step4': ''.toString(),
|
||||
'passengerWalletBurc': rideInfo['bruc'].toString(),
|
||||
'timeOfOrder': DateTime.now().toString(),
|
||||
'totalPassenger': rideInfo['price'].toString(),
|
||||
'carType': rideInfo['carType'].toString(),
|
||||
'kazan': Get.find<HomeCaptainController>().kazan.toString(),
|
||||
'startNameLocation': rideInfo['startName'].toString(),
|
||||
'endNameLocation': rideInfo['endName'].toString(),
|
||||
});
|
||||
} else {
|
||||
MyDialog().getDialog(
|
||||
"This ride is already taken by another driver.".tr, '', () {
|
||||
CRUD().post(
|
||||
link: AppLink.deleteAvailableRide, payload: {'id': rideInfo['id']});
|
||||
|
||||
Get.back();
|
||||
});
|
||||
// إخفاء الـ Loading
|
||||
Get.back();
|
||||
|
||||
// 3. تحليل الرد
|
||||
var jsonResponse = jsonDecode(response);
|
||||
|
||||
if (jsonResponse['status'] == 'success') {
|
||||
// ✅ نجاح: أنت الفائز بالرحلة
|
||||
|
||||
// تحديث حالة السائق محلياً
|
||||
Get.find<HomeCaptainController>().changeRideId();
|
||||
box.write(BoxName.statusDriverLocation, 'on');
|
||||
|
||||
// 🔥 تجهيز الـ Arguments كاملة (Mapping) 📦
|
||||
// نأخذ البيانات من rideInfo (القادمة من getRideWaiting) ونمررها للخريطة
|
||||
Map<String, dynamic> fullRideArgs = {
|
||||
// معرفات الرحلة
|
||||
'rideId': rideInfo['id'].toString(),
|
||||
'passengerId': rideInfo['passengerId'].toString(),
|
||||
'driverId': driverId,
|
||||
|
||||
// المواقع (يجب أن تكون Strings بصيغة "lat,lng")
|
||||
'passengerLocation': rideInfo['start_location'].toString(),
|
||||
'passengerDestination': rideInfo['end_location'].toString(),
|
||||
|
||||
// الأسماء والعناوين
|
||||
'startNameLocation': rideInfo['startName'].toString(),
|
||||
'endNameLocation': rideInfo['endName'].toString(),
|
||||
|
||||
// تفاصيل الراكب
|
||||
'name': rideInfo['first_name'] ?? 'Passenger',
|
||||
'phone': rideInfo['phone'].toString(),
|
||||
'email': rideInfo['email'] ?? '',
|
||||
'tokenPassenger': rideInfo['passengerToken'].toString(),
|
||||
'passengerWalletBurc': rideInfo['bruc'].toString(), // رصيد الراكب
|
||||
|
||||
// التفاصيل المالية والرحلة
|
||||
'totalCost': rideInfo['price'].toString(), // السعر الكلي
|
||||
'paymentAmount': rideInfo['price'].toString(), // المبلغ المطلوب
|
||||
'Distance': rideInfo['distance'].toString(),
|
||||
'Duration': rideInfo['duration'].toString(),
|
||||
'durationOfRideValue':
|
||||
rideInfo['duration'].toString(), // تكرار للتأكد
|
||||
'carType': rideInfo['carType'].toString(),
|
||||
|
||||
// الدفع والمحفظة
|
||||
'paymentMethod': (rideInfo['payment_method'] == 'visa' ||
|
||||
rideInfo['payment_method'] == 'wallet')
|
||||
? 'visa'
|
||||
: 'cash',
|
||||
'WalletChecked':
|
||||
rideInfo['passenger_wallet'].toString() != '0' ? 'true' : 'false',
|
||||
'kazan': Get.find<HomeCaptainController>()
|
||||
.kazan
|
||||
.toString(), // نسبة الشركة (من الكنترولر)
|
||||
|
||||
// بيانات إضافية (لتجنب الـ Null Safety errors)
|
||||
'direction':
|
||||
'http://googleusercontent.com/maps.google.com/maps?saddr=${rideInfo['start_location']}&daddr=${rideInfo['end_location']}',
|
||||
'timeOfOrder': DateTime.now().toString(),
|
||||
'isHaveSteps': 'false', // لو كان عندك خطوات في الـ waitingRides ضيفها
|
||||
'step0': '', 'step1': '', 'step2': '', 'step3': '', 'step4': '',
|
||||
};
|
||||
|
||||
// حفظ البيانات في الصندوق احتياطياً (Crash Recovery)
|
||||
box.write(BoxName.rideArguments, fullRideArgs);
|
||||
|
||||
// الانتقال لصفحة الخريطة ومسح الصفحات السابقة لضمان عدم الرجوع للسوق
|
||||
Get.offAll(() => PassengerLocationMapPage(), arguments: fullRideArgs);
|
||||
} else {
|
||||
// ❌ فشل: الرحلة أخذها سائق آخر
|
||||
// نقوم بتحديث القائمة فوراً
|
||||
Get.find<RideAvailableController>()
|
||||
.getRideAvailable(forceRefresh: true);
|
||||
|
||||
MyDialog().getDialog(
|
||||
"Trip taken".tr,
|
||||
"This ride was just accepted by another driver.".tr,
|
||||
() => Get.back(), // زر الموافقة
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
Get.back(); // إخفاء اللودينج في حال الخطأ
|
||||
print("Accept Ride Error: $e");
|
||||
MyDialog().getDialog(
|
||||
"Error".tr,
|
||||
"An unexpected error occurred. Please try again.".tr,
|
||||
() => Get.back(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user