25-10-11/1

This commit is contained in:
Hamza-Ayed
2025-11-06 12:29:17 +03:00
parent 14484fcd8f
commit a69e4c6912
46 changed files with 14145 additions and 13529 deletions

View File

@@ -45,6 +45,7 @@ class HomeCaptain extends StatelessWidget {
checkForUpdate(context);
getPermissionOverlay();
showDriverGiftClaim(context);
checkForAppliedRide(context);
});
// The stack is now even simpler.
@@ -187,11 +188,38 @@ class _MapView extends StatelessWidget {
@override
Widget build(BuildContext context) {
final locationController = Get.find<LocationController>();
return GetBuilder<HomeCaptainController>(builder: (controller) {
return controller.isLoading
? const MyCircularProgressIndicator()
: GoogleMap(
// جلب الكونترولر الرئيسي
final homeController = Get.find<HomeCaptainController>();
return GetBuilder<HomeCaptainController>(
builder: (controller) {
if (controller.isLoading) {
return const MyCircularProgressIndicator();
}
// --- هذا هو التعديل ---
// هذا الـ Builder يستمع إلى تحديثات الموقع
return GetBuilder<LocationController>(
builder: (locationController) {
// --- هذا هو الكود الجديد ---
// نقوم بتحريك الكاميرا يدوياً عند كل تحديث للموقع
if (homeController.mapHomeCaptainController != null &&
homeController.isActive) {
homeController.mapHomeCaptainController!.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: locationController.myLocation, // الموقع الجديد
zoom: 17.5, // تقريب لمتابعة السائق
tilt: 50.0, // زاوية رؤية 3D
bearing: locationController.heading, // اتجاه السيارة
),
),
);
}
// --- نهاية الكود الجديد ---
// إرجاع الخريطة
return GoogleMap(
padding: const EdgeInsets.only(bottom: 110, top: 300),
fortyFiveDegreeImageryEnabled: true,
onMapCreated: controller.onMapCreated,
@@ -200,19 +228,12 @@ class _MapView extends StatelessWidget {
target: locationController.myLocation,
zoom: 15,
),
onCameraMove: (position) {
CameraPosition(
target: locationController.myLocation,
zoom: 17.5,
tilt: 50.0,
bearing: locationController.heading,
);
},
// --- تم حذف onCameraMove الخاطئ ---
markers: {
Marker(
markerId: MarkerId('MyLocation'.tr),
position: locationController.myLocation,
rotation: locationController.heading,
position: locationController.myLocation, // يتم تحديثه من هنا
rotation: locationController.heading, // يتم تحديثه من هنا
flat: true,
anchor: const Offset(0.5, 0.5),
icon: controller.carIcon,
@@ -222,12 +243,15 @@ class _MapView extends StatelessWidget {
myLocationButtonEnabled: false,
myLocationEnabled: false,
trafficEnabled: controller.mapTrafficON,
buildingsEnabled: true,
buildingsEnabled: false,
mapToolbarEnabled: false,
compassEnabled: true,
compassEnabled: false,
zoomControlsEnabled: false,
);
});
},
);
},
);
}
}
@@ -581,3 +605,7 @@ class FloatingActionButtons extends StatelessWidget {
);
}
}
Future<void> checkForAppliedRide(BuildContext context) async {
checkForPendingOrderFromServer();
}

View File

