11/10/1
This commit is contained in:
@@ -48,7 +48,8 @@ class AppLink {
|
||||
|
||||
static String getWalletByDriver = "$walletDriver/getWalletByDriver.php";
|
||||
static String driverStatistic = "$walletDriver/driverStatistic.php";
|
||||
static String getDriverDetails = "$walletDriver/getDriverDetails.php";
|
||||
static String getDriverDetails =
|
||||
"$seferCairoServer/ride/driverWallet/getDriverDetails.php";
|
||||
static String getDriverWeekPaymentMove =
|
||||
"$walletDriver/getDriverWeekPaymentMove.php";
|
||||
static String getDriversWallet = "$walletDriver/get.php";
|
||||
@@ -73,6 +74,7 @@ class AppLink {
|
||||
//-----------------ridessss------------------
|
||||
static String addRides = "$ride/rides/add.php";
|
||||
static String getRides = "$ride/rides/get.php";
|
||||
static String getMishwari = "$ride/ride/mishwari/get.php";
|
||||
static String getTripCountByCaptain = "$ride/rides/getTripCountByCaptain.php";
|
||||
static String getRideOrderID = "$ride/rides/getRideOrderID.php";
|
||||
static String getRideStatus = "$ride/rides/getRideStatus.php";
|
||||
@@ -235,6 +237,10 @@ class AppLink {
|
||||
static String getTotalDriverDurationToday =
|
||||
"$location/getTotalDriverDurationToday.php";
|
||||
|
||||
//==================cars new drivers=============
|
||||
static String addNewCarsDrivers = '$server/ride/carDrivers/add.php';
|
||||
static String getNewCarsDrivers = '$server/ride/carDrivers/get.php';
|
||||
|
||||
//==================Blog=============
|
||||
static String profile = '$server/ride/profile';
|
||||
static String getprofile = "$profile/get.php";
|
||||
|
||||
22
lib/constant/notification.dart
Normal file
22
lib/constant/notification.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
List<String> driverMessages = [
|
||||
"💸 فرص الربح: افتح تطبيق سفر الآن وزد دخلك اليوم! المزيد من الطلبات بانتظارك! 🚗",
|
||||
"🚀 طلبات جديدة: لا تضيع الفرصة! المزيد من الركاب ينتظرونك الآن على تطبيق سفر. 🏃♂️",
|
||||
"📈 زيادة الدخل: حقق أعلى أرباح اليوم مع سفر! افتح التطبيق وابدأ عملك الآن. 💵",
|
||||
"🕒 أوقات الذروة: استعد لكسب المزيد خلال فترات الطلب المرتفعة. افتح التطبيق الآن! 📲",
|
||||
"🚗 طلبات جديدة: كن مستعداً، افتح تطبيق سفر الآن واستقبل المزيد من الطلبات. 🔔",
|
||||
"🎉 فرص النجاح: ابدأ رحلتك إلى النجاح! افتح تطبيق سفر لزيادة دخلك اليوم. 💼",
|
||||
"🌍 طلبات مرتفعة: المزيد من الركاب بانتظارك، لا تفوّت الفرص، افتح التطبيق الآن! 🚖",
|
||||
"💪 زيادة الدخل: انطلق نحو تحقيق أهدافك المالية، افتح تطبيق سفر واكسب المزيد. 🏆",
|
||||
"💰 أرباح إضافية: افتح التطبيق واستعد لتحقيق أرباح إضافية مع سفر! المزيد من الطلبات في انتظارك. 🛣️",
|
||||
"🔥 فرص جديدة: تطبيق سفر مزدحم الآن! افتح التطبيق وزد أرباحك بفرص جديدة. 🚗",
|
||||
"🚨 طلبات متزايدة: افتح تطبيق سفر الآن! الطلب مرتفع وفرص الربح كبيرة! 💸",
|
||||
"💼 زيادة الدخل: هل أنت جاهز لتحقيق المزيد من الدخل؟ افتح التطبيق وانطلق الآن! 🚖",
|
||||
"🚗 أوقات الذروة: احجز مقعدك في فترات الطلب العالي، افتح تطبيق سفر الآن واكسب المزيد. 📈",
|
||||
"📲 بدء اليوم: ابدأ يومك مع سفر، وافتح التطبيق الآن لتزيد من فرص الربح. 💵",
|
||||
"💸 فرص مستمرة: لا تفوت فرص الربح، افتح تطبيق سفر الآن وكن على استعداد للمزيد! 🔔",
|
||||
"📆 زيادة الطلب: انطلق اليوم واستفد من الطلبات المتزايدة على تطبيق سفر! افتح التطبيق الآن. 🚗",
|
||||
"💥 دخل إضافي: افتح تطبيق سفر الآن واستقبل طلبات جديدة تحقق لك المزيد من الدخل. 💰",
|
||||
"🏆 فرص مرتفعة: استفد من طلبات اليوم المرتفعة، افتح التطبيق الآن مع سفر. 📲",
|
||||
"🚗 تفضيل العملاء: كن السائق الذي يختاره الجميع! افتح تطبيق سفر اليوم واربح المزيد. 🔥",
|
||||
"💸 دخل إضافي: فرص الدخل الإضافي في انتظارك! افتح تطبيق سفر واستمتع بالطلبات المتزايدة. 💼",
|
||||
];
|
||||
@@ -187,12 +187,12 @@ class LoginDriverController extends GetxController {
|
||||
if (token != 'failure') {
|
||||
if (jsonDecode(token)['data'][0]['token'] !=
|
||||
box.read(BoxName.tokenDriver)) {
|
||||
Get.put(FirebaseMessagesController())
|
||||
.sendNotificationToAnyWithoutData(
|
||||
'token change'.tr,
|
||||
'change device'.tr,
|
||||
jsonDecode(token)['data'][0]['token'].toString(),
|
||||
'promo.wav');
|
||||
Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
|
||||
'token change'.tr,
|
||||
'change device'.tr,
|
||||
jsonDecode(token)['data'][0]['token'].toString(),
|
||||
[],
|
||||
'promo.wav');
|
||||
Get.defaultDialog(
|
||||
title: 'you will use this device?'.tr,
|
||||
middleText: '',
|
||||
@@ -316,12 +316,12 @@ class LoginDriverController extends GetxController {
|
||||
if (token != 'failure') {
|
||||
if (jsonDecode(token)['data'][0]['token'] !=
|
||||
box.read(BoxName.tokenDriver)) {
|
||||
Get.put(FirebaseMessagesController())
|
||||
.sendNotificationToAnyWithoutData(
|
||||
'token change'.tr,
|
||||
'change device'.tr,
|
||||
jsonDecode(token)['data'][0]['token'].toString(),
|
||||
'promo.wav');
|
||||
Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
|
||||
'token change'.tr,
|
||||
'change device'.tr,
|
||||
jsonDecode(token)['data'][0]['token'].toString(),
|
||||
[],
|
||||
'promo.wav');
|
||||
Get.defaultDialog(
|
||||
title: 'you will use this device?'.tr,
|
||||
middleText: '',
|
||||
|
||||
@@ -90,15 +90,28 @@ class GoogleSignInHelper {
|
||||
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
|
||||
|
||||
if (googleUser != null) {
|
||||
// Handle sign-up and store user information
|
||||
await _handleSignUp(googleUser);
|
||||
|
||||
// Add detailed debug print statements
|
||||
// Retrieve driverID and emailDriver with added validation
|
||||
final driverID = box.read(BoxName.driverID)?.toString() ?? 'Unknown ID';
|
||||
final emailDriver =
|
||||
box.read(BoxName.emailDriver)?.toString() ?? 'Unknown Email';
|
||||
|
||||
// Debug print statements
|
||||
print('Driver ID: $driverID');
|
||||
print('Driver Email: $emailDriver');
|
||||
|
||||
// Check if driverID is a valid numeric string
|
||||
// if (driverID != 'Unknown ID' && int.tryParse(driverID) != null) {
|
||||
await Get.find<LoginDriverController>()
|
||||
.loginUsingCredentials(driverID, emailDriver);
|
||||
// }
|
||||
// else {
|
||||
// print('Invalid driverID format: $driverID');
|
||||
// Get.snackbar('Login Error', 'Invalid driver ID format.',
|
||||
// backgroundColor: AppColor.redColor);
|
||||
// }
|
||||
}
|
||||
|
||||
return googleUser;
|
||||
@@ -110,6 +123,13 @@ class GoogleSignInHelper {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> _handleSignUp(GoogleSignInAccount user) async {
|
||||
// Store driver information
|
||||
box.write(BoxName.driverID,
|
||||
user.id ?? 'Unknown ID'); // Ensure there's a fallback value
|
||||
box.write(BoxName.emailDriver, user.email ?? 'Unknown Email');
|
||||
}
|
||||
|
||||
// Method to handle Google Sign-Out
|
||||
static Future<void> signOut() async {
|
||||
try {
|
||||
@@ -145,16 +165,4 @@ class GoogleSignInHelper {
|
||||
static GoogleSignInAccount? getCurrentUser() {
|
||||
return _googleSignIn.currentUser;
|
||||
}
|
||||
|
||||
// Method to handle sign-up process
|
||||
static Future<void> _handleSignUp(GoogleSignInAccount user) async {
|
||||
// Store driver information
|
||||
box.write(BoxName.driverID, user.id);
|
||||
box.write(BoxName.emailDriver, user.email);
|
||||
// box.write(BoxName.nameDriver, user.displayName);
|
||||
// box.write(BoxName.driverPhotoUrl, user.photoUrl);
|
||||
|
||||
// Perform any additional sign-up tasks or API calls here
|
||||
// For example, you can send the user data to your server for registration
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ class FirebaseMessagesController extends GetxController {
|
||||
late String driverID;
|
||||
late String driverToken;
|
||||
NotificationSettings? notificationSettings;
|
||||
|
||||
NotificationController notificationController =
|
||||
Get.put(NotificationController());
|
||||
Future<void> getNotificationSettings() async {
|
||||
// Get the current notification settings
|
||||
NotificationSettings? notificationSettings =
|
||||
@@ -78,34 +79,15 @@ class FirebaseMessagesController extends GetxController {
|
||||
RemoteNotification? notification = message.notification;
|
||||
AndroidNotification? android = notification?.android;
|
||||
// if (notification != null && android != null) {
|
||||
|
||||
if (message.data.isNotEmpty && message.notification != null) {
|
||||
fireBaseTitles(message);
|
||||
}
|
||||
if (message.data.isNotEmpty && message.notification != null) {
|
||||
fireBaseTitles(message);
|
||||
}
|
||||
});
|
||||
FirebaseMessaging.onBackgroundMessage((RemoteMessage message) async {
|
||||
// if (message.notification!.title! == 'Order'.tr) {
|
||||
// if (Platform.isAndroid) {
|
||||
// NotificationController1()
|
||||
// .showNotification('Order'.tr, '', 'order', 'order_page_payload');
|
||||
// }
|
||||
// // await FirebaseMessagesController().showOverlayNotification(message);
|
||||
// var myListString = message.data['DriverList'];
|
||||
// // var points = message.data['PolylineJson'];
|
||||
|
||||
// var myList = jsonDecode(myListString) as List<dynamic>;
|
||||
// // var myPoints = jsonDecode(points) as List<dynamic>;
|
||||
// driverToken = myList[14].toString();
|
||||
// // This is for location using and uploading status
|
||||
// Get.put(HomeCaptainController()).changeRideId();
|
||||
// update();
|
||||
// Get.to(() => OrderRequestPage(), arguments: {
|
||||
// 'myListString': myListString,
|
||||
// 'DriverList': myList,
|
||||
// // 'PolylineJson': myPoints,
|
||||
// 'body': message.notification!.body
|
||||
// });
|
||||
// }
|
||||
});
|
||||
FirebaseMessaging.onBackgroundMessage((RemoteMessage message) async {});
|
||||
|
||||
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
|
||||
if (message.data.isNotEmpty && message.notification != null) {
|
||||
@@ -117,7 +99,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
Future<void> fireBaseTitles(RemoteMessage message) async {
|
||||
if (message.notification!.title! == 'OrderSpeed'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
message.notification!.title.toString(),
|
||||
message.notification!.body.toString(),
|
||||
'order',
|
||||
@@ -139,9 +121,25 @@ class FirebaseMessagesController extends GetxController {
|
||||
// 'PolylineJson': myPoints,
|
||||
'body': message.notification!.body
|
||||
});
|
||||
} else if (message.notification!.title == 'Cancel Trip') {
|
||||
} else if (message.notification!.title == 'OrderVIP') {
|
||||
var myListString = message.data['DriverList'];
|
||||
|
||||
var myList = jsonDecode(myListString) as List<dynamic>;
|
||||
|
||||
// driverToken = myList[10].toString();
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController1().showNotification(
|
||||
notificationController.showNotification(
|
||||
'OrderVIP'.tr, 'OrderVIP'.tr, 'order', '');
|
||||
}
|
||||
Get.to(VipOrderPage(), arguments: {
|
||||
'myListString': myListString,
|
||||
'DriverList': myList,
|
||||
// 'PolylineJson': myPoints,
|
||||
'body': message.notification!.body
|
||||
});
|
||||
} else if (message.notification!.title == 'Cancel Trip'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
notificationController.showNotification(
|
||||
'Cancel Trip'.tr, 'Passenger Cancel Trip'.tr, 'cancel', '');
|
||||
}
|
||||
cancelTripDialog();
|
||||
@@ -149,8 +147,8 @@ class FirebaseMessagesController extends GetxController {
|
||||
var myListString = message.data['DriverList'];
|
||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController1()
|
||||
.showNotification('VIP Order'.tr, '', 'order', '');
|
||||
notificationController.showNotification(
|
||||
'VIP Order'.tr, '', 'order', '');
|
||||
}
|
||||
MyDialog().getDialog('VIP Order'.tr, 'midTitle', () {
|
||||
sendNotificationToPassengerToken(
|
||||
@@ -162,26 +160,19 @@ class FirebaseMessagesController extends GetxController {
|
||||
});
|
||||
|
||||
// Get.to(const VipOrderPage());
|
||||
} else if (message.notification!.title! == 'message From passenger'.tr) {
|
||||
// passengerDialog(message.notification!.body!);
|
||||
} else if (message.notification!.title == 'message From passenger') {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('message From passenger'.tr, ''.tr, 'ding', '');
|
||||
notificationController.showNotification(
|
||||
'message From passenger'.tr, ''.tr, 'ding', '');
|
||||
}
|
||||
MyDialog().getDialog(
|
||||
'message From passenger'.tr, message.notification!.body!, () {
|
||||
// FirebaseMessagesController().sendNotificationToPassengerToken(
|
||||
// 'Hi ,I will go now'.tr,
|
||||
// 'I will go now'.tr,
|
||||
// Get.find<MapPassengerController>().driverToken, []);
|
||||
// Get.find<MapPassengerController>()
|
||||
// .startTimerDriverWaitPassenger5Minute();
|
||||
Get.back();
|
||||
});
|
||||
} else if (message.notification!.title == 'Cancel') {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('Cancel'.tr, ''.tr, 'cancel', '');
|
||||
notificationController.showNotification(
|
||||
'Cancel'.tr, ''.tr, 'cancel', '');
|
||||
}
|
||||
MyDialog().getDialog(
|
||||
'Passenger Cancel Trip'.tr,
|
||||
@@ -192,14 +183,14 @@ class FirebaseMessagesController extends GetxController {
|
||||
});
|
||||
// cancelTripDialog1();
|
||||
} else if (message.notification!.title! == 'token change') {
|
||||
// NotificationController1()
|
||||
// notificationController
|
||||
// .showNotification('token change'.tr, 'token change', 'cancel');
|
||||
// GoogleSignInHelper.signOut();
|
||||
GoogleSignInHelper.signOut();
|
||||
} else if (message.notification!.title! == 'face detect') {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('face detect'.tr, ''.tr, 'tone2', '');
|
||||
notificationController.showNotification(
|
||||
'face detect'.tr, ''.tr, 'tone2', '');
|
||||
}
|
||||
String result0 = await faceDetector();
|
||||
// Handle the result here, e.g., show a dialog or update the UI
|
||||
@@ -220,7 +211,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
// Get.snackbar('Hi ,I will go now', '',
|
||||
// backgroundColor: AppColor.greenColor);
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController1().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Passenger come to you'.tr, 'Hi ,I will go now'.tr, 'tone2', '');
|
||||
}
|
||||
update();
|
||||
@@ -230,7 +221,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||
// if (Platform.isAndroid) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController1().showNotification('Call Income'.tr,
|
||||
notificationController.showNotification('Call Income'.tr,
|
||||
message.notification!.body!, 'iphone_ringtone', '');
|
||||
}
|
||||
// }
|
||||
@@ -248,7 +239,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||
// if (Platform.isAndroid) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController1().showNotification('Call Income'.tr,
|
||||
notificationController.showNotification('Call Income'.tr,
|
||||
message.notification!.body!, 'iphone_ringtone', '');
|
||||
}
|
||||
// }
|
||||
@@ -262,11 +253,8 @@ class FirebaseMessagesController extends GetxController {
|
||||
} else if (message.notification!.title! ==
|
||||
"Criminal Document Required".tr) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController1().showNotification(
|
||||
"Criminal Document Required".tr,
|
||||
message.notification!.body!,
|
||||
'tone2',
|
||||
'');
|
||||
notificationController.showNotification("Criminal Document Required".tr,
|
||||
message.notification!.body!, 'tone2', '');
|
||||
}
|
||||
MyDialog().getDialog(
|
||||
"Criminal Document Required".tr, 'You should have upload it .'.tr,
|
||||
@@ -279,7 +267,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
var myListString = message.data['passengerList'];
|
||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController1().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Call End'.tr, message.notification!.body!, 'tone2', '');
|
||||
}
|
||||
// Assuming GetMaterialApp is initialized and context is valid for navigation
|
||||
@@ -296,7 +284,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
);
|
||||
} else if (message.notification!.title! == 'Order') {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
message.notification!.title.toString(),
|
||||
message.notification!.body.toString(),
|
||||
'order',
|
||||
@@ -318,7 +306,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
});
|
||||
} else if (message.notification!.title! == 'Order Applied'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController1().showNotification(
|
||||
notificationController.showNotification(
|
||||
'The order Accepted by another Driver'.tr,
|
||||
'We regret to inform you that another driver has accepted this order.'
|
||||
.tr,
|
||||
@@ -761,98 +749,6 @@ class FirebaseMessagesController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
void sendNotificationToAnyWithoutData(
|
||||
String title, String body, String token, String tone,
|
||||
{int retryCount = 2}) async {
|
||||
try {
|
||||
String serviceAccountKeyJson = '''{
|
||||
"type": "service_account",
|
||||
"project_id": "ride-b1bd8",
|
||||
"private_key_id": "75e817c0b902db2ef35edf2c2bd159dec1f13249",
|
||||
"private_key": "-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD0zH9TQGDQHUv3\\na3/JAD1UKPwAp3wNKT0a6fxiIzjI3JxQWI30QvZCcfl6CdMhIcydX1ncSaYTcEeC\\n/AdPVCPkqyJx1YIGGg6P/mRzCWeaN8fsp6z250m5vcObDCZc3dbJEkepbep+6FPY\\n21m3KO+AHh1glgsTGZOTm5xiU8NGXpdk2QEh8wpiIIlR/HuKwVw9g8urNe3Sno+U\\nDm3z37iFqvZdmpqO8aWTJu6beb3hsREK9XK2I9JqC2JUwiGQRo3idOvPP6hkqrWx\\nKSX96vglQFYfakvJdDp2ZATOlpBYPMtS/IWhJ985u58TSS+Kl8qpnpaZBSxgJirf\\nhWzhnKLfAgMBAAECggEAJP785SePGhS7ZN6ltspm+l+hSjYFrPWFCxq+rlQ1YkHZ\\nC9l+RqKSFhOkiPmQI2s4wbXl3kFxLHHlFNoi/q2wKQBmGb8TQfnRJpjjNHGA61Ev\\n0Ue7/6qPvVb9B2MsLw/FxKiTFPuMG3bgKR9pbSFuJLYoaW7zqITOhVnYphGTqwAY\\nBVVcvISSLvELDmH9VZcv/9DVqVlqbbESHWh1Z4W6XGPoEqeDH/upNTyQQ/46Msgm\\nTGE6VqLHpWuSf6SqHp+r0Y0lI3vIPM1vz5FAJDJbOE/enHa0fSup0OHSMxl0HVMn\\nnO1yrGF3vsIPOej5HKr5d71bEIckzk73/yjNC1/mDQKBgQD7RtUvc9omsSsFMJ6e\\nBASAn6Dktx/QY/XNJjFzHQj69cywLDe5t5AL2gUi3phQ2oqB5XJdwnd5bTIEPEPZ\\nDOuOai2802p6FJk6kjmZAMVGx5JtXBH+vs6jrmQQSMiKbjwN1TT6xIWakvLOonUi\\nX6ZvjYYjU/E0YJU3jSiXWEr76wKBgQD5Zn4SouJ6BCDZMbausJVMBkk3qxsYooip\\np89WakC6e7AZinpkRcqjGGV9GOvc8crJs6fyXAA9ORepGP47Mc0ZrDssOkstznsM\\npr8R0S6MKwEZaT9ixOHdOcLZ47ps+JzA2Wr4KN2OvFHksUkB/46ATD1j9WZVgB8M\\namsYp/Y73QKBgHOo+PvsoZ9psVmkNX6abtAdqdtdB0HOoRea2uwXk0ig12TIFaZg\\nfedWpUKVnxqoXVTJHklV99RmlL0qWDiSH+LfsMnXro0e6iDxqZ1po2Se/CFmXcoa\\nXdctsFVmixhdATuExewfhTfPKABA+xWlXWC/jdy5CK+JPWXijaqMM4edAoGAE5Bj\\nsWiPpYyvWvpYX0nA3G7dzX0hqgQN/mkIjbnWDArp3IcNZNJIvBSM2Yxb7EAXbU0n\\njo6DAkp5Pa2VO+WDNlFZbvW/sf8xjeOCt44WPa6d7nVgIIpbQXRngZoopKW3/jTP\\n/FmQT8McFXmGxZ5belsAsdetSGW9icbLUerTGQ0CgYEAmf/G8Ag3XxmqTXvvHuv2\\n14OP7WnrVqkEMnydrftEwn4peXd/Lz+/GYX5Zc4ZoNgbN8IvZ5z0+OmRsallsbiW\\nBw0/tc68CjzxXOvReWxDluUopqWVGj5tlGqE5xUDku9SWJSxbkiQ3rqutzBdPXpr\\noqHwPyDrmK/Zgqn+uiIm4Ck=\\n-----END PRIVATE KEY-----\\n",
|
||||
"client_email": "firebase-adminsdk-o2wqi@ride-b1bd8.iam.gserviceaccount.com",
|
||||
"client_id": "111210077025005706623",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://oauth2.googleapis.com/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-o2wqi%40ride-b1bd8.iam.gserviceaccount.com",
|
||||
"universe_domain": "googleapis.com"
|
||||
}
|
||||
'''; // As defined above
|
||||
|
||||
// Initialize AccessTokenManager
|
||||
final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
||||
|
||||
// Obtain an OAuth 2.0 access token
|
||||
final accessToken = await accessTokenManager.getAccessToken();
|
||||
|
||||
// Send the notification
|
||||
final response = await http.post(
|
||||
Uri.parse(
|
||||
'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $accessToken',
|
||||
},
|
||||
body: jsonEncode({
|
||||
'message': {
|
||||
'token': token,
|
||||
'notification': {
|
||||
'title': title,
|
||||
'body': body,
|
||||
},
|
||||
// 'data': {
|
||||
// 'DriverList': jsonEncode([]),
|
||||
// },
|
||||
'android': {
|
||||
'priority': 'high', // Set priority to high
|
||||
'notification': {
|
||||
'sound': tone,
|
||||
},
|
||||
},
|
||||
'apns': {
|
||||
'headers': {
|
||||
'apns-priority': '10', // Set APNs priority to 10
|
||||
},
|
||||
'payload': {
|
||||
'aps': {
|
||||
'sound': tone,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
print(
|
||||
'Notification sent successfully. Status code: ${response.statusCode}');
|
||||
print('Response body: ${response.body}');
|
||||
} else {
|
||||
print(
|
||||
'Failed to send notification. Status code: ${response.statusCode}');
|
||||
|
||||
print('Response body: ${response.body}');
|
||||
if (retryCount > 0) {
|
||||
print('Retrying... Attempts remaining: $retryCount');
|
||||
await Future.delayed(
|
||||
const Duration(seconds: 2)); // Optional delay before retrying
|
||||
return sendNotificationToAnyWithoutData(title, body, token, tone,
|
||||
retryCount: retryCount - 1);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error sending notification: $e');
|
||||
if (retryCount > 0) {
|
||||
print('Retrying... Attempts remaining: $retryCount');
|
||||
await Future.delayed(
|
||||
const Duration(seconds: 2)); // Optional delay before retrying
|
||||
return sendNotificationToAnyWithoutData(title, body, token, tone,
|
||||
retryCount: retryCount - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendNotificationToDriverMAP(
|
||||
String title, String body, String token, List<String> data, String tone,
|
||||
{int retryCount = 2}) async {
|
||||
@@ -946,79 +842,6 @@ class FirebaseMessagesController extends GetxController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendNotificationToDriverMapPolyline(String title, String body,
|
||||
String token, List<String> data, String polylineJson, String tone) async {
|
||||
try {
|
||||
String serviceAccountKeyJson = '''{
|
||||
"type": "service_account",
|
||||
"project_id": "ride-b1bd8",
|
||||
"private_key_id": "75e817c0b902db2ef35edf2c2bd159dec1f13249",
|
||||
"private_key": "-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD0zH9TQGDQHUv3\\na3/JAD1UKPwAp3wNKT0a6fxiIzjI3JxQWI30QvZCcfl6CdMhIcydX1ncSaYTcEeC\\n/AdPVCPkqyJx1YIGGg6P/mRzCWeaN8fsp6z250m5vcObDCZc3dbJEkepbep+6FPY\\n21m3KO+AHh1glgsTGZOTm5xiU8NGXpdk2QEh8wpiIIlR/HuKwVw9g8urNe3Sno+U\\nDm3z37iFqvZdmpqO8aWTJu6beb3hsREK9XK2I9JqC2JUwiGQRo3idOvPP6hkqrWx\\nKSX96vglQFYfakvJdDp2ZATOlpBYPMtS/IWhJ985u58TSS+Kl8qpnpaZBSxgJirf\\nhWzhnKLfAgMBAAECggEAJP785SePGhS7ZN6ltspm+l+hSjYFrPWFCxq+rlQ1YkHZ\\nC9l+RqKSFhOkiPmQI2s4wbXl3kFxLHHlFNoi/q2wKQBmGb8TQfnRJpjjNHGA61Ev\\n0Ue7/6qPvVb9B2MsLw/FxKiTFPuMG3bgKR9pbSFuJLYoaW7zqITOhVnYphGTqwAY\\nBVVcvISSLvELDmH9VZcv/9DVqVlqbbESHWh1Z4W6XGPoEqeDH/upNTyQQ/46Msgm\\nTGE6VqLHpWuSf6SqHp+r0Y0lI3vIPM1vz5FAJDJbOE/enHa0fSup0OHSMxl0HVMn\\nnO1yrGF3vsIPOej5HKr5d71bEIckzk73/yjNC1/mDQKBgQD7RtUvc9omsSsFMJ6e\\nBASAn6Dktx/QY/XNJjFzHQj69cywLDe5t5AL2gUi3phQ2oqB5XJdwnd5bTIEPEPZ\\nDOuOai2802p6FJk6kjmZAMVGx5JtXBH+vs6jrmQQSMiKbjwN1TT6xIWakvLOonUi\\nX6ZvjYYjU/E0YJU3jSiXWEr76wKBgQD5Zn4SouJ6BCDZMbausJVMBkk3qxsYooip\\np89WakC6e7AZinpkRcqjGGV9GOvc8crJs6fyXAA9ORepGP47Mc0ZrDssOkstznsM\\npr8R0S6MKwEZaT9ixOHdOcLZ47ps+JzA2Wr4KN2OvFHksUkB/46ATD1j9WZVgB8M\\namsYp/Y73QKBgHOo+PvsoZ9psVmkNX6abtAdqdtdB0HOoRea2uwXk0ig12TIFaZg\\nfedWpUKVnxqoXVTJHklV99RmlL0qWDiSH+LfsMnXro0e6iDxqZ1po2Se/CFmXcoa\\nXdctsFVmixhdATuExewfhTfPKABA+xWlXWC/jdy5CK+JPWXijaqMM4edAoGAE5Bj\\nsWiPpYyvWvpYX0nA3G7dzX0hqgQN/mkIjbnWDArp3IcNZNJIvBSM2Yxb7EAXbU0n\\njo6DAkp5Pa2VO+WDNlFZbvW/sf8xjeOCt44WPa6d7nVgIIpbQXRngZoopKW3/jTP\\n/FmQT8McFXmGxZ5belsAsdetSGW9icbLUerTGQ0CgYEAmf/G8Ag3XxmqTXvvHuv2\\n14OP7WnrVqkEMnydrftEwn4peXd/Lz+/GYX5Zc4ZoNgbN8IvZ5z0+OmRsallsbiW\\nBw0/tc68CjzxXOvReWxDluUopqWVGj5tlGqE5xUDku9SWJSxbkiQ3rqutzBdPXpr\\noqHwPyDrmK/Zgqn+uiIm4Ck=\\n-----END PRIVATE KEY-----\\n",
|
||||
"client_email": "firebase-adminsdk-o2wqi@ride-b1bd8.iam.gserviceaccount.com",
|
||||
"client_id": "111210077025005706623",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://oauth2.googleapis.com/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-o2wqi%40ride-b1bd8.iam.gserviceaccount.com",
|
||||
"universe_domain": "googleapis.com"
|
||||
}
|
||||
'''; // As defined above
|
||||
|
||||
// Initialize AccessTokenManager
|
||||
final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
||||
|
||||
// Obtain an OAuth 2.0 access token
|
||||
final accessToken = await accessTokenManager.getAccessToken();
|
||||
|
||||
// Send the notification
|
||||
final response = await http.post(
|
||||
Uri.parse(
|
||||
'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $accessToken',
|
||||
},
|
||||
body: jsonEncode({
|
||||
'message': {
|
||||
'token': token,
|
||||
'notification': {
|
||||
'title': title,
|
||||
'body': body,
|
||||
},
|
||||
'data': {
|
||||
'DriverList': jsonEncode(data),
|
||||
},
|
||||
'android': {
|
||||
'priority': 'high', // Set priority to high
|
||||
'notification': {
|
||||
'sound': tone,
|
||||
},
|
||||
},
|
||||
'apns': {
|
||||
'headers': {
|
||||
'apns-priority': '10', // Set APNs priority to 10
|
||||
},
|
||||
'payload': {
|
||||
'aps': {
|
||||
'sound': tone,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// Notification sent successfully
|
||||
} else {
|
||||
// Handle error response
|
||||
'Failed to send notification. Status code: ${response.statusCode}';
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle other exceptions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OverlayContent extends StatelessWidget {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:SEFER/constant/colors.dart';
|
||||
@@ -6,7 +8,11 @@ import 'package:SEFER/views/home/Captin/orderCaptin/order_request_page.dart';
|
||||
import 'package:SEFER/views/home/Captin/orderCaptin/order_speed_request.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import 'package:timezone/data/latest.dart' as tz;
|
||||
import 'package:timezone/timezone.dart' as tz;
|
||||
import '../../constant/box_name.dart';
|
||||
import '../../main.dart';
|
||||
import '../../print.dart';
|
||||
import '../../views/notification/notification_captain.dart';
|
||||
@@ -19,10 +25,17 @@ class NotificationController extends GetxController {
|
||||
Future<void> initNotifications() async {
|
||||
const AndroidInitializationSettings android =
|
||||
AndroidInitializationSettings('@mipmap/launcher_icon');
|
||||
|
||||
const InitializationSettings initializationSettings =
|
||||
InitializationSettings(android: android);
|
||||
|
||||
DarwinInitializationSettings ios = DarwinInitializationSettings(
|
||||
requestAlertPermission: true,
|
||||
requestBadgePermission: true,
|
||||
requestSoundPermission: true,
|
||||
onDidReceiveLocalNotification:
|
||||
(int id, String? title, String? body, String? payload) async {},
|
||||
);
|
||||
InitializationSettings initializationSettings =
|
||||
InitializationSettings(android: android, iOS: ios);
|
||||
tz.initializeTimeZones();
|
||||
print('Notifications initialized');
|
||||
await _flutterLocalNotificationsPlugin.initialize(
|
||||
initializationSettings,
|
||||
onDidReceiveNotificationResponse: onDidReceiveNotificationResponse,
|
||||
@@ -85,13 +98,266 @@ class NotificationController extends GetxController {
|
||||
],
|
||||
category: AndroidNotificationCategory.progress,
|
||||
);
|
||||
|
||||
NotificationDetails details = NotificationDetails(android: android);
|
||||
DarwinNotificationDetails ios = const DarwinNotificationDetails(
|
||||
sound: 'default',
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
presentSound: true,
|
||||
);
|
||||
NotificationDetails details =
|
||||
NotificationDetails(android: android, iOS: ios);
|
||||
|
||||
await _flutterLocalNotificationsPlugin.show(0, title, message, details,
|
||||
payload: jsonEncode({'title': title, 'data': payLoad}));
|
||||
}
|
||||
|
||||
void scheduleNotificationAtSpecificTime(
|
||||
String title, String message, String tone, int hour, int minute) async {
|
||||
// Initialize and set Cairo time zone
|
||||
tz.initializeTimeZones();
|
||||
var cairoLocation;
|
||||
if (box.read(BoxName.countryCode).toString() == 'Egypt') {
|
||||
cairoLocation = tz.getLocation('Africa/Cairo');
|
||||
} else {} // todo get for location country
|
||||
|
||||
final AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||
'high_importance_channel',
|
||||
'High Importance Notifications',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
showWhen: false,
|
||||
sound: RawResourceAndroidNotificationSound(tone),
|
||||
);
|
||||
|
||||
const DarwinNotificationDetails ios = DarwinNotificationDetails(
|
||||
sound: 'default',
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
presentSound: true,
|
||||
);
|
||||
|
||||
final NotificationDetails details =
|
||||
NotificationDetails(android: android, iOS: ios);
|
||||
|
||||
final now =
|
||||
tz.TZDateTime.now(cairoLocation); // Use Cairo timezone for current time
|
||||
tz.TZDateTime scheduledTime = tz.TZDateTime(
|
||||
cairoLocation, now.year, now.month, now.day, hour, minute);
|
||||
|
||||
// If the scheduled time has already passed for today, schedule it for the next day
|
||||
if (scheduledTime.isBefore(now)) {
|
||||
scheduledTime = scheduledTime.add(const Duration(days: 1));
|
||||
}
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
if (await Permission.scheduleExactAlarm.isDenied) {
|
||||
if (await Permission.scheduleExactAlarm.request().isGranted) {
|
||||
print('SCHEDULE_EXACT_ALARM permission granted');
|
||||
} else {
|
||||
print('SCHEDULE_EXACT_ALARM permission denied');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print('Current time: $now');
|
||||
print('Scheduling notification for: $scheduledTime');
|
||||
await _flutterLocalNotificationsPlugin.zonedSchedule(
|
||||
0,
|
||||
title,
|
||||
message,
|
||||
scheduledTime,
|
||||
details,
|
||||
androidAllowWhileIdle: true,
|
||||
uiLocalNotificationDateInterpretation:
|
||||
UILocalNotificationDateInterpretation.absoluteTime,
|
||||
matchDateTimeComponents:
|
||||
DateTimeComponents.time, // Triggers daily at the same time
|
||||
);
|
||||
print('Notification scheduled successfully');
|
||||
}
|
||||
|
||||
void scheduleNotificationAfter1Minute(
|
||||
String title, String message, String tone) async {
|
||||
final AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||
'high_importance_channel',
|
||||
'High Importance Notifications',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
showWhen: false,
|
||||
sound: RawResourceAndroidNotificationSound(tone),
|
||||
);
|
||||
|
||||
const DarwinNotificationDetails ios = DarwinNotificationDetails(
|
||||
sound: 'default',
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
presentSound: true,
|
||||
);
|
||||
|
||||
final NotificationDetails details =
|
||||
NotificationDetails(android: android, iOS: ios);
|
||||
|
||||
// Schedule the notification to be shown after 1 minute
|
||||
Timer.periodic(const Duration(seconds: 15), (timer) async {
|
||||
final now = tz.TZDateTime.now(tz.local);
|
||||
final scheduledTime = now.add(const Duration(seconds: 10));
|
||||
Log.print('scheduledTime: ${scheduledTime}');
|
||||
if (Platform.isAndroid) {
|
||||
if (await Permission.scheduleExactAlarm.isDenied) {
|
||||
if (await Permission.scheduleExactAlarm.request().isGranted) {
|
||||
print('SCHEDULE_EXACT_ALARM permission granted');
|
||||
} else {
|
||||
print('SCHEDULE_EXACT_ALARM permission denied');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print('Scheduling notification for: $scheduledTime');
|
||||
await _flutterLocalNotificationsPlugin.zonedSchedule(
|
||||
0,
|
||||
title,
|
||||
message,
|
||||
scheduledTime,
|
||||
details,
|
||||
androidAllowWhileIdle: true,
|
||||
uiLocalNotificationDateInterpretation:
|
||||
UILocalNotificationDateInterpretation.absoluteTime,
|
||||
matchDateTimeComponents: DateTimeComponents.time,
|
||||
);
|
||||
print('Notification scheduled successfully');
|
||||
});
|
||||
}
|
||||
|
||||
void scheduleDailyNotifications(
|
||||
String title, String message, String tone) async {
|
||||
final AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||
'high_importance_channel',
|
||||
'High Importance Notifications',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
sound: RawResourceAndroidNotificationSound(tone),
|
||||
);
|
||||
|
||||
const DarwinNotificationDetails ios = DarwinNotificationDetails(
|
||||
sound: 'default',
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
presentSound: true,
|
||||
);
|
||||
|
||||
final NotificationDetails details =
|
||||
NotificationDetails(android: android, iOS: ios);
|
||||
|
||||
// Check for the exact alarm permission on Android 12 and above
|
||||
if (Platform.isAndroid) {
|
||||
if (await Permission.scheduleExactAlarm.isDenied) {
|
||||
if (await Permission.scheduleExactAlarm.request().isGranted) {
|
||||
print('SCHEDULE_EXACT_ALARM permission granted');
|
||||
} else {
|
||||
print('SCHEDULE_EXACT_ALARM permission denied');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule notifications for 10:00 AM and 3:00 PM daily
|
||||
await _scheduleNotificationForTime(7, 0, title, message, details);
|
||||
await _scheduleNotificationForTime(13, 0, title, message, details);
|
||||
await _scheduleNotificationForTime(18, 0, title, message, details);
|
||||
// await _scheduleNotificationForTime(0, 22, title, message, details);
|
||||
|
||||
print('Daily notifications scheduled successfully');
|
||||
}
|
||||
|
||||
// Helper function to get the next instance of a specific hour and minute
|
||||
Future<void> _scheduleNotificationForTime(int hour, int minute, String title,
|
||||
String message, NotificationDetails details) async {
|
||||
// Initialize and set Cairo timezone
|
||||
tz.initializeTimeZones();
|
||||
final cairoLocation = tz.getLocation('Africa/Cairo'); // Set Cairo timezone
|
||||
|
||||
final now = tz.TZDateTime.now(
|
||||
cairoLocation); // Use Cairo timezone for the current time
|
||||
tz.TZDateTime scheduledDate = tz.TZDateTime(
|
||||
cairoLocation, now.year, now.month, now.day, hour, minute);
|
||||
|
||||
// If scheduled time is already past today, schedule it for the next day
|
||||
if (scheduledDate.isBefore(now)) {
|
||||
scheduledDate = scheduledDate.add(const Duration(days: 1));
|
||||
}
|
||||
|
||||
print('Current time (Cairo): $now');
|
||||
print('Scheduling notification for: $scheduledDate');
|
||||
|
||||
await _flutterLocalNotificationsPlugin.zonedSchedule(
|
||||
0, // Use unique IDs if you want to manage each notification separately
|
||||
title,
|
||||
message,
|
||||
scheduledDate,
|
||||
details,
|
||||
androidAllowWhileIdle: true,
|
||||
uiLocalNotificationDateInterpretation:
|
||||
UILocalNotificationDateInterpretation.absoluteTime,
|
||||
matchDateTimeComponents: DateTimeComponents.time,
|
||||
);
|
||||
print('Notification scheduled successfully for Cairo timezone');
|
||||
}
|
||||
|
||||
void scheduleNotificationEvery10Hours(
|
||||
String title, String message, String tone) async {
|
||||
final AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||
'high_importance_channel',
|
||||
'High Importance Notifications',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
showWhen: false,
|
||||
sound: RawResourceAndroidNotificationSound(tone),
|
||||
);
|
||||
|
||||
const DarwinNotificationDetails ios = DarwinNotificationDetails(
|
||||
sound: 'default',
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
presentSound: true,
|
||||
);
|
||||
|
||||
final NotificationDetails details =
|
||||
NotificationDetails(android: android, iOS: ios);
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
if (await Permission.scheduleExactAlarm.isDenied) {
|
||||
if (await Permission.scheduleExactAlarm.request().isGranted) {
|
||||
print('SCHEDULE_EXACT_ALARM permission granted');
|
||||
} else {
|
||||
print('SCHEDULE_EXACT_ALARM permission denied');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer.periodic(const Duration(hours: 10), (timer) async {
|
||||
final now = tz.TZDateTime.now(tz.local);
|
||||
final scheduledTime = now.add(const Duration(minutes: 10));
|
||||
|
||||
print('Scheduling notification for: $scheduledTime');
|
||||
await _flutterLocalNotificationsPlugin.zonedSchedule(
|
||||
0,
|
||||
title.tr,
|
||||
message.tr,
|
||||
scheduledTime,
|
||||
details,
|
||||
androidAllowWhileIdle: true,
|
||||
uiLocalNotificationDateInterpretation:
|
||||
UILocalNotificationDateInterpretation.absoluteTime,
|
||||
matchDateTimeComponents: DateTimeComponents.time,
|
||||
);
|
||||
});
|
||||
|
||||
print('Notifications scheduled every 5 seconds');
|
||||
}
|
||||
|
||||
// Callback when the notification is tapped
|
||||
void onDidReceiveNotificationResponse(NotificationResponse response) {
|
||||
handleNotificationResponse(response);
|
||||
|
||||
@@ -626,6 +626,51 @@ class AI extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> allMethodForAINewCar(
|
||||
String prompt, String linkPHP, String imagePath, String carID) async {
|
||||
isLoading = true;
|
||||
update();
|
||||
|
||||
try {
|
||||
await ImageController().choosImageNewCAr(linkPHP, imagePath);
|
||||
|
||||
// if (imagePath == 'driver_license') {
|
||||
// await ImageController().choosFaceFromDriverLicense(linkPHP, 'face');
|
||||
// }
|
||||
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
|
||||
var extractedString =
|
||||
await CRUD().arabicTextExtractByVisionAndAI(imagePath: imagePath);
|
||||
var json = jsonDecode(extractedString);
|
||||
var textValues = CRUD().extractTextFromLines(json);
|
||||
|
||||
DocumentType detectedType = checkDocumentType(textValues);
|
||||
String expectedDocument = getExpectedDocument(imagePath);
|
||||
String detectedDocument = getDetectedDocument(detectedType);
|
||||
|
||||
bool isCorrectDocument = (detectedType == getExpectedType(imagePath));
|
||||
|
||||
if (!isCorrectDocument) {
|
||||
MyDialog().getDialog('incorrect_document_title'.tr,
|
||||
'${'expected'.tr}: $expectedDocument\n${'detected'.tr}: $detectedDocument',
|
||||
() {
|
||||
Get.back();
|
||||
});
|
||||
} else {
|
||||
// Process the correct document
|
||||
await Get.put(AI()).anthropicAI(textValues, prompt, imagePath);
|
||||
}
|
||||
} catch (e) {
|
||||
MyDialog().getDialog('error'.tr, 'error_processing_document'.tr, () {
|
||||
Get.back();
|
||||
});
|
||||
} finally {
|
||||
isLoading = false;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
String getExpectedDocument(String imagePath) {
|
||||
switch (imagePath) {
|
||||
case 'car_front':
|
||||
|
||||
@@ -30,8 +30,8 @@ class SmsEgyptController extends GetxController {
|
||||
Future<dynamic> sendSmsEgypt(String phone, otp) async {
|
||||
String sender = await getSender();
|
||||
var body = jsonEncode({
|
||||
"username": AppInformation.appName,
|
||||
"password": AK.smsPasswordEgypt, //'E)Pu=an/@Z',
|
||||
"username": 'Sefer',
|
||||
"password": AK.smsPasswordEgypt,
|
||||
"message": "${AppInformation.appName} app code is $otp\ncopy it to app",
|
||||
"language": box.read(BoxName.lang) == 'en' ? "e" : 'r',
|
||||
"sender": sender, //"Sefer Egy", // todo add sefer sender name
|
||||
|
||||
@@ -139,8 +139,8 @@ class ImageController extends GetxController {
|
||||
File compressedImage = await compressImage(processedImage);
|
||||
|
||||
print('link =$link');
|
||||
Log.print('link: ${link}');
|
||||
|
||||
// Log.print('link: ${link}');
|
||||
//n8u22456
|
||||
await uploadImage(
|
||||
compressedImage,
|
||||
{
|
||||
@@ -160,6 +160,65 @@ class ImageController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
choosImageNewCAr(String link, String imageType) async {
|
||||
try {
|
||||
final pickedImage = await picker.pickImage(
|
||||
source: ImageSource.camera,
|
||||
preferredCameraDevice: CameraDevice.rear,
|
||||
);
|
||||
|
||||
if (pickedImage == null) return;
|
||||
|
||||
image = File(pickedImage.path);
|
||||
|
||||
croppedFile = await ImageCropper().cropImage(
|
||||
sourcePath: image!.path,
|
||||
uiSettings: [
|
||||
AndroidUiSettings(
|
||||
toolbarTitle: 'Cropper'.tr,
|
||||
toolbarColor: AppColor.blueColor,
|
||||
toolbarWidgetColor: AppColor.yellowColor,
|
||||
initAspectRatio: CropAspectRatioPreset.original,
|
||||
lockAspectRatio: false,
|
||||
),
|
||||
IOSUiSettings(
|
||||
title: 'Cropper'.tr,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
if (croppedFile == null) return;
|
||||
|
||||
myImage = File(croppedFile!.path);
|
||||
isloading = true;
|
||||
update();
|
||||
|
||||
// Rotate the compressed image
|
||||
File processedImage = await rotateImageIfNeeded(File(croppedFile!.path));
|
||||
File compressedImage = await compressImage(processedImage);
|
||||
|
||||
print('link =$link');
|
||||
// Log.print('link: ${link}');
|
||||
//n8u22456
|
||||
await uploadNewCar(
|
||||
compressedImage,
|
||||
{
|
||||
'driverID':
|
||||
box.read(BoxName.driverID) ?? box.read(BoxName.passengerID),
|
||||
'imageType': imageType,
|
||||
},
|
||||
link,
|
||||
);
|
||||
} catch (e) {
|
||||
print('Error in choosImage: $e');
|
||||
Get.snackbar('Image Upload Failed'.tr, e.toString(),
|
||||
backgroundColor: AppColor.primaryColor);
|
||||
} finally {
|
||||
isloading = false;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
// choosFaceFromDriverLicense(String link, String imageType) async {
|
||||
// final pickedImage = await picker.pickImage(
|
||||
// source: ImageSource.camera,
|
||||
@@ -278,6 +337,47 @@ class ImageController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
uploadNewCar(File file, Map data, String link) async {
|
||||
var request = http.MultipartRequest(
|
||||
'POST',
|
||||
Uri.parse(link),
|
||||
);
|
||||
|
||||
var length = await file.length();
|
||||
var stream = http.ByteStream(file.openRead());
|
||||
var multipartFile = http.MultipartFile(
|
||||
'image',
|
||||
stream,
|
||||
length,
|
||||
filename: basename(file.path),
|
||||
);
|
||||
request.headers.addAll({
|
||||
'Authorization':
|
||||
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
|
||||
});
|
||||
// Set the file name to the driverID
|
||||
request.files.add(
|
||||
http.MultipartFile(
|
||||
'image',
|
||||
stream,
|
||||
length,
|
||||
filename: '${box.read(BoxName.driverID)}.jpg',
|
||||
),
|
||||
);
|
||||
data.forEach((key, value) {
|
||||
request.fields[key] = value;
|
||||
});
|
||||
var myrequest = await request.send();
|
||||
var res = await http.Response.fromStream(myrequest);
|
||||
if (res.statusCode == 200) {
|
||||
Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}');
|
||||
return jsonDecode(res.body);
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to upload image: ${res.statusCode} - ${res.body}');
|
||||
}
|
||||
}
|
||||
|
||||
choosImagePicture(String link, String imageType) async {
|
||||
final pickedImage = await picker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
|
||||
@@ -300,10 +300,11 @@ class MapDriverController extends GetxController {
|
||||
}
|
||||
// Get.find<HomeCaptainController>().changeToAppliedRide('Applied');
|
||||
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'DriverIsGoingToPassenger',
|
||||
box.read(BoxName.name).toString(),
|
||||
tokenPassenger,
|
||||
[],
|
||||
'start.wav');
|
||||
}
|
||||
|
||||
@@ -390,11 +391,8 @@ class MapDriverController extends GetxController {
|
||||
'status': 'Begin',
|
||||
});
|
||||
}
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
'RideIsBegin',
|
||||
box.read(BoxName.name).toString(),
|
||||
tokenPassenger,
|
||||
'start.wav');
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP('RideIsBegin',
|
||||
box.read(BoxName.name).toString(), tokenPassenger, [], 'start.wav');
|
||||
rideIsBeginPassengerTimer();
|
||||
|
||||
// var d = jsonDecode(res);
|
||||
@@ -673,7 +671,7 @@ class MapDriverController extends GetxController {
|
||||
'driverID': box.read(BoxName.driverID).toString(),
|
||||
});
|
||||
Future.delayed(const Duration(milliseconds: 300));
|
||||
FirebaseMessagesController().sendNotificationToPassengerToken(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'Driver Finish Trip',
|
||||
'${'you will pay to Driver'.tr} $paymentAmount \$',
|
||||
tokenPassenger,
|
||||
|
||||
@@ -196,14 +196,22 @@ class MyTranslation extends Translations {
|
||||
"Total Earnings": "إجمالي الأرباح",
|
||||
"Choose from contact": "اختر من جهات الاتصال",
|
||||
"Cancel": "إلغاء",
|
||||
"Open App": "افتح التطبيق",
|
||||
"Add new car": "أضف سيارة جديدة",
|
||||
"Open the app to stay updated and ready for upcoming tasks.":
|
||||
"افتح التطبيق لتبقى على اطلاع واستعداد للمهام القادمة.",
|
||||
"No invitation found": "لم يتم العثور على دعوة",
|
||||
'You are not near the passenger location':
|
||||
"أنت لست بالقرب من موقع الراكب",
|
||||
'Please upload this license.': "يرجى تحميل هذه الرخصة.",
|
||||
'If your car license has the new design, upload the front side with two images.':
|
||||
"إذا كانت رخصة سيارتك ذات التصميم الجديد، يرجى تحميل الوجه الأمامي بصورتين.",
|
||||
'If you need assistance, contact us':
|
||||
"إذا كنت بحاجة إلى المساعدة، تواصل معنا",
|
||||
'You Can Cancel the Trip and get Cost From ':
|
||||
"يمكنك إلغاء الرحلة والحصول على التكلفة من",
|
||||
|
||||
'Please make sure to read the license carefully.':
|
||||
"يرجى التأكد من قراءة الرخصة بعناية",
|
||||
'Videos Tutorials': "فيديوهات تعليمية",
|
||||
'Please go to the pickup location exactly':
|
||||
"يرجى الذهاب إلى موقع الالتقاط بالضبط",
|
||||
|
||||
@@ -87,10 +87,11 @@ class RateController extends GetxController {
|
||||
// 'token': paymentToken4,
|
||||
// 'driverID': box.read(BoxName.driverID).toString(),
|
||||
// });
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'Wallet Added'.tr,
|
||||
'Wallet Added${(remainingFee).toStringAsFixed(0)}'.tr,
|
||||
Get.find<MapDriverController>().tokenPassenger,
|
||||
[],
|
||||
'tone2.wav');
|
||||
walletChecked = 'true';
|
||||
// }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/controller/payment/paymob/paymob_response.dart';
|
||||
import 'package:SEFER/views/home/Captin/orderCaptin/order_request_page.dart';
|
||||
@@ -18,6 +19,7 @@ import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
import 'constant/api_key.dart';
|
||||
import 'constant/info.dart';
|
||||
import 'constant/notification.dart';
|
||||
import 'controller/firebase/firbase_messge.dart';
|
||||
import 'controller/firebase/local_notification.dart';
|
||||
import 'controller/functions/location_controller.dart';
|
||||
@@ -58,14 +60,13 @@ Future<void> backgroundMessageHandler(RemoteMessage message) async {
|
||||
Log.print('Error decoding JSON: $e');
|
||||
myList = [];
|
||||
}
|
||||
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
NotificationController().showNotification(
|
||||
message.notification!.title.toString(),
|
||||
message.notification!.body.toString(),
|
||||
'order',
|
||||
myListString,
|
||||
);
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
||||
bool isOverlayActive = await FlutterOverlayWindow.isActive();
|
||||
if (isOverlayActive) {
|
||||
@@ -137,9 +138,23 @@ void main() async {
|
||||
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
|
||||
// NotificationController1().initNotifications();
|
||||
// NotificationController().initNotifications();
|
||||
if (Platform.isAndroid) {
|
||||
await Get.put(NotificationController()).initNotifications();
|
||||
}
|
||||
// if (Platform.isAndroid) {
|
||||
// await Get.put(NotificationController()).initNotifications();
|
||||
// }
|
||||
NotificationController notificationController =
|
||||
Get.put(NotificationController());
|
||||
await notificationController.initNotifications();
|
||||
|
||||
// Generate a random index to pick a message
|
||||
final random = Random();
|
||||
final randomMessage = driverMessages[random.nextInt(driverMessages.length)];
|
||||
|
||||
// Schedule the notification with the random message
|
||||
notificationController.scheduleDailyNotifications(
|
||||
randomMessage.split(':')[0],
|
||||
randomMessage.split(':')[1],
|
||||
"ding",
|
||||
);
|
||||
|
||||
await Future.wait([
|
||||
FirebaseMessagesController().getNotificationSettings(),
|
||||
|
||||
76
lib/views/auth/captin/driver_car_controller.dart
Normal file
76
lib/views/auth/captin/driver_car_controller.dart
Normal file
@@ -0,0 +1,76 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/constant/colors.dart';
|
||||
import 'package:SEFER/constant/links.dart';
|
||||
import 'package:SEFER/controller/functions/crud.dart';
|
||||
import 'package:SEFER/main.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class DriverCarController extends GetxController {
|
||||
bool isLoading = false;
|
||||
List cars = [];
|
||||
int? carId;
|
||||
fetchCatrsForDrivers() async {
|
||||
isLoading = true;
|
||||
update();
|
||||
var res = await CRUD().get(link: AppLink.getNewCarsDrivers, payload: {
|
||||
"driverID": box.read(BoxName.driverID).toString(),
|
||||
});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
cars = d;
|
||||
carId = cars.isEmpty ? 1 : cars.length + 1;
|
||||
}
|
||||
isLoading = false;
|
||||
update();
|
||||
}
|
||||
|
||||
addCarsForDrivers(
|
||||
String vin,
|
||||
String car_plate,
|
||||
String make,
|
||||
String model,
|
||||
String year,
|
||||
String expiration_date,
|
||||
String color,
|
||||
String color_hex,
|
||||
String address,
|
||||
String owner,
|
||||
String registration_date,
|
||||
String displacement,
|
||||
String fuel) async {
|
||||
var res = await CRUD().post(
|
||||
link: AppLink.addNewCarsDrivers,
|
||||
payload: {
|
||||
"driverID": box.read(BoxName.driverID).toString(),
|
||||
"vin": vin,
|
||||
"car_plate": car_plate,
|
||||
"make": make,
|
||||
"model": model,
|
||||
"year": year,
|
||||
"expiration_date": expiration_date,
|
||||
"color": color,
|
||||
"owner": owner,
|
||||
"color_hex": color_hex,
|
||||
"address": address,
|
||||
"displacement": displacement,
|
||||
"fuel": fuel,
|
||||
"registration_date": registration_date,
|
||||
},
|
||||
);
|
||||
if (res != 'failure') {
|
||||
Get.snackbar('Success'.tr, '', backgroundColor: AppColor.greenColor);
|
||||
fetchCatrsForDrivers();
|
||||
} else {
|
||||
Get.snackbar('Error'.tr, '', backgroundColor: AppColor.redColor);
|
||||
}
|
||||
}
|
||||
|
||||
removeCar(String car) async {}
|
||||
@override
|
||||
void onInit() {
|
||||
fetchCatrsForDrivers();
|
||||
super.onInit();
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ class CupertinoDrawerCaptain extends StatelessWidget {
|
||||
_buildDrawerItem(
|
||||
icon: CupertinoIcons.mail,
|
||||
text: "Contact Us".tr,
|
||||
onTap: () => Get.to(() => const SettingsCaptain()),
|
||||
onTap: () => Get.to(() => ContactUsPage()),
|
||||
),
|
||||
_buildDivider(),
|
||||
_buildDrawerItem(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/controller/firebase/local_notification.dart';
|
||||
@@ -10,8 +11,12 @@ import 'package:get/get.dart';
|
||||
import 'package:SEFER/controller/home/captin/home_captain_controller.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
|
||||
import 'package:timezone/data/latest.dart' as tz;
|
||||
import 'package:timezone/timezone.dart' as tz;
|
||||
import '../../../../../constant/colors.dart';
|
||||
import '../../../../../constant/notification.dart';
|
||||
import '../../../../../controller/functions/audio_controller.dart';
|
||||
import '../../../../../print.dart';
|
||||
import '../../../../Rate/ride_calculate_driver.dart';
|
||||
import '../../../../../controller/functions/location_controller.dart';
|
||||
import '../../driver_map_page.dart';
|
||||
@@ -180,30 +185,53 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
|
||||
),
|
||||
// Platform.isAndroid
|
||||
// ?
|
||||
// AnimatedContainer(
|
||||
// duration: const Duration(microseconds: 200),
|
||||
// width: controller.widthMapTypeAndTraffic,
|
||||
// decoration: BoxDecoration(
|
||||
// color: AppColor.secondaryColor,
|
||||
// border: Border.all(color: AppColor.blueColor),
|
||||
// borderRadius: BorderRadius.circular(15)),
|
||||
// child: Builder(builder: (context) {
|
||||
// return IconButton(
|
||||
// onPressed: () async {
|
||||
// // NotificationController().showNotification(
|
||||
// // ' message.notification!.title.toString()',
|
||||
// // ' message.notification!.body.toString()',
|
||||
// // 'order',
|
||||
// // '');
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// FontAwesome5.window_close,
|
||||
// size: 29,
|
||||
// color: AppColor.blueColor,
|
||||
// ),
|
||||
// );
|
||||
// }),
|
||||
// ),
|
||||
AnimatedContainer(
|
||||
duration: const Duration(microseconds: 200),
|
||||
width: controller.widthMapTypeAndTraffic,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.secondaryColor,
|
||||
border: Border.all(color: AppColor.blueColor),
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
child: Builder(builder: (context) {
|
||||
return IconButton(
|
||||
onPressed: () async {
|
||||
// NotificationController().showNotification(
|
||||
// ' message.notification!.title.toString()',
|
||||
// ' message.notification!.body.toString()',
|
||||
// 'order',
|
||||
// '');
|
||||
|
||||
NotificationController notificationController =
|
||||
Get.put(NotificationController());
|
||||
await notificationController.initNotifications();
|
||||
final random = Random();
|
||||
final randomMessage =
|
||||
driverMessages[random.nextInt(driverMessages.length)];
|
||||
Log.print(
|
||||
' randomMessage.split[0]: ${randomMessage.split(':')[0]}');
|
||||
Log.print(
|
||||
' randomMessage.split([1]: ${randomMessage.split(':')[1]}');
|
||||
// Schedule the notification with the random message
|
||||
notificationController.showNotification(
|
||||
randomMessage.split(':')[0],
|
||||
randomMessage.split(':')[1],
|
||||
"ding",
|
||||
'');
|
||||
|
||||
// notificationController.scheduleNotificationEvery10Hours(
|
||||
// "افتح التطبيق".tr,
|
||||
// "افتح التطبيق لتبقى على اطلاع واستعداد للمهام القادمة.".tr,
|
||||
// "ding",
|
||||
// );
|
||||
},
|
||||
icon: const Icon(
|
||||
FontAwesome5.window_close,
|
||||
size: 29,
|
||||
color: AppColor.blueColor,
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
// : const SizedBox(),
|
||||
// AnimatedContainer(
|
||||
// duration: const Duration(microseconds: 200),
|
||||
|
||||
@@ -101,12 +101,13 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
"Where are you, sir?"
|
||||
.tr,
|
||||
controller
|
||||
.tokenPassenger,
|
||||
[],
|
||||
'ding.wav');
|
||||
Get.back();
|
||||
},
|
||||
@@ -132,12 +133,13 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
"I've been trying to reach you but your phone is off."
|
||||
.tr,
|
||||
controller
|
||||
.tokenPassenger,
|
||||
[],
|
||||
'ding.wav');
|
||||
Get.back();
|
||||
},
|
||||
@@ -163,12 +165,13 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
"Please don't be late, I'm waiting for you at the specified location."
|
||||
.tr,
|
||||
controller
|
||||
.tokenPassenger,
|
||||
[],
|
||||
'ding.wav');
|
||||
Get.back();
|
||||
},
|
||||
@@ -194,13 +197,14 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
"Please don't be late"
|
||||
.tr,
|
||||
controller
|
||||
.tokenPassenger,
|
||||
'ding.wav');
|
||||
[],
|
||||
'cancel.wav');
|
||||
Get.back();
|
||||
},
|
||||
child: Container(
|
||||
@@ -247,10 +251,11 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
IconButton(
|
||||
onPressed:
|
||||
() {
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
'message From Driver'.tr,
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
controller.messageToPassenger.text,
|
||||
controller.tokenPassenger,
|
||||
[],
|
||||
'ding.wav');
|
||||
controller
|
||||
.messageToPassenger
|
||||
@@ -471,13 +476,13 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
140) {
|
||||
// Notify Passenger
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToPassengerToken(
|
||||
'Hi, I Arrive at your site',
|
||||
.sendNotificationToDriverMAP(
|
||||
'Hi ,I Arrive your site',
|
||||
'I Arrive at your site'
|
||||
.tr,
|
||||
controller.tokenPassenger,
|
||||
[],
|
||||
'start.wav',
|
||||
'ding.wav',
|
||||
);
|
||||
controller
|
||||
.startTimerToShowDriverWaitPassengerDuration();
|
||||
@@ -553,7 +558,7 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
'Are you sure to cancel?'.tr,
|
||||
'', () async {
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToPassengerToken(
|
||||
.sendNotificationToDriverMAP(
|
||||
'Driver Cancelled Your Trip',
|
||||
'You will need to pay the cost to the driver, or it will be deducted from your next trip'
|
||||
.tr,
|
||||
|
||||
@@ -330,7 +330,7 @@ class OrderSpeedRequest extends StatelessWidget {
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(
|
||||
link:
|
||||
"${AppLink.endPoint}/rides/updateStausFromSpeed.php",
|
||||
"${AppLink.endPoint}/ride/rides/updateStausFromSpeed.php",
|
||||
payload: {
|
||||
'id': orderRequestController.myList[16],
|
||||
'rideTimeStart': DateTime.now().toString(),
|
||||
@@ -364,6 +364,17 @@ class OrderSpeedRequest extends StatelessWidget {
|
||||
box.read(BoxName.nameDriver).toString(),
|
||||
box.read(BoxName.tokenDriver).toString(),
|
||||
];
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToPassengerToken(
|
||||
'Accepted Ride',
|
||||
'your ride is applied'.tr,
|
||||
// arguments['DriverList'][9].toString(),
|
||||
orderRequestController
|
||||
.arguments['DriverList'][9]
|
||||
.toString(),
|
||||
// box.read(BoxName.tokenDriver).toString(),
|
||||
bodyToPassenger,
|
||||
'start.wav');
|
||||
await CRUD().postFromDialogue(
|
||||
link: AppLink.addDriverOrder,
|
||||
payload: {
|
||||
@@ -388,7 +399,7 @@ class OrderSpeedRequest extends StatelessWidget {
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(
|
||||
link:
|
||||
"${AppLink.endPoint}/driver_order/add.php",
|
||||
"${AppLink.endPoint}/ride/driver_order/add.php",
|
||||
payload: {
|
||||
'driver_id': orderRequestController
|
||||
.myList[6]
|
||||
@@ -400,17 +411,7 @@ class OrderSpeedRequest extends StatelessWidget {
|
||||
'status': 'Apply'
|
||||
});
|
||||
}
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToPassengerToken(
|
||||
'Apply Ride',
|
||||
'your ride is applied'.tr,
|
||||
// arguments['DriverList'][9].toString(),
|
||||
orderRequestController
|
||||
.arguments['DriverList'][9]
|
||||
.toString(),
|
||||
// box.read(BoxName.tokenDriver).toString(),
|
||||
bodyToPassenger,
|
||||
'start.wav');
|
||||
|
||||
Get.back();
|
||||
|
||||
// 'Arguments passed to PassengerLocationMapPage:');
|
||||
|
||||
@@ -1,16 +1,69 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/constant/links.dart';
|
||||
import 'package:SEFER/controller/functions/crud.dart';
|
||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../../main.dart';
|
||||
|
||||
class VipOrderPage extends StatelessWidget {
|
||||
const VipOrderPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Get.put(VipOrderController());
|
||||
return MyScafolld(
|
||||
title: 'VIP Order'.tr,
|
||||
body: [],
|
||||
body: [
|
||||
GetBuilder<VipOrderController>(builder: (vipOrderController) {
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
children: [],
|
||||
));
|
||||
})
|
||||
],
|
||||
isleading: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class VipOrderController extends GetxController {
|
||||
bool isLoading = false;
|
||||
final arguments = Get.arguments;
|
||||
late String body;
|
||||
List tripData = [];
|
||||
var myList;
|
||||
|
||||
initilize() {
|
||||
final myListString = arguments['myListString'];
|
||||
|
||||
if (arguments['DriverList'] == null || arguments['DriverList'].isEmpty) {
|
||||
myList = jsonDecode(myListString);
|
||||
} else {
|
||||
myList = arguments['DriverList'];
|
||||
}
|
||||
|
||||
body = arguments['body'];
|
||||
update();
|
||||
}
|
||||
|
||||
fetchOrder() async {
|
||||
var res = await CRUD().get(link: AppLink.getMishwari, payload: {
|
||||
'driverId': box.read(BoxName.driverID).toString(),
|
||||
});
|
||||
if (res != 'failure') {
|
||||
tripData = jsonDecode(res)['message'];
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
await initilize();
|
||||
fetchOrder();
|
||||
super.onInit();
|
||||
}
|
||||
}
|
||||
|
||||
105
lib/views/home/profile/captains_cars.dart
Normal file
105
lib/views/home/profile/captains_cars.dart
Normal file
@@ -0,0 +1,105 @@
|
||||
import 'package:SEFER/constant/colors.dart';
|
||||
import 'package:SEFER/constant/style.dart';
|
||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||
import 'package:SEFER/views/widgets/mycircular.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_font_icons/flutter_font_icons.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../auth/captin/driver_car_controller.dart';
|
||||
import '../../widgets/elevated_btn.dart';
|
||||
import 'cars_inserting_page.dart';
|
||||
|
||||
class CaptainsCars extends StatelessWidget {
|
||||
const CaptainsCars({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Get.put(DriverCarController());
|
||||
return MyScafolld(
|
||||
title: "Add new car".tr,
|
||||
body: [
|
||||
Column(
|
||||
children: [
|
||||
MyElevatedButton(
|
||||
title: "Add new car".tr,
|
||||
onPressed: () async {
|
||||
Get.to(() => CarsInsertingPage());
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: GetBuilder<DriverCarController>(
|
||||
builder: (controller) {
|
||||
return controller.isLoading
|
||||
? const MyCircularProgressIndicator()
|
||||
: ListView.builder(
|
||||
itemCount: controller.cars.length,
|
||||
itemBuilder: (context, index) {
|
||||
final car = controller.cars[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Card(
|
||||
elevation: 2,
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
Fontisto.car,
|
||||
size: 50,
|
||||
color: Color(int.parse(car['color_hex']
|
||||
.replaceFirst('#', '0xff'))),
|
||||
),
|
||||
title: Text(
|
||||
car['make'],
|
||||
style: AppStyle.title,
|
||||
), // Assuming `make` is a field in each car item
|
||||
subtitle: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
car['model'],
|
||||
style: AppStyle.title,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: AppColor.blueColor)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 4),
|
||||
child: Text(
|
||||
car['car_plate'],
|
||||
style: AppStyle.title,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
car['year'],
|
||||
style: AppStyle.title,
|
||||
),
|
||||
],
|
||||
), // Assuming `model` is a field in each car item
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
onPressed: () {
|
||||
// Add logic here to remove a car
|
||||
controller
|
||||
.removeCar(car['id'].toString());
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
// Add logic to view or edit the car details
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
isleading: true);
|
||||
}
|
||||
}
|
||||
300
lib/views/home/profile/cars_inserting_page.dart
Normal file
300
lib/views/home/profile/cars_inserting_page.dart
Normal file
@@ -0,0 +1,300 @@
|
||||
import 'package:SEFER/splash_screen_page.dart';
|
||||
import 'package:SEFER/views/widgets/elevated_btn.dart';
|
||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../constant/colors.dart';
|
||||
import '../../../constant/links.dart';
|
||||
import '../../../constant/style.dart';
|
||||
import '../../../controller/functions/gemeni.dart';
|
||||
import '../../auth/captin/driver_car_controller.dart';
|
||||
|
||||
class CarsInsertingPage extends StatelessWidget {
|
||||
CarsInsertingPage({super.key});
|
||||
final driverCarController = Get.put(DriverCarController());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Get.put(AI());
|
||||
return MyScafolld(
|
||||
title: 'Insert New Car'.tr,
|
||||
body: [
|
||||
Container(
|
||||
color: AppColor.accentColor.withOpacity(.2),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
egyptCarLicenceFront(),
|
||||
egyptCarLicenceBack(),
|
||||
const SizedBox(height: 10),
|
||||
Text('Please make sure to read the license carefully.'.tr),
|
||||
Text(
|
||||
'If your car license has the new design, upload the front side with two images.'
|
||||
.tr),
|
||||
const SizedBox(height: 10),
|
||||
MyElevatedButton(
|
||||
title: 'Please upload this license.'.tr,
|
||||
onPressed: () {
|
||||
final aiFront =
|
||||
Get.find<AI>().responseIdCardDriverEgyptFront;
|
||||
final aiBack =
|
||||
Get.find<AI>().responseIdCardDriverEgyptBack;
|
||||
driverCarController.addCarsForDrivers(
|
||||
aiBack['vin'].toString(),
|
||||
aiBack['car_plate'].toString(),
|
||||
aiBack['make'].toString(),
|
||||
aiBack['model'].toString(),
|
||||
aiBack['year'].toString(),
|
||||
aiFront['expiration_date'].toString(),
|
||||
aiBack['color'].toString(),
|
||||
aiBack['color_hex'].toString(),
|
||||
aiFront['address'].toString(),
|
||||
aiFront['owner'].toString(),
|
||||
aiBack['registration_date'].toString(),
|
||||
aiBack['displacement'].toString(),
|
||||
aiBack['fuel'].toString(),
|
||||
);
|
||||
})
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
isleading: true);
|
||||
}
|
||||
}
|
||||
|
||||
GetBuilder<AI> egyptCarLicenceFront() {
|
||||
return GetBuilder<AI>(
|
||||
builder: (ai) {
|
||||
if (ai.responseIdCardDriverEgyptFront.isNotEmpty) {
|
||||
// No need to access ai.responseIdCardDriverEgyptBack anymore
|
||||
final licenseExpiryDate = DateTime.parse(
|
||||
ai.responseIdCardDriverEgyptFront['LicenseExpirationDate']);
|
||||
|
||||
// Check if license has expired
|
||||
final today = DateTime.now();
|
||||
final isLicenseExpired = licenseExpiryDate.isBefore(today);
|
||||
|
||||
return Card(
|
||||
elevation: 4.0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text('Vehicle Details Front'.tr,
|
||||
style: AppStyle.headTitle2),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
ai.allMethodForAI(ai.prompts[3]['prompt'].toString(),
|
||||
AppLink.uploadEgypt, 'car_front');
|
||||
},
|
||||
icon: const Icon(Icons.refresh),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
const Divider(color: AppColor.accentColor),
|
||||
const SizedBox(height: 8.0),
|
||||
// Removed Make, Model, etc. as they are not available
|
||||
|
||||
Text(
|
||||
'${'Plate Number'.tr}: ${ai.responseIdCardDriverEgyptFront['car_plate']}',
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
'${'Owner Name'.tr}: ${ai.responseIdCardDriverEgyptFront['owner']}',
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
'${'Address'.tr}: ${ai.responseIdCardDriverEgyptFront['address']}',
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${'License Expiry Date'.tr}: ${licenseExpiryDate.toString().substring(0, 10)}',
|
||||
style: TextStyle(
|
||||
color: isLicenseExpired ? Colors.red : Colors.green,
|
||||
),
|
||||
),
|
||||
// Removed Fuel as it's not available
|
||||
],
|
||||
),
|
||||
// Removed Inspection Date as it's not available
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Card(
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
ai.allMethodForAINewCar(ai.prompts[3]['prompt'].toString(),
|
||||
AppLink.uploadEgypt, 'car_front', 'carId'); //todo
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/3.png',
|
||||
height: Get.height * .25,
|
||||
width: double.maxFinite,
|
||||
fit: BoxFit.fitHeight,
|
||||
),
|
||||
Text(
|
||||
'Capture an Image of Your car license front '.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
GetBuilder<AI> egyptCarLicenceBack() {
|
||||
return GetBuilder<AI>(
|
||||
builder: (ai) {
|
||||
if (ai.responseIdCardDriverEgyptBack.isNotEmpty) {
|
||||
// Get the tax expiry date from the response
|
||||
final taxExpiryDate =
|
||||
ai.responseIdCardDriverEgyptBack['tax_expiry'].toString();
|
||||
// final displacement = ai.responseIdCardDriverEgyptBack['displacement'];
|
||||
// if (int.parse(displacement) < 1000) {}
|
||||
// Get the inspection date from the response
|
||||
final inspectionDate =
|
||||
ai.responseIdCardDriverEgyptBack['inspection_date'].toString();
|
||||
final year = int.parse(inspectionDate.toString().split('-')[0]);
|
||||
|
||||
// Set inspectionDateTime to December 31st of the given year
|
||||
final inspectionDateTime = DateTime(year, 12, 31);
|
||||
String carBackLicenseExpired =
|
||||
inspectionDateTime.toString().split(' ')[0];
|
||||
// Get the current date
|
||||
final today = DateTime.now();
|
||||
|
||||
// Try parsing the tax expiry date. If it fails, set it to null.
|
||||
final taxExpiryDateTime = DateTime.tryParse(taxExpiryDate ?? '');
|
||||
final isExpired =
|
||||
taxExpiryDateTime != null && taxExpiryDateTime.isBefore(today);
|
||||
// Check if the inspection date is before today
|
||||
bool isInspectionExpired = inspectionDateTime.isBefore(today);
|
||||
|
||||
return Card(
|
||||
elevation: 4.0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Vehicle Details Back'.tr, style: AppStyle.headTitle2),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
ai.allMethodForAI(ai.prompts[4]['prompt'].toString(),
|
||||
AppLink.uploadEgypt, 'car_back');
|
||||
},
|
||||
icon: const Icon(Icons.refresh),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
const Divider(color: AppColor.accentColor),
|
||||
const SizedBox(height: 8.0),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${'Make'.tr}: ${ai.responseIdCardDriverEgyptBack['make']}'),
|
||||
Text(
|
||||
'${'Model'.tr}: ${ai.responseIdCardDriverEgyptBack['model']}'),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${'Year'.tr}: ${ai.responseIdCardDriverEgyptBack['year']}'),
|
||||
Text(
|
||||
'${'Chassis'.tr}: ${ai.responseIdCardDriverEgyptBack['chassis']}'),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${'Color'.tr}: ${ai.responseIdCardDriverEgyptBack['color']}'),
|
||||
Text(
|
||||
'${'Displacement'.tr}: ${ai.responseIdCardDriverEgyptBack['displacement']} cc'),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
'${'Fuel'.tr}: ${ai.responseIdCardDriverEgyptBack['fuel']}'),
|
||||
const SizedBox(height: 8.0),
|
||||
if (taxExpiryDateTime != null)
|
||||
Text(
|
||||
'${'Tax Expiry Date'.tr}: $taxExpiryDate',
|
||||
style: TextStyle(
|
||||
color: isExpired ? Colors.red : Colors.green,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${'Inspection Date'.tr}: $carBackLicenseExpired',
|
||||
style: TextStyle(
|
||||
color: isInspectionExpired ? Colors.red : Colors.green,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Card(
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
ai.allMethodForAI(ai.prompts[4]['prompt'].toString(),
|
||||
AppLink.uploadEgypt, 'car_back');
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/4.png',
|
||||
height: Get.height * .25,
|
||||
width: double.maxFinite,
|
||||
fit: BoxFit.fitHeight,
|
||||
),
|
||||
Text(
|
||||
'Capture an Image of Your car license back'.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:SEFER/constant/style.dart';
|
||||
import 'package:SEFER/controller/home/payment/captain_wallet_controller.dart';
|
||||
import 'package:SEFER/views/widgets/elevated_btn.dart';
|
||||
import 'package:SEFER/views/widgets/mycircular.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -7,6 +8,7 @@ import 'package:SEFER/controller/profile/captain_profile_controller.dart';
|
||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||
|
||||
import '../my_wallet/walet_captain.dart';
|
||||
import 'captains_cars.dart';
|
||||
|
||||
class ProfileCaptain extends StatelessWidget {
|
||||
ProfileCaptain({super.key});
|
||||
@@ -41,6 +43,15 @@ class ProfileCaptain extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
MyElevatedButton(
|
||||
title: 'Show my Cars'.tr,
|
||||
onPressed: () async {
|
||||
Get.to(() => CaptainsCars());
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * .8,
|
||||
child: DriverProfileCard(
|
||||
|
||||
Reference in New Issue
Block a user