@@ -0,0 +1,83 @@
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:get/get.dart';
import 'package:latlong2/latlong.dart';
import '../../../../controller/functions/location_controller.dart';
import '../../../../controller/home/captin/home_captain_controller.dart';
// هذه ويدجت بديلة للـ _MapView في الكود الخاص بك
// V3 - MapView Replacement using flutter_map
class OsmMapView extends StatelessWidget {
const OsmMapView({super.key});
@override
Widget build(BuildContext context) {
// افترض أنك تحصل على الموقع والاتجاه بنفس الطريقة من الكونترولر
final LocationController locationController =
Get.find<LocationController>();
final HomeCaptainController homeCaptainController =
Get.find<HomeCaptainController>();
// يمكنك استخدام GetBuilder لمراقبة التغييرات في الموقع
return Obx(() {
final LatLng currentLocation = LatLng(
locationController.myLocation.latitude,
locationController.myLocation.longitude);
final double currentHeading = locationController.heading;
return FlutterMap(
// يمكنك ربط هذا بـ MapController الخاص بـ flutter_map
// mapController: homeCaptainController.flutterMapController,
options: MapOptions(
initialCenter: currentLocation,
initialZoom: 15,
maxZoom: 18,
minZoom: 6,
// تدوير الخريطة (اختياري)
initialRotation: currentHeading,
),
children: [
// 1. طبقة الخريطة الأساسية (Tiles)
// هذا هو الرابط لخرائط OSM الأساسية
TileLayer(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
userAgentPackageName:
'com.example.app', // استبدل باسم الباكج الخاص بك
// لاستخدام الخرائط الأوفلاين (بعد إعداد flutter_map_tile_caching)
// tileProvider: CachedTileProvider(),
),
// 2. طبقة العلامات (Markers)
MarkerLayer(
markers: [
Marker(
width: 80.0,
height: 80.0,
point: currentLocation,
child: Transform.rotate(
angle: currentHeading *
(3.1415926535 / 180), // تحويل من درجات إلى راديان
child: Image.asset(
'assets/images/car_icon.png', // تأكد أن لديك أيقونة السيارة
// يمكنك استخدام نفس الـ carIcon من الكونترولر
// icon: homeCaptainController.carIcon, (ملاحظة: flutter_map تستخدم ويدجت)
),
),
),
],
),
// يمكنك إضافة طبقات أخرى هنا (مثل الخطوط Polylines أو المضلعات Polygons)
],
);
});
}
}
// ملاحظة: ستحتاج إلى تعديل بسيط في HomeCaptainController
// لإنشاء MapController الخاص بـ flutter_map بدلاً من GoogleMapController
// import 'package:flutter_map/flutter_map.dart';
// MapController flutterMapController = MapController();

View File

@@ -237,8 +237,10 @@ Future<void> checkForPendingOrderFromServer() async {
// MyDialog().getDialog(orderId.toString(), customerToken, () {});
// Now proceed with the UI flow
_sendAcceptanceNotification(customerToken, orderId.toString());
// _sendAcceptanceNotification(customerToken, orderId.toString());
// await _bringAppToForegroundAndNavigate(orderId);
Get.to(() => PassengerLocationMapPage(),
arguments: box.read(BoxName.rideArgumentsFromBackground));
} else {
box.write(BoxName.rideArgumentsFromBackground, 'failure');
}
@@ -307,8 +309,7 @@ Map<String, dynamic> _transformServerDataToAppArguments(
void _sendAcceptanceNotification(String? customerToken, rideId) {
try {
if (customerToken == null) return;
final FirebaseMessagesController _firebaseMessagesController =
Get.put(FirebaseMessagesController());
List<String> bodyToPassenger = [
box.read(BoxName.driverID).toString(),
box.read(BoxName.nameDriver).toString(),
@@ -319,15 +320,13 @@ void _sendAcceptanceNotification(String? customerToken, rideId) {
// Safely check for customer token
final String? token = customerToken;
if (token != null && token.isNotEmpty) {
// _firebaseMessagesController.sendNotificationToDriverMAP('Accepted Ride',
// 'your ride is applied'.tr, token, bodyToPassenger, 'start.wav');
NotificationService.sendNotification(
target: token.toString(),
title: 'Accepted Ride',
title: 'Accepted Ride'.tr,
body: 'your ride is Accepted'.tr,
isTopic: false, // Important: this is a token
tone: 'start',
driverList: [],
driverList: bodyToPassenger, category: 'Accepted Ride',
);
} else {}
} catch (e) {}

View File

@@ -172,7 +172,7 @@ class PassengerInfoWindow extends StatelessWidget {
body: 'I Arrive at your site'.tr,
isTopic: false, // Important: this is a token
tone: 'ding',
driverList: [],
driverList: [], category: 'Hi ,I Arrive your site',
);
controller.startTimerToShowDriverWaitPassengerDuration();
controller.isArrivedSend = false;
@@ -261,12 +261,12 @@ class PassengerInfoWindow extends StatelessWidget {
// 'cancel.wav');
NotificationService.sendNotification(
target: controller.tokenPassenger.toString(),
title: 'Driver Cancelled Your Trip',
title: 'Driver Cancelled Your Trip'.tr,
body:
'You will need to pay the cost to the driver, or it will be deducted from your next trip',
isTopic: false, // Important: this is a token
tone: 'cancel',
driverList: [],
driverList: [], category: 'Driver Cancelled Your Trip',
);
box.write(BoxName.rideStatus, 'Cancel');
await controller.addWaitingTimeCostFromPassengerToDriverWallet();

View File

@@ -352,7 +352,7 @@ class SosConnect extends StatelessWidget {
body: "Where are you, sir?".tr,
isTopic: false, // Important: this is a token
tone: 'ding',
driverList: [],
driverList: [], category: 'message From Driver',
);
Get.back();
}),
@@ -371,7 +371,7 @@ class SosConnect extends StatelessWidget {
body: "I've been trying to reach you but your phone is off.".tr,
isTopic: false, // Important: this is a token
tone: 'ding',
driverList: [],
driverList: [], category: 'message From Driver',
);
Get.back();
}),
@@ -403,7 +403,7 @@ class SosConnect extends StatelessWidget {
body: 'change device'.tr,
isTopic: false, // Important: this is a token
tone: 'cancel',
driverList: [],
driverList: [], category: 'message From Driver',
);
controller.messageToPassenger.clear();
Get.back();

View File

@@ -225,24 +225,15 @@ class _OrderOverlayState extends State<OrderOverlay>
_getData(8).toString(),
_getData(9).toString(),
];
final fmc = Get.isRegistered<FirebaseMessagesController>()
? Get.find<FirebaseMessagesController>()
: Get.put(FirebaseMessagesController());
// fmc.sendNotificationToDriverMAP(
// "Accepted Ride",
// 'your ride is Accepted'.tr,
// _getData(9).toString(),
// bodyToPassenger,
// 'start.wav',
// );
NotificationService.sendNotification(
target: _getData(9).toString(),
title: "Accepted Ride",
title: "Accepted Ride".tr,
body: 'your ride is Accepted'.tr,
isTopic: false, // Important: this is a token
tone: 'start',
driverList: [],
driverList: bodyToPassenger,
category: 'Accepted Ride',
);
final payload = {
// بيانات أساسية
@@ -294,15 +285,6 @@ class _OrderOverlayState extends State<OrderOverlay>
'status': 'Apply'
});
if (AppLink.endPoint != AppLink.seferCairoServer) {
CRUD().post(
link: "${AppLink.endPoint}/ride/driver_order/add.php",
payload: {
'driver_id': driverId,
'order_id': orderData!.orderId,
'status': 'Apply'
});
}
_log("Server update successful. Writing to storage.");
notificationController.showNotification(
"Order Accepted".tr,

View File

@@ -184,6 +184,32 @@ class _OrderRequestPageState extends State<OrderRequestPage> {
),
),
const SizedBox(height: 10),
// Card(
// elevation: 4,
// child: Padding(
// padding: const EdgeInsets.all(16.0),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceAround,
// children: [
// _InfoTile(
// icon: Icons.timer,
// label:
// '${(double.parse(controller.myList[12]) / 60).toStringAsFixed(0)} ${'min'.tr}',
// ),
// _InfoTile(
// icon: Icons.directions_car,
// label:
// '${(double.parse(controller.myList[11]) / 1000).toStringAsFixed(1)} ${'km'.tr}',
// ),
// _InfoTile(
// icon: Icons.monetization_on,
// label: '${controller.myList[2]}',
// ),
// ],
// ),
// ),
// ),
// استبدل هذا الكود
Card(
elevation: 4,
child: Padding(
@@ -194,16 +220,21 @@ class _OrderRequestPageState extends State<OrderRequestPage> {
_InfoTile(
icon: Icons.timer,
label:
'${(double.parse(controller.myList[12]) / 60).toStringAsFixed(0)} ${'min'.tr}',
// استخدم الفهرس 13 للوقت (Duration)
'${((double.tryParse(controller.myList[13].toString()) ?? 0.0) / 60).toStringAsFixed(0)} ${'min'.tr}',
),
_InfoTile(
icon: Icons.directions_car,
label:
'${(double.parse(controller.myList[11]) / 1000).toStringAsFixed(1)} ${'km'.tr}',
// استخدم الفهرس 14 للمسافة (Distance)
// استخدم tryParse للأمان لأن القيمة "" (نص فارغ)
'${((double.tryParse(controller.myList[14].toString()) ?? 0.0) / 1000).toStringAsFixed(1)} ${'km'.tr}',
),
_InfoTile(
icon: Icons.monetization_on,
label: '${controller.myList[2]}',
label:
// السعر أصبح في الفهرس 4
'${controller.myList[4]}',
),
],
),
@@ -230,17 +261,15 @@ class _OrderRequestPageState extends State<OrderRequestPage> {
'status': 'Apply',
'driver_id': box.read(BoxName.driverID),
});
if (AppLink.endPoint != AppLink.seferCairoServer) {
CRUD().post(
link:
"${AppLink.endPoint}/ride/rides/updateStausFromSpeed.php",
payload: {
'id': (controller.myList[16]),
'rideTimeStart': DateTime.now().toString(),
'status': 'Apply',
'driver_id': box.read(BoxName.driverID),
});
}
CRUD().post(
link:
"${AppLink.endPoint}/ride/rides/updateStausFromSpeed.php",
payload: {
'id': (controller.myList[16]),
'rideTimeStart': DateTime.now().toString(),
'status': 'Apply',
'driver_id': box.read(BoxName.driverID),
});
if (res == 'failure') {
MyDialog().getDialog(
"This ride is already applied by another driver."
@@ -258,43 +287,21 @@ class _OrderRequestPageState extends State<OrderRequestPage> {
(controller.myList[16].toString()),
'status': 'Apply'
});
if (AppLink.endPoint !=
AppLink.seferCairoServer) {
CRUD().postFromDialogue(
link:
'${AppLink.endPoint}/rides/driver_order/add.php',
payload: {
'driver_id':
(controller.myList[6].toString()),
'order_id':
(controller.myList[16].toString()),
'status': 'Apply'
});
}
List<String> bodyToPassenger = [
controller.myList[6].toString(),
controller.myList[8].toString(),
controller.myList[9].toString(),
];
final fmc =
Get.isRegistered<FirebaseMessagesController>()
? Get.find<FirebaseMessagesController>()
: Get.put(FirebaseMessagesController());
// fmc.sendNotificationToDriverMAP(
// "Accepted Ride",
// 'your ride is Accepted'.tr,
// controller.myList[9].toString(),
// bodyToPassenger,
// 'start',
// );
NotificationService.sendNotification(
target: controller.myList[9].toString(),
title: "Accepted Ride",
title: "Accepted Ride".tr,
body: 'your ride is Accepted'.tr,
isTopic: false, // Important: this is a token
tone: 'start',
driverList: [],
driverList: bodyToPassenger,
category: 'Accepted Ride',
);
Get.back();
box.write(BoxName.rideArguments, {
@@ -398,7 +405,7 @@ class _OrderRequestPageState extends State<OrderRequestPage> {
'${box.read(BoxName.nameDriver)} ${'is reviewing your order. They may need more information or a higher price.'.tr}',
isTopic: false, // Important: this is a token
tone: 'start',
driverList: [],
driverList: [], category: 'Order Under Review',
);
controller.refuseOrder(

View File

@@ -368,7 +368,7 @@ class OrderSpeedRequest extends StatelessWidget {
AppLink.seferCairoServer) {
CRUD().post(
link:
"${AppLink.endPoint}/ride/rides/updateStausFromSpeed.php",
"${AppLink.rideServer}/rides/updateStausFromSpeed.php",
payload: {
'id': rideId,
'rideTimeStart':
@@ -401,12 +401,12 @@ class OrderSpeedRequest extends StatelessWidget {
?[9]
?.toString() ??
_getData(9),
title: 'Accepted Ride',
title: 'Accepted Ride'.tr,
body: 'your ride is applied'.tr,
isTopic:
false, // Important: this is a token
tone: 'start',
driverList: [],
driverList: [], category: 'Accepted Ride',
);
// Using rideId (_getData(16)) for order_id consistently
@@ -423,7 +423,7 @@ class OrderSpeedRequest extends StatelessWidget {
AppLink.seferCairoServer) {
CRUD().post(
link:
"${AppLink.endPoint}/ride/driver_order/add.php",
"${AppLink.rideServer}/driver_order/add.php",
payload: {
'driver_id': _getData(6),
'order_id': rideId,

View File

@@ -139,16 +139,16 @@ class ActionsGrid extends StatelessWidget {
mainAxisSpacing: 16,
childAspectRatio: 2.5, // للتحكم في ارتفاع الأزرار
children: [
_ActionTile(
title: 'My Cars'.tr,
icon: Icons.directions_car_filled,
onTap: () => Get.to(() => CaptainsCars()),
),
_ActionTile(
title: 'Criminal Record'.tr,
icon: Icons.description,
onTap: () => Get.to(() => CriminalDocumemtPage()),
),
// _ActionTile(
// title: 'My Cars'.tr,
// icon: Icons.directions_car_filled,
// onTap: () => Get.to(() => CaptainsCars()),
// ),
// _ActionTile(
// title: 'Criminal Record'.tr,
// icon: Icons.description,
// onTap: () => Get.to(() => CriminalDocumemtPage()),
// ),
_ActionTile(
title: 'Bank Account'.tr,
icon: Icons.account_balance,